Modx Revolution 远程代码执行漏洞(CVE-2018-1000207)

来源:scanv2018.07.19

一 漏洞概述

1.1简介

近日,MODx官方发布通告称其MODx Revolution 2.6.4及之前的版本存在2个高危漏洞,攻击者可以通过该漏洞远程执行任意代码,从而获取网站的控制权或者删除任意文件。 本文分析其中的CVE-2018-1000207漏洞,并分别分析MODx 2.5.1和2.6.4版本漏洞形成原因和PoC构造。

1.2漏洞危害

攻击者可以通过该漏洞远程执行任意代码,从而获取网站的控制权或者删除任意文件。

1.3 影响版本

Modx Revolution <= 2.6.4

 

二 影响范围

根据 ZoomEye 网络空间搜索引擎的探测结果,全球一共有 5584 台设备可能受该漏洞的影响。

 

三 漏洞详情

3.1环境搭建

分别安装MODx 2.5.12.6.4版本

3.2漏洞分析

MODx 2.5.1版本

漏洞发生在phpthumb模块,该模块的作用是提供缩略图对象

当我们把光标放到文件系统中的图片上的时候,可以看到弹出了图片的缩略图,此时就调用了phpthumb接口

请求接口类似这样

http://127.0.0.1/connectors/system/phpthumb.php?src=1.png&w=116&h=0&HTTP_MODAUTH=modx5b5067d920ba81.94108199_15b513c49743c49.16917110&f=png&q=90&wctx=mgr&source=1

可以看到几个参数描述了图片的一些基本属性,这些属性在core/model/phpthumb/phpthumb.class.php中定义

从定义中也能看到,phpthumb提供了两种类型的参数:publicprivate

public就是普通属性,包括图片长宽高等,private则是一些私有属性,包括缓存目录,文件类型等,此次漏洞形成的关键就是程序并没有对两种类型的参数区分处理,以至于我们可以直接传入私有参数控制其中的变量值,从而改变程序执行逻辑。

当我们请求这个接口的时候,会访问modSystemPhpThumbProcessor()类,其中的process()方法:

可以看到里面的几个主要操作,包括检查文件是否被缓存,以及读取缓存,设置缓存等,我们利用的就是phpthumb设置缓存的方法phpThumb->cache()

这里面关键的方法是RenderToFile(),可以看到它接收参数$this->cache_filename,那么我们可以直接传入cache_filename这个变量值。

RenderToFile()方法里有file_put_contents()函数,文件名是我们传入的cache_filename,文件内容是$this->outputImageData。如果对内容没有校验的话意味着我们可以写入任意内容,前提是满足$this->RenderOutput()为真,进去看一下RenderOutput()

在这里我们需要满足$this->useRawIMoutput为真,而这个变量默认值为false。实际上useRawIMoutput即为我们提到的私有变量,程序虽然默认定义了私有变量的值,但我们还是可以通过post把值直接传进去,同时这里也没有检验文件的内容,直接把$this->IMresizedData赋值为$this->outputImageData,也就是file_put_contents()所需要的第二个参数,所以到这里就能构成一个任意文件写入的漏洞。

2.6.4版本

那么有没有方法在2.6.4版本也能不需要权限直接写入任意文件呢?答案还是有的,只不过网站需要安装一个插件Gallery

Gallery is a dynamic Gallery Extra for MODx Revolution. It allows you to quickly and easily put up galleries of images, sort them, tag them, and display them in a myriad of ways in the front-end of your site.

简而言之Gallery 是一个图库,可以更方便地管理网站图片。

在这个库中也有phpThumb的相关方法,而且同样有缓存机制,不出意外同样存在任意文件写入漏洞,但是这个方法稍微复杂一些,它把文件写入cache目录,而文件名经过了一个array的反序列化再MD5,这样即使我们能写入文件,却猜不到文件名,因此a2u给出的PoC也没能直接写入文件,而是通过返回包来判断是否存在漏洞。但是经过分析,实际上我们是可以往缓存目录写入一个shell的,而且能够知道保存的文件名,下面来分析一下如何绕过这个看似复杂的流程。

当利用插件上传图片的时候,如果图库中已经有图片,我们就可以看到一张缩略图,请求类似这样

http://127.0.0.1/modx-2.6.4-pl/assets/components/gallery/connector.php?action=web/phpthumb&w=100&h=100&zc=1&src=/modx-2.6.4-pl/assets/gallery/1/cover.png&time=1532596253635

同样的,galleryconnector.php也接收图片属性等public参数,但是此处我们并不关心,直接定位到处理写入缓存的文件core/components/gallery/processors/web/phpthumb.php。漏洞形成点同样也是file_put_contents参数没有经过过滤。

请求在进入phpthumb.php之后,首先会把参数设置成一个array,放在$scriptProperties中,类似这样


在调用系统phpthumb.class.php模块的RenderToFile之前对文件进行了一系列处理,主要关注其中几个

首先对src文件后缀有一个判断

如果没有指定f参数的话,就根据文件后缀将f赋值。也就是说,如果我们传递了f参数,也就可以指定任意文件后缀,此处没有任何过滤。

然后判断src参数是否是以http开头,如果不是,则把src拼接成完整的物理路径:D:/phpStudy/PHPTutorial/WWW/modx-2.6.4-pl/assets/gallery/1/cover.png

接着把src路径中的:/替换成_,也就是D__phpStudy_PHPTutorial_WWW_modx-2.6.4-pl_assets_gallery_1_cover.png,这个字符串将成为最后缓存文件的文件名的前半部分。

而文件名后半部分则是md5(serialize($scriptProperties))的值,把上面的array进行反序列化再MD5,最后拼接上面设置的f后缀,所以最后的文件名类似D__phpStudy_PHPTutorial_WWW_modx-2.6.4-pl_assets_gallery_1_cover.png.0f0d6092657266f9718061fb8a20730d.png,由于在实际利用中我们不知道网站物理路径,因此几乎无法猜出这个文件名。

绕过方式就是利用src参数,上面代码对src进行了一个http判断,假如我们指定srchttp开头,就不会拼接物理路径,而反序列化时的各个参数均是我们可以控制的,这样我们最终就能得到一个文件名类似http.md5_string.php的缓存文件。

3.3补丁分析

补丁主要是对可传入的参数进行了限制,只允许公共参数(public parameters),这样就避免了直接传入私有参数改变程序逻辑。

 

四 修复建议

 

1.Modx官方已经发布了新版本修复了上述漏洞,受影响的用户请尽快升级进行防护。

2.技术业务咨询:

知道创宇技术业务咨询热线:400-060-9587(政府、国有企业)

                                               028-68360638(互联网企业)

 

五 相关链接

新版本下载链接:https://modx.com/download

参考链接:https://forums.modx.com/thread/104040/revolution-2-6-4-and-prior-two-cricital-vulnerabilities-upgrade-mandatory-patch#dis-post-559515

 

 

 

 

热门文章

关注知道创宇云安全

获取安全动态