CVE-2024-4439 Wordpress存储型XSS
前言
之前在机器人的信息推送中看到了Wordpress
存储型的xss
漏洞,虽然定义为了中危,并且评分只有5.9
,但是这与以往不同的是这次的漏洞出现在了Wordpress
本身,而不是它繁多的插件之中,不禁引发出了我的好奇。于是在空闲时间中,简单的看了一下漏洞的成因并做了复现,形成了以下一篇简单的文章。
影响版本
上面阿里云显示的漏洞影响版本只说了一个6.5.2
,并没有具体到细节的版本号,但是在wordpress
官网中可以找到实际影响的版本,如下:
受影响的版本: 6.5 – 6.5.1、6.4 – 6.4.3、6.3 – 6.3.3、6.2 – 6.2.4、 6.1 – 6.1.5、6.0 – 6.0.7
完全补丁版本: 6.1.6、6.2.5、6.3.4、6.4.4、6.5.2
漏洞分析
这次的漏洞产生点并不能在默认的wordpress
中,还需要对wordpress
进行一些配置,主要产生存储型XSS
的点是在文章评论的作者名称中,因为对文章作者的名称代码不恰当,导致了输入的作者名称没有经过任何的过滤就嵌入到了HTML
的属性当中,导致了存储型XSS
。
关于头像的渲染的处理在wp-includes/blocks/avatar.php
文件中,它的render_block_core_avatar
对评论处的头像和名称等进行了渲染处理。
这部分代码是对评论信息的一些处理,首先通过get_comment
函数传入commentId
获取评论的内容,这里是通过数据库中的索引字段commentId
获取数据,获取到了内容之后,通过__
函数将作者的名称进行翻译,以便于支持多语言。随后通过get_avatar()
函数来获取评论者的头像,随后就进入到了if
判断之中,当评论中的某些属性不为空,根据下面wordpress
评论的一些属性信息,这里的条件检查应该是处理是否可以将评论者的头像作为链接显示,如果链接的目标是可以以_blank
新窗口的方式打开,那么就会赋值$label
属性。
if ( '_blank' === $attributes['linkTarget'] ) {
$label = 'aria-label="' . sprintf( esc_attr__( '(%s website link, opens in a new tab)' ), $comment->comment_author ) . '"';
}
$avatar_block = sprintf( '<a href="%1$s" target="%2$s" %3$s class="wp-block-avatar__link">%4$s</a>', esc_url( $comment->comment_author_url ), esc_attr( $attributes['linkTarget'] ), $label, $avatar_block );
}
return sprintf( '<div %1s>%2s</div>', $wrapper_attributes, $avatar_block );
其实这里一开始看并没有看出什么问题,细看会发现esc_attr__
函数并没有包裹$comment->comment_author
,也就是没有对$comment->comment_author
进行处理,最终通过sprintf
翻译输出了$comment->comment_author
,在下面的代码中直接就将$label
嵌入到了target="%2$s
之后,这就导致了XSS
的问题。
看回去esc_attr
函数,这个函数的确保字符串在存储或输出前是有效的UTF-8
格式,随后就调用了_wp_specialchars
进行了处理。
_wp_specialchars
函数是进行了一些安全处理的,如果$comment->comment_author
能经过这些处理,那么就不会产生xss
的问题,因为在这个函数中,对能够造成xss
的字符问题进行了实体的编码,防止了xss
问题的产生。
function _wp_specialchars( $text, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) {
$text = (string) $text;
if ( 0 === strlen( $text ) ) {
return '';
}
if ( ! preg_match( '/[&<>"\']/', $text ) ) {
return $text;
}
if ( empty( $quote_style ) ) {
$quote_style = ENT_NOQUOTES;
} elseif ( ENT_XML1 === $quote_style ) {
$quote_style = ENT_QUOTES | ENT_XML1;
} elseif ( ! in_array( $quote_style, array( ENT_NOQUOTES, ENT_COMPAT, ENT_QUOTES, 'single', 'double' ), true ) ) {
$quote_style = ENT_QUOTES;
}
if ( ! $charset ) {
static $_charset = null;
if ( ! isset( $_charset ) ) {
$alloptions = wp_load_alloptions();
$_charset = isset( $alloptions['blog_charset'] ) ? $alloptions['blog_charset'] : '';
}
$charset = $_charset;
}
if ( in_array( $charset, array( 'utf8', 'utf-8', 'UTF8' ), true ) ) {
$charset = 'UTF-8';
}
$_quote_style = $quote_style;
if ( 'double' === $quote_style ) {
$quote_style = ENT_COMPAT;
$_quote_style = ENT_COMPAT;
} elseif ( 'single' === $quote_style ) {
$quote_style = ENT_NOQUOTES;
}
if ( ! $double_encode ) {
$text = wp_kses_normalize_entities( $text, ( $quote_style & ENT_XML1 ) ? 'xml' : 'html' );
}
$text = htmlspecialchars( $text, $quote_style, $charset, $double_encode );
if ( 'single' === $_quote_style ) {
$text = str_replace( "'", ''', $text );
}
return $text;
}
因此在修复的版本之中,可以看到wordpress
官网只是把两个函数的顺序调换了一下,就完成了修复。感觉这是程序员在编码的时候疏忽大意造成的问题。
漏洞复现
从上文的分析中可以看到,要在$label
属性中带有comment->comment_author
,需要进入到条件判断中,所以这并非是wordpress
默认就能够产生的漏洞。在wordpress
的主题编辑器中,点击评论的头像设置可以看到右方有两个属性,链接到用户个人资料和在新窗口打开,把两个按钮勾选上去,就是对应的条件判断。
随后就可以进行评论,在评论中将作者的名字换成带有xss
恶意语句的,这里一定要加上网站地址的信息,不然过不了条件判断。最终复现的结果如下:
总结
整个漏洞的成因是因为在评论头像处开启了新窗口和链接的配置后,在对$comment->comment_author
的处理函数顺序反了,导致安全处理的函数没有对评论作者名进行实体转义编码处理,直接成为了HTML
代码的一个属性,造成了XSS
漏洞。
文章标题:CVE-2024-4439 Wordpress存储型XSS
文章链接:https://aiwin.fun/index.php/archives/4407/
最后编辑:2024 年 5 月 9 日 13:35 By Aiwin
许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)