发新话题
打印

[翻译]A New Class of Attack in Oracle

[翻译]A New Class of Attack in Oracle

译文作者:[E.S.T] 冰血封情
原文作者:David Litchfield (davidl@ngssoftware.com
信息来源:邪恶八进制信息安全团队(www.eviloctal.com

概览
在Oracle数据库里,DBMS_SQL调用一个曾经存在却已被关闭的指针的误操作,或者在异常事件中清理一个打开的指针都回导致安全漏洞。
如果问题指针是较高权限的代码创建并挂起,那么很有可能低权限用户可以在程序逻辑外清理或使用这个指针,这样就会导致数据暴露。

确保指针在使用后被关闭,显然是一个良好的编程习惯,可惜正如我们所了解到的那样,好的编程习惯可不流行。

本篇文档将详细为大家解释为什么开发者应该确保这些指针在使用后正确关闭,尤其在异常事件中。

这个类型的安全问题同样也会影响其他句柄,比如那些由UTL_FILE返回的,并可能影响其他RDBMS的句柄。

关于这个漏洞
来看看下面这段代码:



上面那段代码根据给定的USERNAME,在USERNAME是SYS的用户以外查询用户名对应的密码HASH(哈希),并将它与0123456789ABCDEF进行对比。
任何时候,密码HASH都不能暴露给执行这段代码的用户。

这段程序显然最多也就只能当作一个演示,其他的一无是处。

这段程序使用DBMS_SQL来查找密码。当你使用DBMS_SQL来运行一个查询的时候,你首先使用OPEN_CURSOR函数开启了一个指针。
这个指针仅仅是一个数字,本质上是指向一块保存了有关这个指针项目的特定内存区域,比如,查询、查询变量和许可。

OPEN_CURSOR返回这个指针后,指针会一直驻留,直到被明确关闭或者SQL会话结束。
好,咱们现在回到PWD_COMPARE这个例子。当查询已经执行后,指针应该由CLOSE_CURSOR来结束。

注意,在上面那段代码中,并没有异常挂起代码用来应对指针在关闭前出错的情况,因此一旦出错指针就会“吊起”。
这将会捅出一个安全漏洞。我们来再看细致点。

首先,创建一段类似上面SYS那样的程序,并且授权给PUBLIC执行:



现在我们用低权限用户执行这段代码,不过我们现在要通过传递给它一个超长字符串来触发异常。



异常报错的情况如下。



这个会话现在有一个野指针,很有可能被攻击者利用。
通过PWD_COMPARE的报错信息,我们了解到这个指针目前有3个值。顺便说一下,就算没看见这个“3”,攻击者照样可以通过从1到N循的猜这个野指针的值,直到猜到为止。

当攻击者发现了这个野指针,他们可以再利用它。换句话会所,他们可以通过查询重新绑定USERNAME,如果他们愿意这样选择,这回完全可以用SYS。
如果攻击者这样做了,他们就可以重新执行查询并且一点点的析取数据,最后猜到用户SYS的密码HASH。



这段代码给出如下输出:
“PWD: D3AAEDA7EDA1B4AC”

至此,攻击者已经获得了SYS密码HASH的访问。简而言之,要招致这种攻击,目标就是利用一个指针。
攻击者必须首先定位漏洞代码,也就是捕获到一个查询数据库的进程或函数调用了DBMS_SQL并且没有关闭指针的异常错误。
然后触发异常,第三步,找到那个野指针。只要攻击者成功了,他们可以通过变化变量,重新创建新的查询,比如,绑定新的变量。

威胁程度
这种缺陷将会影响到数据的保密性。攻击者可以获得一些他们正常情况下无法访问的数据。
然而,有一些限制因素,攻击者会受到高权限代码传递的查询的限制。
要有可能对指针做一个新的查询,则必须依赖攻击者的权限,如果权限不够,则根本不可能。

攻击者绑定变量,操纵查询变量值会受到限制。

起初一些人会开始这个值产生疑问,但现在攻击者不再会被这段存在问题的代码的程序逻辑所限制了,他们其实能想操作指针一样操作它。

PWD_COMPARE这个例子中,如果代码运行正常,攻击者不可能看到密码HASH,他们也不可能将用户SYS作为参数,因为程序逻辑不允许这样。
然而,通过造成异常中止程序执行,他们就可以利用这个指针并把密码打印到屏幕。更进一步,现在他们能对用户SYS做他们以前不能做的事情了。

这种缺陷也同样会影响到数据的完整性。在这样的情况下,较高权限的代码是使用DBMS_SQL来执行INSERT,UPDATE或DELETE命令。
但是限制用户输入特定格式则可能让攻击者绕过逻辑判断。举个例子,加入我们要求被插入的数据不能够含有单引号,并且这个检测是通过较高权限代码来做的。

当进程可以通过异常错误被提前中断,这样攻击者就可以获取并回收指针来INSERT那些含单引号的数据。这将影响数据完整性,并且可以导致类似二次命令SQL注入这样的漏洞。

关于这个漏洞的任意一种情况都被认为是个别的并且要冒着崩溃的危险。事实上,在很多情况下根本没有风险。

注意:
同样的威胁也存在于未关闭的SYS_REFCURSOR中。
DBMS_ODCI.RestoreRefCursor过程可以用来还原野指针,但是一旦恢复,就不可能在没有当前用户被检查的许可的情况下修改查询的任何部分,记住,让查询运行在未返回句柄的异常错误下是必要的。

不能修改查询变量,当前中断就得回调。

有一种可能可以绕过这种问题的方法,就是攻击者造成一个“无效识别符”中断并且在指针已经被捕获的时候创建识别符(比如通过函数)。但是,如果攻击者能做这个,他们可能同样可以在函数中放置任意的SQL,以便达到他们的目的。

现在,我们明白了,攻击者在没有合适已知信息的情况下,未关闭的SYS_REFCURSOR是无法导致直接安全隐患的。

防护方法

针对这个问题的防护,开发者可以采取两个方法。
第一,严格的验证输入数据,使用绑定变量的方法已经不够了。在PWD_COMPARE例子里,我们通过即以给定的用户名查找密码。用户名最长30个字符,所以我们需要检查用户输入是不是少于30个字符。这将可以避免我们发生字符过长的异常。记住,还有其他的方法可以促发异常,这些都应该被良好的过滤。
第二个防护手段就是始终有一个“其他”异常情况处理模块,用于关闭打开的指针。



总结
天到不会塌,但是这种攻击会导致数据暴露给攻击者。当进行PL/SQL安全代码审核的时候这个问题一定要注意检查和修补。
其实检查起来并不困难,查找哪些使用了DBMS_SQL的代码,但是却没有提交数据失败准备异常处理代码,或者,在异常处理的情况下没有关闭指针的代码。在这些开发人员疏忽的地方多注意,我们就可以避免类似问题的发生。

附件

A New Class of Attack in Oracle.rar (77.48 KB)

2008-3-28 09:01, 下载次数: 79

文档英文原版

一种新的Oracle攻击方法.rar (755.1 KB)

2008-3-28 09:05, 下载次数: 836

中文翻译文档

TOP

发新话题