Mybb 18.20从存储型XSS到RCE分析

栏目: 编程工具 · 发布时间: 4年前

内容简介:2019年6月11日,RIPS团队在团队博客中分享了一篇其实漏洞本身来说,毕竟是需要通过XSS来触发的,哪怕是储存型XSS可以通过私信等方式隐藏,但漏洞的影响再怎么严重也有限,但漏洞点却意外的精巧,下面就让我们一起来详细聊聊看…

2019年6月11日,RIPS团队在团队博客中分享了一篇 MyBB <= 1.8.20: From Stored XSS to RCE ,文章中主要提到了一个Mybb18.20中存在的存储型xss以及一个后台的文件上传绕过。

其实漏洞本身来说,毕竟是需要通过XSS来触发的,哪怕是储存型XSS可以通过私信等方式隐藏,但漏洞的影响再怎么严重也有限,但漏洞点却意外的精巧,下面就让我们一起来详细聊聊看…

漏洞要求

储存型xss

拥有可以发布信息的账号权限

服务端开启视频解析

<=18.20

管理员后台文件创建漏洞

拥有后台管理员权限(换言之就是需要有管理员权限的账号触发xss)

<=18.20

漏洞分析

在原文的描述中,把多个漏洞构建成一个利用链来解释,但从漏洞分析的角度来看,我们没必要这么强行,我们分别聊聊这两个单独的漏洞:储存型xss、后台任意文件创建。

储存型XSS

在Mybb乃至大部分的论坛类CMS中,一般无论是文章还是评论又或是的什么东西,都会需要在内容中插入图片、链接、视频等等等,而其中大部分都是选择使用一套所谓的“伪”标签的解析方式。

也就是说用户们通过在内容中加入 [url][img] 等“伪”标签,后台就会在保存文章或者解析文章的时候,把这类“伪”标签转化为相应的 <a><img> ,然后输出到文章内容中,而这种方式会以事先规定好的方式解析和处理内容以及标签,也就是所谓的白名单防御,而这种语法被称之为 bbcode

这样一来攻击者就很难构造储存型xss了,因为除了这些标签以外,其他的标签都不会被解析(所有的左右尖括号以及双引号都会被转义)。

function htmlspecialchars_uni($message)
{
    $message = preg_replace("#&(?!\#[0-9]+;)#si", "&", $message); // Fix & but allow unicode
    $message = str_replace("<", "<", $message);
    $message = str_replace(">", ">", $message);
    $message = str_replace("\"", """, $message);
    return $message;
}

正所谓,有人的地方就会有漏洞。

在这看似很绝对的防御方式下,我们不如重新梳理下Mybb中的处理过程。

/inc/class_parse.php line 435 的  parse_mycode 函数中就是主要负责处理这个问题的地方。

function parse_mycode($message, $options=array())
    {
        global $lang, $mybb;

        if(empty($this->options))
        {
            $this->options = $options;
        }

        // Cache the MyCode globally if needed.
        if($this->mycode_cache == 0)
        {
            $this->cache_mycode();
        }

        // Parse quotes first
        $message = $this->mycode_parse_quotes($message);

        // Convert images when allowed.
        if(!empty($this->options['allow_imgcode']))
        {
            $message = preg_replace_callback("#\[img\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_callback1'), $message);
            $message = preg_replace_callback("#\[img=([1-9][0-9]*)x([1-9][0-9]*)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_callback2'), $message);
            $message = preg_replace_callback("#\[img align=(left|right)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_callback3'), $message);
            $message = preg_replace_callback("#\[img=([1-9][0-9]*)x([1-9][0-9]*) align=(left|right)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_callback4'), $message);
        }
        else
        {
            $message = preg_replace_callback("#\[img\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_disabled_callback1'), $message);
            $message = preg_replace_callback("#\[img=([1-9][0-9]*)x([1-9][0-9]*)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_disabled_callback2'), $message);
            $message = preg_replace_callback("#\[img align=(left|right)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_disabled_callback3'), $message);
            $message = preg_replace_callback("#\[img=([1-9][0-9]*)x([1-9][0-9]*) align=(left|right)\](\r\n?|\n?)(https?://([^<>\"']+?))\[/img\]#is", array($this, 'mycode_parse_img_disabled_callback4'), $message);
        }

        // Convert videos when allow.
        if(!empty($this->options['allow_videocode']))
        {
            $message = preg_replace_callback("#\[url]test.com[/url]

后台会首先处理

首先跟入到函数 /inc/class_parse.php line 1385行 mycode_parse_video 中。

Mybb 18.20从存储型XSS到RCE分析 链接经过 parse_url 处理被分解为:

array (size=4)
  'scheme' => string 'http' (length=4)
  'host' => string 'test' (length=4)
  'path' => string '/test' (length=5)
  'fragment' => string '[url]onmousemove=alert();//[/url]&1=1' (length=41)

然后在1420行,各个参数会被做相应的处理,由于我们必须保留 = 号以及 / 号,所以这里我们选择把内容放在fragment中。

Mybb 18.20从存储型XSS到RCE分析

在1501行case youtube中,被拼接到id上。

case "youtube":
    if($fragments[0])
    {
        $id = str_replace('!v=', '', $fragments[0]); // http://www.youtube.com/watch#!v=fds123
    }
    elseif($input['v'])
    {
        $id = $input['v']; // http://www.youtube.com/watch?v=fds123
    }
    else
    {
        $id = $path[1]; // http://www.youtu.be/fds123
    }
    break;

最后id会经过一次htmlspecialchars_uni,然后生成模板。

$id = htmlspecialchars_uni($id);

eval("\$video_code = \"".$templates->get("video_{$video}_embed", 1, 0)."\";");
return $video_code;

当然这并不影响到我们上面的内容。

到此为止我们的内容变成了:

<iframe width="560" height="315" src="//www.youtube.com/embed/[url]onload=alert();//[/url]" frameborder="0" allowfullscreen></iframe>

紧接着再经过对 [url] 的处理,上面的内容变为:

<iframe width="560" height="315" src="//www.youtube.com/embed/<a href="http://onload=alert();//" target="_blank" rel="noopener" class="mycode_url">http://onload=alert();//</a>" frameborder="0" allowfullscreen></iframe>

我们再把前面的内容简化看看,链接由:

变成了:

变成了:

<iframe src="//www.youtube.com/embed/<a href="http://onload=alert();//"..."></iframe>

由于我们插入在 iframe 标签中的href被转变成了 <a href="http://onload=alert();//"> , 由于双引号没有转义,所以iframe的href在a标签的href中被闭合,而原本的a标签中的href内容被直接暴露在了标签中,onload就变成了有效的属性!

最后浏览器会做简单的解析分割处理,最后生成了相应的标签,当url中的链接加载完毕,标签的动作属性就可以被触发了。

Mybb 18.20从存储型XSS到RCE分析

管理员后台文件创建漏洞

在Mybb的管理员后台中,管理员可以自定义论坛的模板和主题,除了普通的导入主题以外,他们允许管理员直接创建新的css文件,当然,服务端限制了管理员的这种行为,它要求管理员只能创建文件结尾为 .css 的文件。

/admin/inc/functions_themes.php line 264

function import_theme_xml($xml, $options=array())
{
    ...
    foreach($theme['stylesheets']['stylesheet'] as $stylesheet)
    {
        if(substr($stylesheet['attributes']['name'], -4) != ".css")
        {
            continue;
        }
        ...

看上去好像并没有什么办法绕过,但值得注意的是,代码中先将文件名先写入了数据库中。

Mybb 18.20从存储型XSS到RCE分析

紧接着我们看看数据库结构。

Mybb 18.20从存储型XSS到RCE分析

我们可以很明显的看到name的类型为varchar且长度只有30位。

如果我们在上传的xml文件中构造name为 tttttttttttttttttttttttttt.php.css 时,name在存入数据库时会被截断,并只保留前30位,也就是 tttttttttttttttttttttttttt.php

<?xml version="1.0" encoding="UTF-8"?>

<theme>
    <stylesheets>
        <stylesheet name="tttttttttttttttttttttttttt.php.css">
            test
        </stylesheet>
    </stylesheets>

</theme>

紧接着我们需要寻找一个获取name并创建文件的地方。

在/admin/modules/style/themes.php 的1252行,这个变量被从数据库中提取出来。

Mybb 18.20从存储型XSS到RCE分析

theme_stylesheet 的name作为字典的键被写入相关的数据。

$mybb->input['do'] == "save_orders" 时,当前主题会被修改。

Mybb 18.20从存储型XSS到RCE分析

在保存了当前主题之后,后台会检查每个文件是否存在,如果不存在,则会获取name并写入相应的内容。

Mybb 18.20从存储型XSS到RCE分析

可以看到我们成功的写入了 php 文件。

完成的漏洞复现过程

储存型XSS

找到任意一个发送信息的地方,如发表文章、发送私信等….

Mybb 18.20从存储型XSS到RCE分析

发送下面这些信息。

然后阅读就可以触发。

Mybb 18.20从存储型XSS到RCE分析

管理员后台文件创建漏洞

找到后台加载theme的地方。

Mybb 18.20从存储型XSS到RCE分析

构造上传文件test.xml。

<?xml version="1.0" encoding="UTF-8"?>

<theme>
    <stylesheets>
        <stylesheet name="tttttttttttttttttttttttttt.php.css">
            test
        </stylesheet>
    </stylesheets>

</theme>

需要注意要勾选 Ignore Version Compatibility。

然后查看Theme列表,找到新添加的theme。

Mybb 18.20从存储型XSS到RCE分析

然后保存并访问相应tid地址的文件即可。

Mybb 18.20从存储型XSS到RCE分析 补丁

https://github.com/mybb/mybb/commit/44fc01f723b122be1bc8daaca324e29b690901d6

储存型XSS

Mybb 18.20从存储型XSS到RCE分析

这里的iframe标签的链接被encode_url重新处理,一旦被转义,那么 [url] 就不会被继续解析,则不会存在问题。

管理员后台文件创建漏洞

Mybb 18.20从存储型XSS到RCE分析

在判断文件名后缀之前,加入了字符数的截断,这样一来就无法通过数据库字符截断来构造特殊的name了。

写在最后

整个漏洞其实说到实际利用来说,其实不算太苛刻,基本上来说只要能注册这个论坛的账号就可以构造xss,由于是储存型xss,所以无论是发送私信还是广而告之都有很大的概率被管理员点击,当管理员触发之后,之后的js构造exp就只是代码复杂度的问题了。

抛开实际的利用不谈,这个漏洞的普适性才更加的特殊,bbcode是现在主流的论坛复杂环境的解决方案,事实上,可能会有不少cms会忽略和mybb一样的问题,毕竟人才是最大的安全问题,当人自以为是理解了机器的一切想法时,就会理所当然得忽略那些还没被发掘的问题,安全问题,也就在这种情况下悄然诞生了。

*本文作者:LoRexxar’@知道创宇404实验室,转载请注明来自FreeBuf.COM


以上所述就是小编给大家介绍的《Mybb 18.20从存储型XSS到RCE分析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

.NET设计规范

.NET设计规范

克瓦林纳 / 葛子昴 / 人民邮电出版社 / 2006-7 / 49.00元

本书为框架设计师和广大开发人员设计高质量的软件提供了权威的指南。书中介绍了在设计框架时的最佳实践,提供了自顶向下的规范,其中所描述的规范普遍适用于规模不同、可重用程度不同的框架和软件。这些规范历经.net框架三个版本的长期开发,凝聚了数千名开发人员的经验和智慧。微软的各开发组正在使用这些规范开发下一代影响世界的软件产品。. 本书适用于框架设计师以及相关的专业技术人员,也适用于高等院校相关专业......一起来看看 《.NET设计规范》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具