WordPress 5.1:从CSRF到远程代码执行
上个月,我公布了一个WordPress 5.0中需要权限远的程执行代码漏洞。而这篇文章我将揭示一个在WordPress 5.1中的另一条漏洞利用链,它能使未经授权的攻击者在WordPress 5.1.1之前的任何WordPress网站上进行远程代码执行。
影响
攻击者可以通过诱骗目标网站的管理员访问攻击者所控制的网站来接管任何启用了评论功能的WordPress网站。
一旦目标网站管理员访问攻击者所控制的恶意网站,就会受到一个CSRF攻击,而且不会引起到受害者的注意。这个CSRF漏洞利用了多个逻辑缺陷和代码错误,最终会导致远程执行代码,导致受害者的网站被接管。
这些漏洞存在于5.1.1之前的WordPress版本中,默认设置下就会生效。
根据统计,全球33%的网站都使用WordPress。考虑到评论是博客的核心功能并且在默认情况下启用,预计该漏洞会影响数百万个网站。
技术分析
评论功能的CSRF漏洞可导致HTML代码注入
当用户发布新评论时,WordPress并不会进行CSRF检查。因为这可能会影响到某些WordPress特性,如trackbacks 和 pingbacks。这意味着攻击者可以通过CSRF攻击假借WordPress网站管理员的名义发表评论。
而这就会形成另一个安全问题,因为WordPress网站的管理员可以在评论中插入任意HTML代码,甚至是前端脚本。从理论上讲,攻击者可利用CSRF漏洞来往页面插入恶意的前端代码。
对于以上问题,WordPress尝试通过为管理员生成额外的随机数来解决。当管理员提交评论并附带有效的随机数时,评论将会不经过安全检查就直接发布。如果提供的随机数无效,则评论仍会发布,但会对评论进行安全检查。
以下的代码显示了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']);
}
} else {
$_POST['comment'] = wp_filter_kses($_POST['comment']);
}
⋮
自2009年以来,WordPress网站评论CSRF保护就不存在。
但是,我们在对管理员的安全检查流程中发现了一个逻辑漏洞。正如你在上面的代码片段中所看到的,普通用户的评论始终会通过wp_filter_kses()
的安全检查,而当拥有unfiltered_html
功能的管理员发表评论时,则不需要。接着,如果管理员不能提供有效的随机数,则使用wp_filter_post_kses()
函数来进行安全检查。
wp_filter_post_kses()
和wp_filter_kses()
两个安全检查函数的在区别在于严格程度。一般来说,wp_filter_kses()
只允许使用基本的HTML标记,例如<a>
。
当然,虽然wp_filter_post_kses()
更宽松,但仍会删除任何可能导致跨站点脚本的HTML标记和属性。
将HTML注入升级为存储型XSS
此时,我们需要找到以管理员身份注入XSS的办法。经过尝试后,我利用某些属性的解析错误,成功得到一个存储型XSS。
在安全检查函数处理管理员评论时,出于优化SEC的目的,它会修改<a>
标签。
它会把<a>
的属性href="#" title="some link" rel="nofollow"
解析为关联数组,其中key是属性的名称,值是属性值。
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()
安全检查时这个值才会被设置。如果是,则会和<a>
标记重新组合在一起。
wp-includes/formatting.php
if (!empty($atts['rel'])) {
// the processing of the 'rel' attribute happens here
⋮
$text = '';
foreach ($atts as $name => $value) {
$text .= $name . '="' . $value . '" ';
}
}
return '<a ' . $text . ' rel="' . $rel . '">';
}
从上述代码片段可以看出,其中属性值被连接在一起而没有经过转义。
因此,攻击者可以创建包含恶意代码的<a>
,例如,将title
设置为title='XSS " on mouseover=alert(1) id="'
。这个字符串是可以通过安全检查的。但是,此时被title标签使用单引号包围起来了。
而当属性重新组合在一起时,title属性的值会以双引号括起来。这意味着攻击者可以通过注入额外的双引号来逃逸。
例如:
注意,以上<a>
的拼接是在安全检查后。所以,攻击者已经攻击成功,把存储型XSS插入网站中。
通过内框架执行XSS
在攻击者能用CSRF以管理员身份往评论中插入XSS后,由于缺乏X-fr ame-Options
的保护,攻击者可以往目标网站插入一个隐藏的<if rame>
,里面包含带有XSS代码的评论。这样,所有的攻击都是隐藏执行,管理员很难注意到。
升级为远程执行代码
此时,我可以使用管理员身份执行任意前端代码,轻松实现远程代码执行。默认情况下,WordPress允许管理员直接编辑主题和插件的.php
文件。通过简插入简单的PHP后门,攻击者就可以获得任意PHP代码执行。
补丁
默认情况下,WordPress会自动安全更新,你应该已经运行了最新版本5.1.1。如果你的WordPress网站出于某种原因禁用了自动更新功能,你还可禁用评论。最重要的是,请务必在访问其他网站之前注销管理员身份。
时间线
2018年10月24日 发现可以通过CSRF向WordPress注入更多的HTML标签。
2018年10月25日 WordPress回应了Hackerone的报告。
2019年2月5日 WordPress提出补丁,我们及进行验证。
2019年3月1日 通知WordPress,我已将TML注入升级到存储的XSS漏洞。
2019年3月1日 WordPress通知我们,WordPress安全团队的成员已经发现了问题,并且已准备好补丁。
2019年3月13日 WordPress 5.1.1版本发布
我们要感谢WordPress的安全团队,他们在这个漏洞的合作时表现非常友好并且专业。
本文由白帽汇整理并翻译,不代表白帽汇任何观点和立场
来源:https://blog.ripstech.com/2019/wordpress-csrf-to-rce/
最新评论