CTF解题笔记

本文介绍两种SQL注入技巧:一是利用group by pwd with rollup绕过SQL关键字过滤;二是利用弱类型比较特性绕过敏感符号过滤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

只能说坑。。。

要不是看了大神的write up 我觉得不会想到。。。


http://blog.youkuaiyun.com/qq_34841823/article/details/54287419


1.因缺思汀的绕过

解题路径:http://ctf5.shiyanbar.com/web/pcat/index.php

打开后是一个登录框类似的东西,查看页面源码可以看到有source:source.txt的字样


打开连接:http://ctf5.shiyanbar.com/web/pcat/source.txt

可以看到登录的PHP逻辑:

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:18px;"><?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. ?></span>  

可以看到,这里面有SQL的一个过滤器,把一些sql的关键字例如benchmark,join等都过滤了

而且sql查询语句是:

[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:18px;">SELECT * FROM interest WHERE uname = '{$_POST['uname']}  
  2. </span>  
又由:
[php]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:18px;">mysql_num_rows($query) == 1</span>  
这个判断可以得知数据库中的记录就只有一条,这部分逻辑大概就是然后通过提交的uname查询出结果,如果结果只有一条则继续,如果查询结果中的pwd字段和post过去的key值相同,则给出flag。
这时就要用到注入的一个小技巧,我们使用group by pwd with rollup 来在查询结果后加一行,并且这一行pwd字段的值为NULL
在mysql官方文档中是这样描述rollup函数的:


大概的意思就是在GROUP BY子句中使用WITH ROLLUP会在数据库中加入一行用来计算总数,ROLLUP子句的更加详细的用法,可以参考mysql的官方文档,此处就不多做赘述了。
再结合limit和offset就可以写出一个payload
即:输入的用户名为:' 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  (从第二行开始查询)
#注释
此时密码只要为空即可查询成功




2.登陆一下好吗??
解题路径:http://ctf5.shiyanbar.com/web/wonderkun/web/index.html
题目说这个过滤了很多敏感符号,于是先构造一下常用的payload:' or 1=1 #

发现or 和 #都被过滤掉了,通过测试发现--也被过滤了,看起来是很吓人,但是不过幸好'没有被过滤,于是构造payload:
username = travis'='
password=travis'='

这个时候成果获得flag
为什么这样可以绕过呢?
当提交username=travis'='&password=travis'='
语句会变成如下:
select * from user where username='travis'='' and password='travis'=''
这时候还不够清晰,我提取前一段判断出来(后面的同样道理)
username='travis'=''
这是有2个等号,然后计算顺序从左到右,
先计算username='travis' 一般数据库里不可能有我这个小名(若有,你就换一个字符串),所以这里返回值为0(相当于false)
然后0='' 这个结果呢?看到这里估计你也懂了,就是返回1(相当于true)

所以这样的注入相当于
select * from user where 1 and 1
也等于 select * from user
(这题只有筛选出来的结果有3个以上才会显示flag,没有就一直说“对不起,没有此用户!!”)

面那个比较是弱类型的比较,
以下情况都会为true
1='1'
1='1.0'
1='1后接字母(再后面有数字也可以)'
0='除了非0数字开头的字符串'
(总体上只要前面达成0的话,要使语句为true很简单,所以这题的万能密码只要按照我上面的法子去写一大把)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值