对于使用了DBMS_AW
、OLAP_TABLE
或任何OLAP*函数
的Oracle OLAP
应用程序来说,都将面临着一种新型的注入威胁。归根结底,这是由于SQL
和OLAP DML
之间的语法差异所导致的。最终结果就是,攻击者可以利用这一点,以较高的权限来执行任意的SQL操作。
0x01 导言
联机分析处理(OLAP
)通常用来查询多维数据。在Oracle
中,可以创建分析工作区(Analytic Workspace
)来存储待分析的数据、计算公式和模型等计算对象以及执行分析的各种程序。这里的计算对象及程序都是使用OLAP DML
编写的。需要注意的是,OLAP DML
不同于SQL
,因为它们具有不同的语法。
举例来说,在SQL
中,--用于单行注释,/**/用于多行注释。而OLAP DML中的注释则是用双引号"来表示。一个分号(;)可以用于分隔单行上的各个OLAP DML
命令,而一条命令被拆分为两行的时候,则使用单个减号作为续行符。
OLAP DML
可以从SQL
中执行,但是需要借助于接收OLAP DML
的接口。这包括DBMS_AWPL/SQL包
、OLAP_TABLE函数
以及其他OLAP函数
(比如OLAP_CONDITION
和OLAP_EXPRESSION
)。
另外,还有许多OLAP DML命令
和函数以及一些SQL命令系列也可以从OLAP DML
来执行。
0x02 OLAP DML注入攻击
本文介绍的新型注入攻击,主要出现在用户的输入被传递给OLAP函数
或DBMS_AW包
的时候。即使该输入对于SQL来说是合法的,甚至使用的是约束变量,这种风险依然存在。基本上,攻击者可以将任意SQL语句嵌入到一条OLAP DML语句
中,并以较高的权限执行之。
下面给出一个实际例子。DROP_AW_ELIST_ALL
是Oracle提供的一个存储过程,相应代码如下所示:
在这里我们可以看到,DBMS_ASSERT
是用来确保在"MYSCHEMA
"和"AWNAME
"这两个用户提供的参数中没有嵌入式的SQL
的。一旦通过了验证,它们就会被传递给存储过程DBMS_AW.EXECUTE
,并执行OLAP DML
命令"AW ATTACH
"。
但是我们仍然能够向这个调用中“夹带”进任意的OLAP DML命令
,方法是用双引号括住一个伪造的AWNAME
,并在分号后面加上另外的命令。在下面的例子中,我们执行OLAP DML
命令SQL PROCEDURE
的时候,会顺带执行一个PL/SQL
的存储过程,就本例来说就是DBMS_OUTPUT.PUT_LINE
。
请注意上面输出中的SYS。
另外的一个实例是在DBMS_AW.AW_ATTACH
这个存储过程中发现的。实际上,DBMS_AW
的大多数存储过程和函数都有此安全漏洞。DBMS_AW.AW_ATTACH
在取得AW
名称后,会将其传递给GEN_DBNAME()
。GEN_DBNAME()
函数会利用DBMS_ASSERT.QUALIFIED_SQL_NAME()
对这个AW名称进行检查,以验证输入的合法性。
同样,这里攻击者也能夹带任意OLAP DML
,并从这里执行SQL
。
在上面的攻击中,通过使用双引号,攻击者就可以绕过DBMS_ASSERT.QUALIFIED_SQL_NAME
的输入验证了。不要忘了,OLAP DML
也会看到这个双引号,并将其视为一个注释符。然后,攻击者可以提供一个连字符,这样就能够将OLAP DML
命令AW ATTACH
分为两行。再后面是一个分号,这样攻击者就能够执行其后的OLAP DML
命令(在本例中就是调用SQL PROCEDURE
)了,然后以双引号结束。这样一来,用户的输入不但绕过了DBMS_ASSERT.QUALIFIED_SQL_NAME
,OLAPDML
还会将其视为一个注释符号。
当处理OLAP_TABLE
函数时,如果有任何用户输入被传递给了第三个参数,其本来就是要接收一个OLAP DML
命令,或者是传递给了第四个参数LIMIT_MAP
,那么攻击者就能够执行任意的OLAP DML
了。
下面我们以一个专门设计的例子来进行说明。下面中的前几行代码,只是为展示这个安全问题而做了一些简单的设置工作:
在这里,我们想在视图中使用OLAP_TABLE
,并从一个名为XLNAME
的分析工作区变量中读入LIMIT_MAP
。即使用户没有写AW
的权限,他们仍然能够修改自己私有的副本。这个私有的副本可以用于AW
对象的访问。因此,如果用户DAVID
连接并发送下列内容,他就能够重写XLNAME
,从而直接影响OLAP_TABLE
的参数LIMIT_MAP
。利用关键字PREDMLCMD
,DAVID
就可以执行任意的OLAP DML
命令了。
需要注意的是,上面SYS_CONTEXT('USERENV','CURRENT_USER')
函数的输出为DAVID
。这表明,OLAP DML
及其后来的SQL
命令都是以当前用户的身份来执行的,而不是以该视图的属主的身份来执行的。为了利用这一点来获得更高的权限,用户DAVID
需要将这个视图传递给一个具有定义者权限的PL/SQL包或能够操作任意数据表的存储过程。实际的例子有很多,但是为了便于说明,我们专门设计的例子涉及¬SELECT_FROM_TABLE
,这里存储过程的属主为SYS:
0x03 小结
如果开发人员在PL/SQL
包中使用了DBMS_AW
,存储过程或函数使用了定义者权限,并且用户的输入被传递给DBMS_AW
,那么,即使输入内容通过了SQL级别的验证,或者即使使用了约束变量,攻击者仍然能够执行任意OLAP DML
命令,并且是以PL/SQL包
属主的身份从任意的SQL中执行。同样的,如果开发人员在用到定义者权限的PL/SQL
包中使用了OLAP_TABLE
或任何其他OLAP函数
,那么攻击者就可以利用用户输入来发动类似的攻击。如果OLAP_TABLE
被用于视图中,并且该视图可以像上面例子中那样允许随后加以处理,同时可以通过PL/SQL包来访问该视图的话,那么同样也会遭受类似的注入攻击。
OLAP
应用程序的开发人员必须对所有的用户输入进行仔细检查,以确保用户输入中没有“夹带”任何OLAP DML
命令。为此,通常需要拒绝任何含有连字符、双引号或分号的内容,当然,这还要考虑到具体应用程序的特殊情况。