熊本熊本熊's Studio.

MyBB 1.8.20 从存储型XSS到RCE漏洞深度分析

字数统计: 3.4k阅读时长: 12 min
2019/09/04 Share

MyBB是国际上非常优秀的免费论坛软件,最大的特色是简单但是功能却出奇的强大,支持多国语言,可以分别设置前台后台的语言。

MyBB作为一个开源项目,拥有活跃的社区环境,项目的管理,发展由社区志愿者支持。用户量广泛,在github上的项目拥有609 个star,79个releases。

MyBB <= 1.8.20存在一处从存储的XSS到RCE组合利用漏洞,攻击者可以先通过xss获得管理员权限,再通过rce达到远程代码执行。这套利用流程不仅隐蔽而且利用难度低,只要私信给mybb管理员发出一条包含payload的消息即可。

该漏洞由RIPS 团队安全研究人员Simon Scannell发现并纰漏。但截止目前,并未公布利用poc

我们试图从Simon Scannell简单的漏洞披露中深入分析该漏洞,并尝试还原出poc

首先分析下mybb xss漏洞

 

0x01 XSS漏洞


此漏洞为mybb对BBCode的错误解析而造成的

首先了解下BBCode:

BCode是Bulletin Board Code的缩写,属于轻量标记语言(Lightweight Markup Language)的一种,如字面上所表示的,它主要是使用在BBS、论坛、Blog等网络应用上。BBcode的语法通常为 [标记] 这种形式,即语法左右用两个中括号包围,以作为与正常文字间的区别。系统解译时遇上中括号便知道该处是BBcode,会在解译结果输出到用户端时转换成最为通用的HTML语法。

下图举个简单的例子:

0

在BBcode中给关键词加链接可以用下面的代码:

[url=https://www.xiongbenxiongbenxiong.com/1.html]熊本熊本熊[/url]

然而,BBcode只是一种标记语言,并没有一个共同的标准。各个BBS、论坛、Blog等网络应用程序可能会有自己独创的BBcode。在实际场景中,不同的程序会在后台使用不同的方式将BBcode解析成html来进行页面渲染

接下来看下mybb程序对BBCode的解析流程

举一个例子,使用BBcode格式分别插入的一条视频链接与一条url链接

1

Mybb程序会对BBcode进行解析,以便转化为浏览器可识别的html语言

Mybb首先会对video链接进行解析(注意:这与video和url的排列顺序无关,在程序的后台,会首先处理video,后处理url)

经过video解析器解析后的格式如下

2

接着mybb对BBCode格式的url进行解析,经过url解析器解析后的格式如下

3

此时,mybb以将BBcode语言解析成为html语言,浏览器渲染页面,显示嵌入的video与超链接中的url

如果,我们将两个BBCode格式的语句进行嵌套呢?

像如下图这样的形式

4

按照我们的推测,会进行如下的解析:

首先,解析video

5

解析之后的格式如上图

然后,解析url,也就是下图红框处的结构

6

解析之后的结果如下图

7

8

注意上图红框这里,src中的值,被href引入的双引号闭合,而onmusemove成功逃逸出来,意味着alert会在鼠标移动时,alert将会被执行

事实上,以上的流程,在mybb中是否成立。正式因为上文猜测中的嵌套解析,造成了此次xss漏洞

接下来跟下代码

首先,我们给管理员(admin)账号发一条如下图bbcode语言的私信

9

这条私信会原封不动的被写入数据库中

10

当管理员查看私信时,这条message会被从数据库中取出,并解析为html语言进行渲染

11

程序调用private.php执行上述操作,跟进private.php

12

在997行处,程序将留言从数据库中取出,并赋值$pm

13

在11789行处,将$pm传入build_postbit方法

14

跟入build_postbit方法

15

在该方法774行处,将message传入parse_message,这里的message即为我们构造的BBCode语句

跟入parse_message方法

16

在parse_message方法中201行处,调用parse_mycode对$message进行处理

跟入parse_mycod方法

17

如上图,第一个红框处,会对bbcode中的video结构进行解析,而第二个红框处,会对url,email等结构进行解析。正因为这里的解析的先后顺序,决定了构造poc时的嵌套顺序

首先来看video解析

18

这里使用了preg_replace_callback,对匹配到的内容使用mycode_parse_video_callback回调进行替换

19

跟入mycode_parse_video_callback

20

可见mycode_parse_video_callback将$matches[1], $matches[2]传入mycode_parse_video方法

跟入mycode_parse_video方法

21

如下图,首先使用parse_url对传入的url($matches[2])进行解析

22

解析后的parsed_url值如下图

23

接着,将$parsed_url[‘fragment’]赋值与$ fragment

24

随后,进入switch语句,根据不同视频来源,分情况解析。我们这里构造的是youtbe来源,进入该分支

25

在下图中,将$ fragment中的!v=置空,赋值与$id

26

此时id值为test[url=onmousemove=’alert(1337)’]

27

随后,由于担心xss攻击,程序在这里对$id进行html特殊字符转义处理,如下图

28

29

接着,从templates中取出对应video的模板,如下图$templates get方法

30

根据get方法,看下取出模板的形式

31

上图为最终生成html的模板,此处的$id即为上文中case分支中赋值的$id

最终,将$id值填充的模板中,结果如下图

32

回到preg_replace_callback处,$message替换后的结果如下图

33

此时$message=<iframe width=”560” height=”315” src=”//www.youtube.com/embed/test[url=onmousemove='alert(1337)']" frameborder=”0” allowfullscreen></iframe>[/url]

Video的解析到此结束了,此时html语句,是不是和上文流程中猜测的形式一样呢?

 

接下来,仍然使用preg_replace_callback对url进行替换

34

如下图可见,使用#[url=((?!javascript)[a-z]+?://)([^

“<]+?)](.+?)[/url]#si正则进行匹配,使用

mycode_parse_url_callback1回调对$message进行替换

35

此处的处理与上文中的video极其相似,这里就不重复说明了

在url解析结束后,messgae值如下图

36

可见,如上文流程分析一致,href中引入的双引号,将src闭合了,onmousemove得以逃逸

最终,xss产生

37

38

39

利用给管理员私信的这个功能,通过xss漏洞,可以获取管理员cookie,从而获得后台权限

接下来分析下rce漏洞

 

0x02 RCE漏洞


Mybb后台提供导入theme功能

40

可以选择本地theme进行导入,上传的theme格式许为xml格式,形式如下

41

这里的导入的xml文件存储了该theme下所有包含的css文件,下面展示其中两个片段

42

43

简单来说,相当于是把这个theme里包含的所有css都存储到xml一个结构里

在上传xml格式的theme时,程序后台会解析该xml,如下图代码

44

随后,将解析的xml树中的内容,例如css名称,内容、id等写入数据库

45

上图即为解析上传的xml格式的theme,将解析出的css的信息入库的操作

46

入库后,数据库中内容如上图

在解析xml内的css数据的name时,后台程序会校验css的后缀是否合法

47

可见,程序要求xml结构中,css文件后缀应为.css。但其校验方式仅仅检测css名称后四位是否为.css

当我们构造css数据时,可以使得css文件名为aaaaaaaaaaaaaaaaaaaaaaaaaa.php.css,在css文件内容处插入payload,如下图

48

在xml解析后,$stylesheet[‘attributes’][‘name’]的值为aaaaaaaaaaaaaaaaaaaaaaaaaa.php.css,成功绕过检测

当进行入库操作时,如下图代码

49

此时将要插入表中name字段的值为aaaaaaaaaaaaaaaaaaaaaaaaaa.php.css,由于mysql默认字段长度为30字符,而我们的name长度为34字符,所以,.css会被截断,最终插入表中name字段的值为aaaaaaaaaaaaaaaaaaaaaaaaaa.php。

与此同时,aaaaaaaaaaaaaaaaaaaaaaaaaa.php.css中的内容,会插入到stylesheet字段中,我们构造的payload随同aaaaaaaaaaaaaaaaaaaaaaaaaa.php.css中的内容,一同写入数据库。

50

程序在执行xml数据从解析到入库的操作的同时,也会在本地生成对应的文件,如下图

51

这里生成文件名仍是.css后缀。原因很好理解:这里生成的文件名由解析上传的xml文件中的css name值决定的,如下图

52

因此后缀为.css

 

接下来在后台页面中,查看我们刚刚导入的theme

53

可以看到我们grq themes里的css列表中,后缀已经变为php

这是为什么呢?原因很简单,因为此处展示的内容,是从数据库中查询得到,此时数据库内容如下图

54

数据库由于30字符最大长度的截断,已经把入库的文件名后的.css截断了,此时数据库中name的后缀变为php

这时,点击Stylesheets in grq 列表中的aaaaaaaaaaaaaaaaaaaaaaaaaa.php,进入编辑页面

55

56

再次查看后台文件夹,可见生成了一个.php后缀文件,如下图

57

这里的原理也很简单。点击编辑css文件时,程序会从数据库中读取该文件的name以及内容,

并判断在指定目录中是否存在,若不存在,则用数据库中取出的name为文件名,生成文件,并将数据库中取出的内容写入该文件中

由于此时库中的name为aaaaaaaaaaaaaaaaaaaaaaaaaa.php,所以在指定位置生成了aaaaaaaaaaaaaaaaaaaaaaaaaa.php文件

下面跟下php文件生成的流程与代码

在点击aaaaaaaaaaaaaaaaaaaaaaaaaa.php,进入其编辑页面这个操作

58

 

此时发送请求如下

59

后台代码执行如下:

首先进入

\admin\modules\style\themes.php

60

此时的action为edit_stylesheet,进入上图分支

接着从数据库中查询该条数据,执行的sql语句如下

61

62

查询结果如上图

 

最后将库中内容写入文件,文件名即为库中name字段,文件内容即为库中stylesheet字段

63

如上图,构造的payload被写入aaaaaaaaaaaaaaaaaaaaaaaaaa.php

 

打开aaaaaaaaaaaaaaaaaaaaaaaaaa.php,可见payload成功写入

64

 

访问该文件

65

Phpinfo执行成功

 

 

 

0x03 漏洞分析时发现的问题


1. sql_mode默认值问题

笔者在尝试构造与复现rce漏洞时,当构造34字符长度文件名,以便通过mysql最大长度截断机制截断时,出现的如下问题:

66

Data too long~

笔者使用的是Wamp环境,在查看安装的mysql配置时,发现默认sql_mode为STRICT_ALL_TABLES,如下图:

67

STRICT_ALL_TABLES:

对所有引擎的表都启用严格模式。(STRICT_TRANS_TABLES只对支持事务的表启用严格模式)。

在严格模式下,一旦任何操作的数据产生问题,都会终止当前的操作。对于启用STRICT_ALL_TABLES选项的非事务引擎来说,这时数据可能停留在一个未知的状态。这可能不是所有非事务引擎愿意看到的一种情况,因此需要非常小心这个选项可能带来的潜在影响。

在严格模式下,超长的字符串,不能被截断入库,因此这里可能会影响到该漏洞的利用

###

2.urldecode的必要性

在xss漏洞中,漏洞作者原文有一段描述如下

68

漏洞作者在他的文章中这样描述

“通常,由于正则表达式过滤器可以防止此类攻击,因此无法在其他bbcodes中注入bbcodes。但是,对于呈现[video] bbcodes的回调方法会在应嵌入的视频的URL上调用urldecode()。视频URL被urldecoded,这将允许绕过正则表达式保护并通过URL编码注入。”

从作者的描述来看,正是因为此处的urldecode存在,导致被url编码后的payload可以绕过正则防护,从而造成注入。根据作者描述,构建的流程如下:

1.Payload->正则过滤器->检测不通过->失败

2.url编码后的payload->正则过滤器->检测通过->urldecode->还原为明文payload->注入成功

但是在我实际分析中,发现根本不需要对payload进行URL编码,正如上文我构造的pyaload,无需编码仍可触发漏洞。而且,也没有在urldecode执行前,发现正则过滤器

3.RCE漏洞的入口

关于RCE漏洞的入口,作者原文描述如下:

69

在此处,作者多次提到create与choose the filename字眼,一度让我认为漏洞存在于创建与修改Theme处,如下图

70

或是修改Template Name处,如下图

71

在尝试寻找rce入口时,发现一处有意思的地方,当修改templates为aaaaaaaaaaaaaaaaaaaaaaaaaa.php.css时

72

保存后,程序会将.css截断,并提示后缀问题,如下图

73

在跟踪此处代码时发现,在修改template name时,程序是会检查文件名长度并截断的,控制template name长度为30字符,如下图

74

这里可以印证,漏洞入口并不在修改名字和创建template处,经过后来的分析与寻找,才找到上文中真正的入口点,也就是Import a Theme处。但是从这个过程可见,mybb对文件名长度还是有一定限制的,只是防护的有疏漏,忘记检查导入的xml结构中的name字段长度。

 

0x04 漏洞修复


xss漏洞

针对xss漏洞,使用encode_url方法替换原来的htmlspecialchars_uni,如下图

75

回顾上文,在漏洞利用中,id中的内容为嵌套的url bbcod代码

76

当id被url编码后,之后在通过正则解析url bbcod代码时,该处被编码后的内容就不会被正则匹配到,从而防止嵌套解析造成xss漏洞

RCE漏洞

针对rce漏洞,使用my_substr方法限制name长度为30字符,如下图

77

CATALOG
  1. 1. 0x01 XSS漏洞
  2. 2. 0x02 RCE漏洞
  3. 3. 0x03 漏洞分析时发现的问题
    1. 3.1. 1. sql_mode默认值问题
    2. 3.2. 2.urldecode的必要性
    3. 3.3. 3.RCE漏洞的入口
  4. 4. 0x04 漏洞修复
    1. 4.1. xss漏洞
    2. 4.2. RCE漏洞