欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

WordPress 5.1:从CSRF到RCE

来源:本站整理 作者:佚名 时间:2019-03-17 TAG: 我要投稿

一、前言
注:此漏洞利用和环境较为复杂,实际价值可能并不是很高,但对于XSS与权限管理也有一定参考价值。
上个月我们公布了WordPress 5.0中一个远程代码执行(RCE)漏洞(需通过身份认证)。本文公布了WordPress 5.1中存在的另一个严重的漏洞利用链,使未经身份认证的攻击者能够在5.1.1版之前的WordPress中获得远程代码执行权限。
 
二、漏洞影响
如果WordPress站点启用了评论(comment)功能,那么攻击者可以诱骗目标网站管理员访问攻击者设置的一个站点,最终接管目标站点。一旦受害管理员访问恶意网站,攻击者就会在后台通过跨站请求伪造(CSRF)攻击目标WordPress站点,不会因此目标受害者警觉。CSRF攻击中滥用了WordPress中的多个逻辑缺陷及数据过滤错误,并且结合这些缺陷实现RCE,最终完全接管目标站点。
5.1.1版之前默认配置的WordPress受这些漏洞影响。
根据WordPress下载页面的统计数据,互联网上超过33%的站点正在使用WordPress。考虑到博客评论是博客网站的核心功能,默认情况下处于启用状态,因此该漏洞会影响数百万站点。
 
三、技术分析
攻击过程参考此处视频。
评论表单中的CSRF
当用户发表新评论时,WordPress并没有检查是否存在CSRF。如果执行检查操作,那某些WordPress功能(如trackbacks以及pingbacks)将无法正常工作。这意味着攻击者可以通过CSRF攻击,以WordPress博客管理员用户的身份创建评论。
这可能成为一个安全问题,因为WordPress网站管理员可以在评论中使用任意HTML标签,甚至还可以使用标签。理论上攻击者可以简单地滥用CSRF漏洞来创建包含恶意JavaScript代码的评论。
WordPress会在评论表单中为管理员生成一个额外的nonce值,通过这种方法尝试解决这个问题。当管理员提交评论并提供有效的nonce值时,WordPress将直接创建评论,没有执行任何过滤此操作。如果nonce值无效,那么评论仍可以创建,但会被过滤处理。
我们可以通过如下代码片段了解WordPress的处理过程。
源文件:/wp-includes/comment.php(简化版):

if ( current_user_can( 'unfiltered_html' ) ) {
    if (! wp_verify_nonce( $_POST['_wp_unfiltered_html_comment'], 'unfiltered-html-comment' )) {
        $_POST['comment'] = wp_filter_post_kses($_POST['comment']); // line 3242
    }
} else {
    $_POST['comment'] = wp_filter_kses($_POST['comment']);
}

事实上,从2009年起,WordPress就没有在评论表单中部署CSRF防护机制。
然而,我们发现针对管理员的过滤过程中存在一处逻辑缺陷。如上代码片段中,WordPress始终使用wp_filter_kses()来过滤评论,除非创建该评论的是具备unfiltered_html功能的管理员。如果满足该条件,并且没有提供有效的nonce值,那么WordPress就会使用wp_filter_post_kses()来过滤评论(上述代码第3242行)。
wp_filter_post_kses()与wp_filter_kses()在严格程度上有所区别。这两个函数都会处理未经过滤的评论,只在字符串中保留特定的HTML标签及属性。通常情况下,使用wp_filter_kses()过滤的评论只会留下非常基本的HTML标签及属性,比如标签以及href属性。
这样攻击者就可以创建一些评论,其中包含比正常评论更多的HTML标签及属性。然而,虽然wp_filter_post_kses()更为宽松,但仍会删除可能导致跨站脚本漏洞的HTML标签及属性。
将HTML注入变成存储型XSS
由于我们能注入其他HTML标签及属性,最终还是可以在WordPress中实现存储型XSS。这是因为WordPress会以某种错误的方式解析并处理正常评论中通常不会设置的某些属性,导致出现任意属性注入问题。
当WordPress执行完评论的过滤过程后,就会修改评论字符串中的标签,以适配SEO(搜索引擎优化)应用场景。
WordPress会将标志的属性字符串(如href="#" title="some link" rel="nofollow")解析成一个关联数组(如下代码片段),其中key为属性名,而value为属性值。
源文件:wp-includes/formatting.php
function wp_rel_nofollow_callback( $matches ) {
    $text = $matches[1];
    $atts = shortcode_parse_atts($matches[1]);
    ⋮
随后WordPress会检查其中是否设置了rel属性。只有通过wp_filter_post_kses()过滤评论时才会设置该属性。如果设置了该属性,则WordPress会处理rel属性,然后再次与标签拼接起来。
源文件:wp-includes/formatting.php
    if (!empty($atts['rel'])) {
        // the processing of the 'rel' attribute happens here
        ⋮
        $text = '';
        foreach ($atts as $name => $value) {            // line 3017
            $text .= $name . '="' . $value . '" ';        // line 3018
        }
    }
    return ' . $text . ' rel="' . $rel . '">';        // line 3021
}
上述代码第3017及3018行处存在缺陷,其中属性值在没有被转义处理的情况下就再次拼接在一起。

[1] [2]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载