Oracle注入简单挖掘—Order By排序

  • A+

关于Order By:

在SQL语言中,Order By语句主要用于对结果集进行排序。既然跟数据库交互有关,自然而然就会想到SQL注入的防护问题,第一时间想到的方案就是预编译了。但是采用预编译执行SQL语句传入的参数不能作为SQL语句的一部分,那么Order By后的字段名、或者是descasc也不能预编译处理,那么也就是说Order By场景的排序规则还是只能使用拼接,这时候如果在开发阶段没有处理好,那么就很可能导致SQL注入问题了。排序也一直是注入的重灾区。

挖掘思路

首先看一个业务环境,很正常的一个排序功能:

image.png

相关的数据包如下:

以姓名排序,字段为USER_NAME:

image.png

以id号排序,字段为USER_ID:

image.png

结合上述测试环境,下面说几个Order By注入的判断方法:

(1)利用Order By的性质:

手工注入的时候,经常会使用Order By来判断当前数据库表的列数,这里在寻找Order By注入的时候同样适用:

若Order By后对应参数的值可控的话,可以尝试写入对应数字进行判断,若超出了当前SQL语句查询的列数,则会触发SQLerror(实际情况可能开发人员做了对应的友好性处理,返回数据为null或者返回通用报错页面):

这里直接把排序字段修改为100(远超于实际表里的列数),触发SQL报错:

image.png

修改为1的时候,正常返回:

image.png

这里初步可以判断存在SQL注入了。

(2)好用的1/0:

Mysql数据库中1/0是warning,还是可以成功返回内容的:

image.png

但是在Oracle数据库中,1/0会触发error,并不能返回查询结果:

这个特性在判断OracleSQL注入中是一个利器。

直接在排序字段后追加1/1和1/0,返回的结果应该是不一样的:

1/1时是可以正常返回查询结果的:

image.png

1/0成功触发报错:

image.png

这里基本可以判断注入点存在了,既然1/不同内容有不同的返回,那么就可以尝试构造1/(casewhen 1=1 then 1 else 0 end)这样的条件判断进行注入利用了。

(3)基于报错函数注入:

也可以看看Sqlmap的Payload,主要还是以基于报错为主:

也是一个很不错的思路,类似boolean的一个条件判断了,当报错触发的时候返回错误信息或者开发自定义的页面(null),否则正常返回,两者形成对比:

image.png

举个例子:利用decode和ordsys.ord_dicom.getmappingxpath()构造一个报错逻辑,当均为1时,触发报错:

image.png

当不一致时,正常返回:

image.png

(4)利用带外注入:

利用Oracle发送HTTP和DNS请求,并将查询结果带到请求中,然后监测外网服务器的HTTP和DNS日志,通过这种方式判断函数是否执行,进行盲注:

主要是两个函数:

使用utl_http.request()向外网主机发送http请求

具体效果:

image.png

image.png

使用utl_inaddr.get_host_address()进行dns解析

具体效果:

image.png

image.png

这里如果可以成功带外注入的话,深入利用获取数据就简单了,可以将查询的结果拼接到域名下请求即可:

image.png

请求后到dnslog里就可以看到刚刚拼接查询的结果了:

image.png

(5)利用decode函数进行条件排序:

一般在实际业务里,可以利用decode()可以根据字段内容进行指定顺序的排序.

Example:

例如想以test,ceshi,tkswifty的顺序进行排序:decode(字段名,想要指定顺序的字段内容)

image.png

那么在有排序回显的情况下(主要是要知道字段名和数据的值)就可以利用decode()函数进行注入判断了:

正常情况下,排序查询结果如下,是有数据回显的:

image.png

那么此时如果想把tkswifty内容排到第一行,可以尝试写入Payload:decode(列名,指定内容,1),可以看到tkswifty那一行成功排到第一行了:

image.png

通过修改对tkswifty进行字符拼接,通过’||’的特性插入对应的expression,即可深入利用了:

Example:

image.png

此外,instr()、casewhen也能达到类似的效果。

(6)基于时间盲注:

Oracle的时间盲注通常使用DBMS_PIPE.RECEIVE_MESSAGE(),该函数将为从RDS管道返回的数据等待对应的时间。

正常情况下服务器查询并返回的时间为131millis:

image.png

尝试在排序字段后写入DBMS_PIPE.receive_message('tkswifty',1),可以看到服务器查询并返回的时间变成了5131millis了,这里即可证明注入点存在了:

image.png

深入利用的话,也只需要在延迟时间里利用算数运算,加入对应的逻辑即可,例如DBMS_PIPE.receive_message('tkswifty',1-(casewhen 1=1 then 1 else 0 end)),当1=1时,正常返回不延迟,1=0时,产生延迟。

修复建议

1、通过过滤器拦截器的方式对输入进行过滤。

2、使用间接对象引用的方式,在前端传递引用数字或者字符串等,用于与后端做类似数组映射(类似HashMap的结构),避免直接引用带来危害。

具体实例

通过点击页面按钮,传递sort参数,sort参数的值对应1,2,3,4……,传递到后端后找到对应的name,distance,ranking….,找到对应的字段后调用对应的SQL语句执行。

如果用户尝试注入1,1/0,传递到后端后找不到对应的字段。找不到对应的字段也就不会调用对应的SQL语句执行。

image.png

总结

可以利用Order By的特殊性尝试一些注入的挖掘,主要还是判断注入点,注入点判断出来了,再慢慢琢磨怎么获取数据进一步利用。

image.png

相关推荐: 浅谈短信业务中的格式化漏洞

关于短信业务   短信服务(Short Message Service)是指通过调用短信发送API,将指定短信内容发送给指定手机用户。短信的内容多用于企业向用户传递验证码、系统通知、会员服务等信息。大型网站的业务实现中都提供有手机短信业务功…