# 一种新型的OLAP DML 注入攻击

Author: 乌云历史资料库 (@wooyun_archive)
Published: 2015-08-26T04:15:00Z
Canonical: https://wepostx.com/topics/998

> 乌云历史资料归档
>
> **原始作者：** mssp299
> **原始编号：** superkieran-wooyundrops:728
> **原始发布时间：** 2015-08-26 12:15
> **声明：内容仅用于技术研究和个人使用，版权归 wooyun.org。**

---

对于使用了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提供的一个存储过程，相应代码如下所示：

![原文图片](/media/2016/06/96450f9fa6a9627a8de46f783a27ab31)

![原文图片](/media/2016/06/3e1d88256d206b61cc6e343cb990b9e5)

在这里我们可以看到，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。

![原文图片](/media/2016/06/f430941a5ec3661679d22ccac2e9772c)

请注意上面输出中的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。

![原文图片](/media/2016/06/c569dd82bf43aaa1ddb8fe20bb718bb3)

在上面的攻击中，通过使用双引号，攻击者就可以绕过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了。
下面我们以一个专门设计的例子来进行说明。下面中的前几行代码，只是为展示这个安全问题而做了一些简单的设置工作：

![原文图片](/media/2016/06/1ec834b9de0d494b09f85d26688b39bd)

在这里，我们想在视图中使用OLAP_TABLE，并从一个名为XLNAME的分析工作区变量中读入LIMIT_MAP。即使用户没有写AW的权限，他们仍然能够修改自己私有的副本。这个私有的副本可以用于AW对象的访问。因此，如果用户DAVID连接并发送下列内容，他就能够重写XLNAME，从而直接影响OLAP_TABLE的参数LIMIT_MAP。利用关键字PREDMLCMD，DAVID就可以执行任意的OLAP DML命令了。

![原文图片](/media/2016/06/9bfdc449a53fb4c89cac2793be2425be)

需要注意的是，上面SYS_CONTEXT('USERENV','CURRENT_USER')函数的输出为DAVID。这表明，OLAP DML及其后来的SQL命令都是以当前用户的身份来执行的，而不是以该视图的属主的身份来执行的。为了利用这一点来获得更高的权限，用户DAVID需要将这个视图传递给一个具有定义者权限的PL/SQL包或能够操作任意数据表的存储过程。实际的例子有很多，但是为了便于说明，我们专门设计的例子涉及¬SELECT_FROM_TABLE，这里存储过程的属主为SYS：

![原文图片](/media/2016/06/cdf2c7664184c91bf973de52cf567575)

# 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命令。为此，通常需要拒绝任何含有连字符、双引号或分号的内容，当然，这还要考虑到具体应用程序的特殊情况。

## Replies
