ORACLE 12C 安全隐患系列(二)
作者:思成 发布时间:2017-03-16

摘要

索引是数据库优化性能的关键技术,同时也是从9i开始(前面未做考证)到现今的12C中,一直存在的安全隐患。索引给数据库带来的安全隐患有多种方式,例如:在PARAMETERS中注入恶意代码导致的缓冲区溢出(CVE-2012-0052);通过SYSTEM.OL$插入触发器,任意执行SQL语句(CVE-2011-3512);拿到高权限用户的表的创建索引权限,进行任意提权(CVE-2010-0902)等。经过多年发展,大部分安全漏洞已经被彻底封死,但CVE-2010-0902带来的提权思路并未封死,直至今天在12C下,如果条件允许还能死灰复燃。

要想彻底根除索引权限带来的(CVE-2010-0902)安全隐患,就必须搞清楚三个问题:1.索引可以舍弃吗? 2.如何利用索引提权?3. 如何合理配置索引?

Index 

大部分情况下,对于一个存在着安全隐患的功能来说,最稳妥的处理方式就是弃之不用。但总有一些功能我们没法直接舍弃,只能尽更大的努力去配置,而索引就属于这样的一种功能。

索引的价值在于能够极大地提高特定数据的查询速度。因为数据库的最基层单位是块,所有的数据在物理磁盘上是以块的形式存储的,为确保对磁盘操作的原子性,访问数据就会一并访问所有数据块。磁盘上的这些数据块与链表类似,它们都包含一个数据段和一个指针,指针指向下一个节点(数据块)的内存地址,而且它们都不需要连续存储(即逻辑上相邻的数据块在物理上可以相隔很远)。

当我们要查询某一字段的时候,如果该值是唯一的,会使用线性查找,理论上要访问N/2个数据块,其中N指的是一个表所涵盖的所有数据块。如果该字段值不唯一,那么就更麻烦了,要搜索整个表空间,理论上要访问全部N个数据块。

然而,如果我们将这些唯一值的字段进行排序,就可以使用二分查找,也就是说理论上只要访问log2 N个数据块就可以找到目标。同样,对不唯一值字段进行排序,找到边缘值,也就不用再搜索表中的其他数据块了。这样一来,性能也会有实质性的提升。

而索引完成的正是对特定字段进行排序的工作。最终往往会以“树”的形式存储。索引唯一明显缺点就是额外占用磁盘空间。鉴于其突出价值,索引功能还是要好好保留,做好正确配置,小心使用。

Index Privilege提权

在Oracle对索引修修补补多个版本之后,大部分漏洞早已堵上,现在剩余的是利用创建索引权限进行提权的这类安全隐患。Oracle规定,只有表的所有者拥有对该表创建权限的权利。其他用户想在别的用户表上创建索引可以通过两个途径:1.简单粗暴的系统权限- Create Any Index,如果一个用户具有系统权限Create Any Index,则该用户可以对任意用户的表创建索引,即便对那张表没有访问权限);2.细腻特定的对象权限- Create Index,指定某个用户对一张特定的表有创建索引的权限。下面,我们将举个例子为大家说明如果一个低权限用户拥有SYS用户某张表的权限会发生什么?

首先创建用户hacker_user,只给予hacker_user最基本的权限。

 1.png

SYS用户创建一张表test_table,这张表将是hacker_user用来提权的关键,向表中插入一条数据,最后把表的查询和创建索引的权限给予低权限用户hacker_user。

2.png

切到hacker_user用户,首先建立调用者权限函数GETDBA。GETDBA的核心语句是:EXECUTE IMMEDIATE 'GRANT DBA TO hacker_user'; 这句话是把hacker_user提权到DBA权限。接下来就需要DBA权限用户调用这个函数了。由于用户hacker_user有SYS表test_table的创建索引权限,于是利用这个权限构造SYS用户调用GETDBA,创建函数形索引可以利用SYS权限调用GETDBA函数,具体如下图:

3.png

注:12C最新版本索引创建会失败,提示缺乏INHERIT PRIVILEGES。INHERIT PRIVILEGES默认没有赋予SYS。在SYS用户下执行GRANT INHERIT PRIVILEGES ON USER SYS TO PUBLIC ;可正常建立。具体内容请查阅《ORACLE 12C 安全隐患系列(一)又喜又悲的新功能-INHERIT PRIVILEGES》一文。

创建成功后,执行查询语句,目的是调用一次索引,使其执行,完成整个提权过程。最后查询DBA用户发现hacker_user已经被成功提权。

4.png

这种提权的方式不仅可以针对SYS用户,可以针对任意具有特定权限的用户,目标往往就是利用这些权限,进行越权或提权操作。12C下对创建的所有用户默认都赋予INHERIT PRIVILEGES,不会出现类似SYS的情况。这里就不用其他权限用户给大家做额外的演示了,过程都是类似的,针对不同权限的用户修改GETDBA中的语句GRANT DBA TO hacker_user 即可。

Index Privilege检查和配置

Oracle对索引提权采用的是治标不治本的方式,因此就需要我们的数据库用户特别注意,要避免错误的配置导致不法分子对数据库实施利用索引的提权攻击。想要检查是否存在Index Privilege入侵的隐患,可以切到SYS用户下进行语句查询:

SELECT OWNER||'.'||TABLE_NAME||':'||GRANTEE FROM DBA_TAB_PRIVS WHERE PRIVILEGE = 'INDEX' AND GRANTEE!=OWNER ORDER BY 1;

此语句可以批量检查索引权限的拥有者和创建者是否相同,如果不同,需要进一步调查来确定是否存在索引注入的可能性。或以高权限用户为单位,检查是否存在高权限用户索引被赋予其他用户的情况存在。

5.png

通过上述查询,从中很容易发现用户HACKER_USER具有test_table的索引权限,需要对其进行清理。清理请使用语句:REVOKE INDEX ON sys.test_table FROM hacker_user;

请注意,很多应用可以在数据库上创建一些表并修改一些权限。例如Oracle eBusiness suite的某些版本,在安装应用的时候把SYS.DUAL的索引权限赋予了public,直接导致了任意用户可以利用SYS.DUAL上的索引漏洞执行任意SQL语句(CVE-2015-0393)。

结论

Index Privilege的安全问题从9i到12c还一直存在,好似一块甩不掉的狗皮膏药,属于典型的便利和安全之间的矛盾。想从两者之间获得平衡,Oracle必须从用户的角度考虑,最大化地提高性能和用户体验。而涉及安全问题,目前就需要以围魏救赵的方式进行封堵,防止索引权限提权的出现。因为这种方法无法从根源上切掉隐患,这就需要Oracle用户时刻注意不要把表的索引权限赋予比创建表权限低的用户,要始终绷紧安全这根弦。