xp_cmdshell (Transact-SQL)
适用范围:SQL Server
生成 Windows 命令 shell 并以字符串的形式传递以便执行。 任何输出都作为文本的行返回。
语法
xp_cmdshell { 'command_string' } [ , NO_OUTPUT ]
参数
“command_string”
包含要传递给操作系统的命令的字符串。 command_string为 varchar(8000) 或 nvarchar(4000),没有默认值。 command_string 不能包含多个双引号集。 如果文件路径或command_string中引用的程序名称中存在任何空格,则需要单对引号。 如果不方便使用内含的空格,则可考虑使用 FAT 8.3 文件名作为解决方法。
NO_ OUTPUT
可选参数,指定不应将输出返回到客户端。
返回代码值
0
(成功)或 1
(失败)。
结果集
执行以下 xp_cmdshell
语句将返回当前目录的目录列表。
EXEC xp_cmdshell 'dir *.exe';
GO
行在 nvarchar(255) 列中返回。 NO_OUTPUT
如果使用此选项,则仅返回以下输出:
The command(s) completed successfully.
注解
生成的 xp_cmdshell
Windows 进程具有与 SQL Server 服务帐户相同的安全权限。
注意
xp_cmdshell
是一项功能强大的功能,默认情况下处于禁用状态。 xp_cmdshell
可以使用基于策略的管理或执行 sp_configure
来启用和禁用。 有关详细信息,请参阅 Surface area 配置和xp_cmdshell(服务器配置选项)。 使用 xp_cmdshell
可以触发安全审核工具。
xp_cmdshell
同步操作。 在命令 shell 命令完成之前,控件不会返回到调用方。 如果在 xp_cmdshell
批处理中执行并返回错误,则批处理将失败。
xp_cmdshell代理帐户
当用户调用不是 sysadmin 固定服务器角色的成员时,xp_cmdshell
请使用名为 ##xp_cmdshell_proxy_account## 的凭据中的帐户名和密码连接到 Windows。 如果此代理凭据不存在, xp_cmdshell
则失败。
可以通过执行 sp_xp_cmdshell_proxy_account
代理帐户凭据来创建。 此存储过程将 Windows 用户名和密码作为参数使用。 例如,以下命令为具有 Windows 密码 SHIPPING\KobeR
的 Windows 域用户 sdfh%dkc93vcMt0
创建代理凭据。
EXEC sp_xp_cmdshell_proxy_account 'SHIPPING\KobeR', 'sdfh%dkc93vcMt0';
有关详细信息,请参阅 sp_xp_cmdshell_proxy_account。
权限
由于恶意用户有时尝试使用 xp_cmdshell
提升其权限, xp_cmdshell
因此默认处于禁用状态。 使用 sp_configure
或 基于策略的管理 来启用它。 有关详细信息,请参阅 xp_cmdshell 服务器配置选项。
首次启用时, xp_cmdshell
需要 CONTROL SERVER 权限才能执行,并且创建的 xp_cmdshell
Windows 进程与 SQL Server 服务帐户具有相同的安全上下文。 SQL Server 服务帐户通常具有的权限比由创建 xp_cmdshell
的进程执行的工作所需的权限多。 为了增强安全性,应将访问 xp_cmdshell
限制为高特权用户。
若要允许非管理员使用 xp_cmdshell
,并允许 SQL Server 使用特权较低的帐户的安全令牌创建子进程,请执行以下步骤:
使用进程要求的最小特权创建并自定义一个 Windows 本地用户帐户或一个域帐户。
使用
sp_xp_cmdshell_proxy_account
系统过程进行配置xp_cmdshell
以使用该最低特权帐户。注意
还可以使用 SQL Server Management Studio 配置此代理帐户,方法是右键单击对象资源管理器中的服务器名称上的“属性”,然后查看“服务器代理帐户”部分的“安全”选项卡。
在 Management Studio 中,使用
master
数据库执行以下 Transact-SQL 语句,使特定的非 sysadmin 用户能够执行xp_cmdshell
。 指定的用户必须存在于master
数据库中。GRANT exec ON xp_cmdshell TO N'<some_user>';
现在,非管理员可以使用你配置的代理帐户的权限启动操作系统进程 xp_cmdshell
,并且这些进程使用你配置的权限运行。 具有 CONTROL SERVER 权限的用户(sysadmin 固定服务器角色的成员)继续接收由其xp_cmdshell
启动的子进程的 SQL Server 服务帐户的权限。
若要确定在启动操作系统进程时使用的 xp_cmdshell
Windows 帐户,请执行以下语句:
EXEC xp_cmdshell 'whoami.exe';
若要确定另一个登录名的安全上下文,请执行以下 Transact-SQL 代码:
EXEC AS LOGIN = '<other_login>';
GO
xp_cmdshell 'whoami.exe';
REVERT;
示例
A. 返回可执行文件列表
以下示例显示执行目录命令的 xp_cmdshell
扩展存储过程。
EXEC master..xp_cmdshell 'dir *.exe'
B. 不返回输出
以下示例使用 xp_cmdshell
执行命令字符串,且不向客户端返回输出。
USE master;
EXEC xp_cmdshell 'copy c:\SQLbcks\AdvWorks.bck
\\server2\backups\SQLbcks', NO_OUTPUT;
GO
°C 使用返回状态
在以下示例中 xp_cmdshell
,扩展存储过程还建议返回状态。 返回代码值存储在变量 @result
中。
DECLARE @result INT;
EXEC @result = xp_cmdshell 'dir *.exe';
IF (@result = 0)
PRINT 'Success'
ELSE
PRINT 'Failure';
D. 将变量内容写入文件
以下示例将 @var
变量的内容写入当前服务器目录下名为 var_out.txt
的文件中。
DECLARE @cmd SYSNAME,
@var SYSNAME;
SET @var = 'Hello world';
SET @cmd = 'echo ' + @var + ' > var_out.txt';
EXEC master..xp_cmdshell @cmd;
E. 将命令的结果捕获到文件
以下示例将当前目录的内容写入当前服务器目录下名为 dir_out.txt
的文件中。
DECLARE @cmd SYSNAME,
@var SYSNAME;
SET @var = 'dir /p';
SET @cmd = @var + ' > dir_out.txt';
EXEC master..xp_cmdshell @cmd;