从无到有的一个漏洞

0x00 关于整个流程

这是一个通过扫描端口发现的一个应用。

点击登陆时,发现没有数据包来往,查看控制台发现,提示IsEmpty没有定义;

此时我内心感觉这里不出意外的话,肯定是有问题的。于是,跟进。

发现IsEmpty函数是用来校验数据是否输入的一个函数,无关紧要。

起初以为可能在某个地方没有引进,打算手动引进的,但是并没有在任何一个地方引入。

我随便定义了一个IsEmpty函数,再次点击登录时,发现出现了新的问题;跟进。

应该是对密码进行相应检测或者转换的一个函数,没有引入该函数,先忽略掉;跟进。

直接看后面的代码,使用了XMLHttpRequest的方式发送数据:

logonForm.txt_paritybit.value是图形验证码的值

logonForm.txt_user.value是用户名的值

logonForm.hid_pwd.value是密码的值

v_flag是是否记住密码的值,不记住是0,记住是1

get_XMLHttp()函数也丢了,根据后面的方法推测是XMLHttpRequest函数的一个封装。

手动设置参数,发送请求

顺利抓到数据包

而通过后面的代码也可以看到,是通过前端来刷新验证码,所以可以爆破

通过JS代码可以知道相应包返回数字4时表示校验通过,然后跳转到主页面。

尝试未授权访问,失败。

尝试爆破,失败。

添加单引号,发现有戏.....

...

探测万能密码...失败

各种探测....

直接上POC,探测所需信息。

先获取图形验证码,然后手动输入验证码的值,然后进行探测

数据库名称:

0x01 关于Payload

decode函数有很多种功能,在这里我们主要用到它可以比较字符串的功能。类似if-then语句。

DECODE(expr, search, result
             [, search, result ]...
       [, default ]
      )

DECODE函数会依次比较exprsearch的值,如果expr等于search的值,那么DECODE函数将会返回search后面对应的result的值。如果到最后也没有匹配成功,那么便会返回最后面的default

类似 C++ 里面的switch语句。

该Payload的核心思想便是,根据表达式与search的值是否匹配,来决定是否执行高耗时SQL操作。

例如:(select count(*) from all_objects),对数据库中大量数据进行查询或其他处理的操作,这样的操作会耗费较多的时间,然后通过这个方式来获取数据。这种方式也适用于其他数据库。

另一个需要注意的是:在Oracle中查询表名等这种存在多记录的结果集时,通过不断的排除前面获取的结果,来实现检索所有记录的效果。可以使用
类似where table_name <>'table_name'这样的查询来排除前面获取的结果。

0x02 参考文章

Thinking师傅的Paper:

https://www.freebuf.com/column/146464.html

Pentestmonkey的cheat sheet:

http://pentestmonkey.net/cheat-sheet/sql-injection/oracle-sql-injection-cheat-sheet

Oracle官方文档:

https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions040.htm