专栏名称: 利刃信安
利刃信安
目录
相关文章推荐
Linux就该这么学  ·  告别繁琐操作!Linux ... ·  19 小时前  
Linux就该这么学  ·  官宣:这所高校禁用 DeepSeek ·  19 小时前  
Linux就该这么学  ·  成为 Linux ... ·  昨天  
Linux爱好者  ·  AI 正在培养一代 “文盲程序员” ·  4 天前  
51好读  ›  专栏  ›  利刃信安

神奇的order by注入

利刃信安  · 公众号  ·  · 2024-12-03 12:11

正文

一、    判断order by注入

当你看到一个查询结果有排序小箭头时,要额外注意,这可能一个SORT(排序)键值,抓包后可能是这样的。

那么后端SQL语句就差不多类似

select * from table where id =1 order by zzf desc;


这种地方在java-mybatis环境中容易引发注入问题,原因很简单,在mybatis中order by ${sort}传的是列名不能用#{},因此需要额外用白名单处理。有的开发没处理就有注入了。
同理,table_name/column_name这种地方也容易产生SQL注入。
还有一种是like,like是可以用#{}的,但部分开发不会写like的#{}就用的${}。不过like注入比比order by注入少很多。

如何判断这里有order by注入呢?很简单,原理跟最基础的联合注入利用order by爆破字段数量是一样的。
order by (1)  不报错
order by (10000000) 报错

这样就基本能判断出来这里有order by注入了。
当然也可以直接order by sleep(1)。

二、    order by注入利用

一个SQL注入的标准是至少注出user()出来,当然现代WAF/框架之狠,直接给你干没select,也很难注出什么有效数据(不绝对,部分情况除外)。
order by怎么注user()呢?正常有三种方法利用。

1,时间盲注
能用sleep(1)就能构造最简单的基于时间延迟的布尔盲注。

select * from user  order by if(1=1,sleep(1),1);

但它有个很大的缺点,就是有几条数据就重复几次sleep(1)。
那么另外一个常用的benchmark(50000000,sha(1))能用吗?答案是不行,原因后面就知道了。



2,报错注入
经典的updatexml()

select * from user  order by updatexml(1,concat(0x7e,(select user()),0x7e),1);

报错注入有个最特殊的地方,它是唯一查询内容会空,依旧可以order by注入的方式。

缺点就是生产环境往往关闭了报错信息。

3,用列名构造基于排序差异的布尔盲注

select * from user  order by if(1=1,id,email);

但前提是知道列名,以及列名确实能够产生排序不同。
如果不知道列名,用数字代替是不行的。

4,用rand构造基于排序差异布尔的盲注
rand是根据种子返回一个0-1的随机小数,rand(1=1)和rand(1=2)在大量数据时大概率会导致排序不同 ,因此可以构造基于排序不同的布尔条件。

select * from user  order by rand(1=1);

显然基于排序差异的布尔盲注,如果碰到没有排序差异的查询结果,比如就一条数据,就没办法了。



三、    基于报错的布尔盲注

在有些注入中,表里没有数据,或者查询出来的数据不展示在web,又或者是增删改的SQL注入。这个时候可能只能时间盲注,但通常可以将这个时间盲注升级成基于报错的布尔盲注。
就是构造出一个条件,为true时执行错误的语句导致服务端抛错,为false时执行正确的语句,即使服务端不返回任何东西或者返回随机的东西,只要不抛错,即可构造布尔条件。
直观点就是这样的SQL语句。

select * from user where id =1 and if(1=1,exp(9999999),1);

用case when代替if

select * from user where id =1 and (case when 1=1 then exp(9999999) else 1 end);


exp(9999999)这个报错行为,代替如下。
cot(1-(1=1))
pow(1+(1=1),99999)
还有另外一种在其他数据库也能构造出来的报错行为,那就是联合查询使子查询有两条数据。

select * from user where id =1 and (case when 1=1 then (select 1 union select 2) else 1 end);

基于报错的布尔盲注弥补了基于排序差异的布尔盲注的不足,那么order by能用它吗?
答案是能用一部分,也就是联合查询那部分。

select * from user where 1=1  order by (case when 1=1 then (select 1 union select 2) else 1 end);

为什么if+exp不能用呢?

答案是order by正常情况下根本不会去执行方法,甚至连基础的运算都不支持。
如下图,order by (2-1)的排序结果是跟没有order by或者order by null的结果是一样的。

什么情况下会执行运算呢?前面已经说了很多种情况了,比如sleep,比如联合查询。
但这里面还要分情况,那就是运算的先后顺序,比如常用的substr(),它结合exp(9999999)也会导致报错,但却是恒定报错。

select * from user where 1=1  order by if(1=1,substr(1,exp(9999999)),1);

也就是说,先运算exp(),再运算substr(),最后运算if(1=1)。
而如果是sleep(exp(9999999)),运算顺序就变化了。

select






请到「今天看啥」查看全文