自以为sql注入掌握的还是比较系统的,然而,做了这些题之后才发现,大千世界无奇不有,真是各种猥琐的思路...还是要多学习学习姿势跟上节奏呀
登录一下好吗??
http://ctf5.shiyanbar.com/web/wonderkun/web/index.html
试了一下发现他过滤了/ or union select - #
虽然and ‘ " = + %没有被过滤,但用%0b和%23都没效,于是还在想这是用了多麻烦的WAF,越想越复杂我竟然还去用xss,真是跑题了...
然而最后的payload是这样的...跪了,果然题刷的太少吗
who are you?
http://ctf5.shiyanbar.com/web/wonderkun/index.php
进入这个页面,发现他获取了我的ip,首先想到的就是user agent注入,用updatexml试一下,什么错的没有报...看来这个思路不行
百度了才知道这是一道伪造IP的题,相关知识可以看这里:http://www.cnblogs.com/x2048/articles/1794020.html
总结下,伪造IP的HTTP头都有这些:
X-Forwarded-For Client-IP x-remote-IP x-originating-IP x-remote-addr
一般用的最多的就是前两个,这里我们用X-Forwarded-For来伪造
但是很奇怪,不管构造的是什么语句,都会返回到页面,看了下别人的writeup发现,他的后台处理过程大致是这样的,首先获取到HTTP-X-Forwarded-For,对他进行字符串的处理,只截取逗号前的内容,然后直接将其输出到页面,再插入到数据库,但应该没有对插入结果做处理,即没有输出数据库的报错仅输出空,所以想从数据库的报错获取信息应该是不行了,返回页面也是不具判断性的,那么可以考虑时间型的盲注
这里解决的方法可以有三种:
1、写个盲注脚本跑
这是跑出来的库名:
表名:
字段:
于是,我们知道了flag存储在flag表的flag字符里,且长度为32,接下来直接跑就行了
2、用burp进行时间盲注
3、用sqlmap进行http头的盲注
然后,要注意的是跑出来的结果要加在ctf{xxx}里....被坑的很惨,跑出来flag一直提交不对,最后发现花括号用的中文字符输入的...
因缺思汀的绕过
http://ctf5.shiyanbar.com/web/pcat/index.php
查看网页的源码,发现登录的源码路径是source.txt
于是拿到源码如下:
1 <?php 2 error_reporting(0); 3 4 if (!isset($_POST[‘uname‘]) || !isset($_POST[‘pwd‘])) { 5 echo ‘<form action="" method="post">‘."<br/>"; 6 echo ‘<input name="uname" type="text"/>‘."<br/>"; 7 echo ‘<input name="pwd" type="text"/>‘."<br/>"; 8 echo ‘<input type="submit" />‘."<br/>"; 9 echo ‘</form>‘."<br/>"; 10 echo ‘<!--source: source.txt-->‘."<br/>"; 11 die; 12 } 13 14 function AttackFilter($StrKey,$StrValue,$ArrReq){ 15 if (is_array($StrValue)){ 16 $StrValue=implode($StrValue); 17 } 18 if (preg_match("/".$ArrReq."/is",$StrValue)==1){ 19 print "姘村彲杞借垷锛屼害鍙禌鑹囷紒"; 20 exit(); 21 } 22 } 23 24 $filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)"; 25 foreach($_POST as $key=>$value){ 26 AttackFilter($key,$value,$filter); 27 } 28 29 $con = mysql_connect("XXXXXX","XXXXXX","XXXXXX"); 30 if (!$con){ 31 die(‘Could not connect: ‘ . mysql_error()); 32 } 33 $db="XXXXXX"; 34 mysql_select_db($db, $con); 35 $sql="SELECT * FROM interest WHERE uname = ‘{$_POST[‘uname‘]}‘"; 36 $query = mysql_query($sql); 37 if (mysql_num_rows($query) == 1) { 38 $key = mysql_fetch_array($query); 39 if($key[‘pwd‘] == $_POST[‘pwd‘]) { 40 print "CTF{XXXXXX}"; 41 }else{ 42 print "浜﹀彲璧涜墖锛?"; 43 } 44 }else{ 45 print "涓€棰楄禌鑹囷紒"; 46 } 47 mysql_close($con); 48 ?>
从源码中可以知道这些全都被过滤了:and|select|from|where|union|join|sleep|benchmark|,|\(|\)
并且数据库中只有一条数据
if (mysql_num_rows($query) == 1) {
最核心的部分是这里
$sql="SELECT * FROM interest WHERE uname = ‘{$_POST[‘uname‘]}‘";
大致的执行过程是先将用户输入的uname作为查询条件,在数据库中查询uname和pwd,然后将查询到的pwd与用户输入的pwd进行比较,内容一致才输出flag
这里的思路是,利用group by pwd with rollup在查询中的一个特点,他可以返回pwd所在的那一条记录,通过limit控制返回哪一条,因此他不可以返回多条,一旦返回2条及以上,pwd就会为空,但同一条记录中的其他字段则是正常的
那么利用这一点令查询结果为空,我们输入的pwd也为空值,则构成了if(null == null)为true
简单的sql注入之三
http://ctf5.shiyanbar.com/web/index_3.php
看源码,是一个用get方式传参数id的查询,于是手工注入一波,发现单引号引起报错,加上注释后回显正常,id在1~3的范围都可以正常回显“Hello!”,否则返回空,尝试逻辑运算,可以正常返回,那这就很好办了
然后,我就开始入了手注的坑...
首先来试试有几个字段
2报错了,说明只查询出一个字段,那么用union试试
没有想要的结果回显,很奇怪,看来这个Hello不是输出的位置,应该是后台在获取到id的值后,执行sql语句,如果存在查询的结果,那么就输出Hello,但不输出结果
如果是这样的话,那么只能从报错回显入手了,先试试双注入
很尴尬,做了报错处理?那试试xpath的报错
还是不行...好吧,报错这条路也被堵了,那就考虑盲注吧
,
根据上面页面中的不同返回,我们可以写一个bool型的盲注脚本来爆数据库,当然也可以用burp搞定
这里偷个懒,因为已经知道ctf的套路了,所以可以直接来猜表名和字段
参考文献:
http://www.jianshu.com/p/5d34b3722128