利用CVE-2018-1335:Apache Tika 命令注入

 

一、前言

本文将介绍从一个未公开披露详情的CVE——Apache tika-server 命令注入漏洞到实现攻击的一系列步骤。此CVE编号为CVE-2018-1335。由于Apache Tika是开源项目,我能够通过CVE介绍和分析Apache Tika代码实际情况来获取一些基本信息。虽然一个命令注入漏洞通常是简单明了的,但是在本文你将看到要实现完整的代码执行或命令注入仍需克服一些障碍。这是Java执行系统命令的方法以及Apahce Tika代码自身的特性导致的。最后,仍然可以通过Windows Script Host (Cscript.exe)来绕过这些限制。

 

二、Apahce Tika简介

Apache Tika™ 工具集可以检测和提取上千种不同文件类型(比如PPT,XLS,PDF等)中的元数据和文本。所有的这些类型文件都可以通过一个单独的接口实现解析,这使Tika对搜索引擎的索引,目录分析和翻译等很有帮助。(https://tika.apache.org/)

Apache Tika由几个不同的组件组成:一个Java库,命令行工具和一个有自己的REST API的独立服务器(tika server)。为了详细了解此独立服务器,可以阅读公开的REST API(https://wiki.apache.org/tika/TikaJAXRS)来开发此漏洞。存在漏洞的Tika版本可以在这里下载:https://archive.apache.org/dist/tika/tika-server-1.17.jar

 

三、解读CVE

开始寻找问题之前,我们首先得阅读CVE公告,看看是否有一些信息可以将我们带到研究的起始点。

原始公告描述如下:

在Tika1.18 之前,用户可以发送精心构造的标头至tika-server,这些标头能够用来注入一些命令到运行tika-server的服务器的命令行中。此漏洞只影响向不受信用户开放并且运行tika-server的服务器。

我们可以从中得到以下信息:

  • 1.18版本已修复

  • 1.17版本未修复

  • 漏洞为命令注入

  • 漏洞入口点为标头

  • 此漏洞由tika-server部分代码造成

有了这些信息,现在我们就有了一个起始点来尝试研究此漏洞。首先我将展示Tikaz已修复和未修复版本的一些信息,尤其是tika-server部分。然后,使用Java的某些函数代码来实现执行操作系统命令也是一个精彩的部分。最后,我们先假设存在某种HTTP请求,然后查找tika-server代码中与请求标头有关的部分。

 

四、深入研究

漏洞验证

对tika-server 1.1.7和1.1.8版本的源代码目录执行并行递归diff处理,一次只返回一个发生修改的文件。下面是较为关键的一次修改:

 利用CVE-2018-1335:Apache Tika 命令注入-互联网之家

由于要找的命令注入漏洞出现在标头部分,而我们的第一个发现在是补丁版本中添加了名为allowable_header_chars的代码块,所以这是一个完美的起点。当然,这些代码可能是用来过滤在标头处用于命令注入的字符。

继续往下翻阅是一个庞大的代码块,其中包含一个有趣的的函数processHeaderConfig,该函数在1.1.8版本中已被移除修改。它使用某些变量来动态地创建一个方法,该方法设置一些对象的特性并使用HTTP标头执行。

 利用CVE-2018-1335:Apache Tika 命令注入-互联网之家

这里是对该函数的描述:

 利用CVE-2018-1335:Apache Tika 命令注入-互联网之家

上图展示了不同特性的前缀,并且在代码的起始位置被定义为静态字符串。

 利用CVE-2018-1335:Apache Tika 命令注入-互联网之家

因此,我们有一组在请求中能作为HTTP标头的静态字符串,它们通常是用来设置对象的某个特性。对于最后的标头,它似乎是X-Tika-OCRsomeproperty: somevalue形式的,然后somevalue转换为类似于setSomeproperty()的函数,该函数将被调用并且等于someValue初始值。

 利用CVE-2018-1335:Apache Tika 命令注入-互联网之家

这里你可以看到这个函数被使用,并且在此请求中会检查标头前缀以确认调用此函数的方式。所需的参数将从这个HTTP请求传入processHeaderConfig函数。

查看processHeaderConfig的使用方式,可以看到特性是被设置在TesseractOCRConfig对象。经过搜寻可能用到对象TesseractOCRConfig的位置,我们发现了一个非常有趣的地方:tika-parsers/src/main/java/org/apache/tika/parser/ocr/TesseractOCRParser.java

TesseractOCRParser.java存在函数doOCR,该函数从我们刚发现的TesseractOCRConfig对象传递配置特性给一个字符串数组,此数组为ProcessBuilde组建一个命令,然后程序开始运转。

 利用CVE-2018-1335:Apache Tika 命令注入-互联网之家

似乎我们快要达成目标了——如果把目前发现的所有信息结合起来,理论上讲我们可以发送一些标头为X-Tika-OCRTesseractPath: <some command>的HTTP请求给服务器,然后这个命令被插入到cmd字符并执行。但是,目前唯一的问题是config.getTesseractPath()已经被预定给另一个我们无法控制的字符,而getTesseractProg()最终变为一个静态字符,tesseract.exe。为了解决这个问题,我们尝试把要执行的命令用双引号包裹,但是Windows忽略引号后面的任何附加内容并且只会执行前面的部分。

为了进一步测试,我们先看看tika-server文档中关于提取某个文件元数据的说明。

 利用CVE-2018-1335:Apache Tika 命令注入-互联网之家

因为OCR全名为Optical Character Recognition(光学字符识别),用于提取出图像中的文本和内容信息。这里,我将上传图像文件而不是docx,希望它能与doOCR函数交互。

组合起来命令为:

curl -T test.tiff http://localhost:9998/meta --header "X-Tika-OCRTesseractPath: "calc.exe""

 利用CVE-2018-1335:Apache Tika 命令注入-互联网之家

OK,我们做到了——在上传时使用PUT方式发送请求,该请求中HTTP标头X-Tika-OCRTesseractPath后端命令用双引号包裹,并且该命令被成功执行。

除了弹出计算器,还能做些别的?

现在,我们只能直接改变应用名称来实现命令执行。这是由于此命令被作为一个数组被传递给JavaProcessBuilder,而我们实际上无法运行超过一条命令或者给命令添加一些参数作为单独的字符,否则将无法执行。这是因为在Java中传递一个字符串数组到进ProcessBuilder或者runtime.exec是遵循以下方式:

 利用CVE-2018-1335:Apache Tika 命令注入-互联网之家

&,<,>,|, 这一类字符,可以在cmd.exe/bin/sh中正常解析,但是ProcessBuilder不可以并且会忽略掉,所以你不能扩展命令或者参数。使用X-Tika-OCRTesseractPath: “cmd.exe /c some args这样简单的命令或者其他的组合无法实现绕过(组合命令)。

让我们回顾cmd数组的构建过程,你可以看到我们也可以控制此命令中的多个参数,每个参数都是config.get*()这样的形式,但是它们又被其他我们无法控制的子部件控制。

 利用CVE-2018-1335:Apache Tika 命令注入-互联网之家

我第一个思路是运行cmd.exe,然后把参数/C换做config.getLanguage(),再插入命令代码到config.getPageSegMode()并执行。但是并不如意,这没有成功,因为在doOCR函数调用之前,名为config.getTesseractPath()的字符已经调用了另一个函数(我们修改后的命令)并且只会执行该命令(为了验证正在调用的应用是否有效)。这里的问题是它只会运行cmd.exe(不包括后续参数)从而导致服务器暂时挂起,因为cmd.exe不会结束,所以后续的doOCR函数不会执行。

解决方案

在实现运行多个命令之前,让我们使用Process Monitor(一款Windows进程监视器)来看看当doCOR函数开启进程时内部发生了什么。tika-server开启后查看此进程属性,以下命令是注入命令构造的结果:

"calc.exe"tesseract.exe C:UsersTestAppDataLocalTempapache-tika-3299124493942985299.tmp 
C:UsersTestAppDataLocalTempapache-tika-7317860646082338953.tmp -l eng -psm 1 txt -c preserve_interword_spaces=0

在命令行中,我们能够控制的有三部分"calc.exe"3299124493942985299.tmp7317860646082338953.tmp。这三个地方我们可以注入一些东西,包括一个命令和两个参数。我们发现了其他有趣的事,Tika的确会创建两个temp文件,但是只有一个是作为第一个参数被传递。

经过进一步调查,我可以确认能够传递命令的第一个temp文件的内容等于我上传的文件。因此,我应该可以使用某些代码或者命令填充该上传文件,并且发生执行。

那么现在,我需要一个Windows本地程序,该程序可以忽略掉tika-server创建的一些离散的参数,并且即使文件后缀为.tmp也可以把它的文件内容当作某个代码或者命令来执行。要想找到这类程序听起来似乎不太可能。但是当我看过了https://github.com/api0cradle/LOLBAS中的LOLBins部分后,我觉得我的运气来了,我遇到了Cscript.exe,该程序似乎有点希望。让我们来看看Cscript 能做些什么吧。

 利用CVE-2018-1335:Apache Tika 命令注入-互联网之家

Cscript证明了它就是我们所需的(程序)。它将第一个参数视为脚本,允许你使用//E:engine标识来指定你要用的脚本引擎(可能是Jscript或者VBS),所以我们不需要考虑文件类型了。放入新命令到cscript中,查看结果:

"cscript.exe"tesseract.exe C:UsersTestAppDataLocalTempapache-tika-3299124493942985299.tmp 
C:UsersTestAppDataLocalTempapache-tika-7317860646082338953.tmp -l //E:Jscript -psm 1 txt -c 
preserve_interword_spaces=0

通过HTTP标头可以设置:

X-Tika-OCRTesseractPath: "cscript.exe"X-Tika-OCRLanguage: //E:Jscript

上传一个“图片”文件,其中包含一些Jscript或者VBS代码:

var oShell = WScript.CreateObject("WScript.Shell");var oExec = oShell.Exec('cmd /c calc.exe');

刚开始上传图像文件时失败了,因为它不是一个有效的图像,其中的特定字节无法被验证。我想到了解决方法,我把content-type设置为image/jp2,这样图像文件能够绕过Tika的检测然后交由OCR处理。然后,我们就可以成功上传包含Jscript的图像了。

最后,我们把所有有东西结合起来,获得了一个完整的任意命令/jscrpit/vbs代码执行。

 

五、小结

看起来简单的一个命令注入漏洞,要真正地实现利用仍需克服大量困难。寻找越过阻碍的方案过程其实非常有趣。尽管该过程非常困难,但仍然有办法,这再次提醒了(开发者)在构造操作系统命令时千万不能相信用户的输入。Apache官方不建议使用者在不安全环境下运行Tika-server,并且暴露给不受信的用户。本文所述漏洞已经修复,现在最新的版本为1.20,如果你仍在使用该服务请立即更新!

Rhino安全实验室已公布该CVE的POC文件:https://github.com/RhinoSecurityLabs/CVEs/tree/master/CVE-2018-1335

本文是翻译文章,文章原作者rhinosecuritylabs,文章来源:rhinosecuritylabs.com
原文地址:https://rhinosecuritylabs.com/application-security/exploiting-cve-2018-1335-apache-tika/


发表评论 取消回复

电子邮件地址不会被公开。 必填项已用*标注