WordPress能够说是当今最受欢迎的(我想说没有之一)基于PHP的开源CMS,其目前的全球用户高达数百万,并拥有超过4600万次的超高下载量。它是一个开源的系统,其次它的功能也十分强大,源代码能够在这里找到。也正由于此,WordPress也成了众多黑客的攻击目标,一旦得手也就意味着数百万用户的沦陷。这种普遍的采用使其成为网络犯罪分子的一个有趣目标。此次实验的漏洞是在WordPress核心中的一个通过身份验证的任意文件删除漏洞CVE-2018-20714php
该漏洞可能致使攻击者执行任意代码。该漏洞自发现到报告给WordPress安全团队7个月,但仍未修补。自首次报告以来已通过去很长时间没有任何补丁或具体计划。如今wordpress4.9.6及如下版本都存在此漏洞。mysql
为了利用下面讨论的漏洞,攻击者须要得到预先编辑和删除媒体文件的权限。也就是拥有做者权限。这里咱们也要了解一下wordpress有哪些权限用户。git
咱们发现做者权限用户本来只能够发布和管理本身的帖子,但经过这个漏洞却能够劫持整个网站并在服务器上执行任意代码,也就是经过这个WordPress漏洞,黑客可轻松控制网站。github
该漏洞存在于用户永久删除上传图像的缩略图时在后台运行的WordPress核心功能之一。sql
至少一个做者账户的要求会在某种程度上自动下降此漏洞的严重程度,这可能会被流氓内容撰稿人或黑客利用网络钓鱼,密码重用或其余攻击以某种方式获取做者的凭证所利用。数据库
利用此漏洞可使攻击者可以删除WordPress安装的任何文件(+ PHP进程用户具备删除权限的服务器上的任何其余文件)。除了擦除整个WordPress安装的可能性,若是没有可用的当前备份可能会带来灾难性的后果,攻击者能够利用任意文件删除的能力来规避一些安全措施并在Web服务器上执行任意代码。更准确地说,能够删除如下文件:安全
可是,应该注意的是,因为攻击者没法直接读取wp-config.php文件的内容来知道现有的“数据库名称”,“mysql用户名”及其“密码”,因此他能够从新设置目标站点在他的控制下使用远程数据库服务器。一旦完成,攻击者能够建立一个新的管理员账户并彻底控制网站,包括在服务器上执行任意代码的能力。“除了删除整个WordPress安装的可能性,若是没有当前的备份可用会形成灾难性的后果,攻击者能够利用任意文件删除的功能来规避一些安全措施并在Web服务器上执行任意代码服务器
前往wordpress中文官网https://cn.wordpress.org/download/releases/下载有此漏洞的版本cookie
(1)安装wordpress网络
WordPress 4.9.6
安装成功后,在后台添加一个“做者”权限帐户 “xy” 只有写做功能,用于测试
(1)用新添加的做者权限用户登录到网站后台
(2)添加媒体,上传一张图片
(3)点击编辑
(4)在页面源码中找出 _wpnonce 值,经过页面源码查找 值为“388054b4f3”并将cookie复制下来。
(5)而后使用curl或burp构造http请求。
发送到repeater构造数据包而后发送post数据包 (须要带入cookie值)
payload: action=editattachment&_wpnonce=388054b4f3&thumb=../../../../wp-config.php'
POST /wp-admin/post.php?post=21&action=edit HTTP/1.1
发送成功会返回302状态
(6)此时在点击删除按钮
(7)抓包查看,也是返回302包
(8)再次访问主网站就会要求从新安装wordpress
(1)既然是任意文件删除漏洞,那咱们就从删除功能入手,先来看wp-admin/post.php的246-268行:
case 'delete': check_admin_referer('delete-post_' . $post_id); if ( ! $post ) wp_die( __( 'This item has already been deleted.' ) ); if ( ! $post_type_object ) wp_die( __( 'Invalid post type.' ) ); if ( ! current_user_can( 'delete_post', $post_id ) ) wp_die( __( 'Sorry, you are not allowed to delete this item.' ) ); if ( $post->post_type == 'attachment' ) { //删除附件 $force = ( ! MEDIA_TRASH ); if ( ! wp_delete_attachment( $post_id, $force ) ) wp_die( __( 'Error in deleting.' ) ); } else { if ( ! wp_delete_post( $post_id, true ) ) wp_die( __( 'Error in deleting.' ) ); } wp_redirect( add_query_arg('deleted', 1, $sendback) ); exit();
(2)因为咱们删除的是图片附件,因此程序会进入wp_delete_attachment函数,跟进: wp-include/post.php,函数太长,只截取关键部分。
function wp_delete_attachment( $post_id, $force_delete = false ) { .... if ( ! empty($meta['thumb']) ) { // Don't delete the thumb if another attachment uses it. if (! $wpdb->get_row( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE meta_key = '_wp_attachment_metadata' AND meta_value LIKE %s AND post_id <> %d", '%' . $wpdb->esc_like( $meta['thumb'] ) . '%', $post_id)) ) { $thumbfile = str_replace(basename($file), $meta['thumb'], $file); /** 该过滤器记录在wp-includes / functions.php中 */ $thumbfile = apply_filters( 'wp_delete_file', $thumbfile ); @ unlink( path_join($uploadpath['basedir'], $thumbfile) ); } } . . . . wp_delete_file( $file );
$meta['thumb']来自与数据库,是图片的属性之一。代码未检查$meta['thumb']的内容,直接带入unlink函数,若是$meta['thumb']可控
(3) 那么可控点在哪呢?还记得漏洞利用的第一步吗?如今咱们就回到wp-admin/post.php看一下具体代码
/wp-admin/post.php //178-189行 case 'editattachment': check_admin_referer('update-post_' . $post_id); // Don't let these be changed unset($_POST['guid']); $_POST['post_type'] = 'attachment'; // Update the thumbnail filename $newmeta = wp_get_attachment_metadata( $post_id, true ); //获取附件的属性 $newmeta['thumb'] = $_POST['thumb']; wp_update_attachment_metadata( $post_id, $newmeta ); //更新数据库中的信息
代码片断/wp-admin/post.php
表示如何将属于附件的缩略图的文件名保存到数据库中。在从保存的用户输入检索$_POST[‘thumb’]
和保存到数据库wp_update_attachment_metadata()
之间,没有安全措施来确保该值确实表明正在编辑的附件的缩略图。值$_POST[‘thumb’]
能够变动修改成相对于WordPress上传目录的任何文件的路径,当附件被删除时,文件将被删除,如第一个列表中所示。
总结一句就是该漏洞出现的缘由是因为在WordPress的wp-includes/post.php文件中wp_delete_attachement()
函数在接收删除文件参数时未进行安全处理,直接进行执行致使。
(1)在上面咱们了解了漏洞生成的缘由以后,咱们将进行尝试性的漏洞修复。
首先针对漏洞细节提出修复方向
1. 过滤. \等关键字符
2. 挂钩wp_update_attachement_metadata()
调用并确保为meta[‘thumb’]
值提供的数据thumb
不包含任何能够进行路径遍历的部分.
3. 将$newmeta['thumb'] = $_POST['thumb'];改成$newmeta['thumb'] = basename($_POST['thumb']);
(2)修复代码
经过将修复程序添加到functions.php
当前活动的主题/子主题的文件中,能够将修复程序集成到现有的WordPress安装中。
add_filter('wp_update_attachment_metadata','rips_unlink_tempfix'; function rips_unlink_tempfix( $data ) { if( isset($data['thumb']) ) { $data['thumb'] = basename($data['thumb']); } return $data; }
咱们将补丁放入指定位置以后,再来测试漏洞。
能够看到在手动打了补丁以后,虽然发包和回显跟以前区别不大,可是已经没法任意删除文件了
整体操做与上文漏洞复现差很少,但为了监控流量和避免干扰便于分析,本次操做在虚拟机中进行并使用wireshark分析流量。
(1)使用wireshark捕获恶意操做的流量数据
服务器返回302
咱们发现恶意数据最主要的特征就是向服务器传入了一个“thumb”自定义的值
(2)咱们追踪这个包的tcp流
也出现了咱们构造的关键代码,但因为这个漏洞能够删除任意文件,因此咱们须要关注的就是thumb传入的数值,无论上传请求的方式是什么,总须要传入
thumb=xxxx
因此当流量中出现这些异常并指定thumb的值的时候,就须要引发咱们的注意,要查看数值是否合法。