Wordpress 5.0.0远程代码执行缝隙分析与复现

颁布功夫 2019-02-23
1、缝隙介绍

2月19日,,,,,,Rips在博客上披露了一个关于Wordpress 5.0.0远程代码执行缝隙。。。。。。。该缝隙为CVE-2019-8942和 CVE-2019-8943组合缝隙,,,,,,缝隙代码在Wordpress主题中已存在了6年。。。。。。。


(https://blog.ripstech.com/2019/wordpress-image-remote-code-execution/)

缝隙由三部门组成:


(主题问题)PostMeta能够被覆盖。。。。。。。攻击者能够节造POST中meta_input字段的值,,,,,,从而自由更改wp_postmeta表中的meta_key与meta_value的值。。。。。。。


更新附件时,,,,,,攻击者可自由设置对应附件的_wp_attached_file的值,,,,,,并结合裁剪职能实现目录穿越,,,,,,从而将恶意图片保留到肆意目录。。。。。。。


更新文章时,,,,,,攻击者能够自由设置文章的_wp_page_template的值,,,,,,并结合模板职能实现本地文件蕴含,,,,,,从而最终造成代码执行。。。。。。。


2、缝隙分析

2.1 Post Meta覆盖(主题问题)

当编纂一个POST时会挪用edit_post步骤,,,,,,wp-admin/includes/post.php:208


8827太阳集团(Macau)股份有限公司-Official website


此时会将$_POST赋值给$post_data。。。。。。。而后$post_data的值又会被带入到wp_update_post函数中。。。。。。。


8827太阳集团(Macau)股份有限公司-Official website


跟踪wp_update_post函数,,,,,,wp-includes/post.php:3969


8827太阳集团(Macau)股份有限公司-Official website


在该函数末尾,,,,,,城市挪用wp_insert_post函数,,,,,,并将$postarr传入到该函数中,,,,,,wp_insert_post函数略长,,,,,,在该函数中有这样一段代码,,,,,,wp-includes/post.php:3779 。。。。。。。


8827太阳集团(Macau)股份有限公司-Official website


对$postarr['meta_input']做一个遍历,,,,,,并将键值都带入到update_post_meta函数中,,,,,,该函数内容如下:


8827太阳集团(Macau)股份有限公司-Official website


挪用了update_metadata函数,,,,,,对应的$meta_key和$meta_value都是攻击者可控的。。。。。。。该函数重要职能就是wp_postmeta表进行更新和插入。。。。。。。


wp_postmeta表结构如下:


8827太阳集团(Macau)股份有限公司-Official website

通过该函数,,,,,,攻击者能够自由增长和批改对应post_id的meta_key和meta_value的值。。。。。。。


2.2 目录穿越问题

目录穿越问题是以Post Meta覆盖为铺垫的。。。。。。。在wp-admin/includes/ajax-actions.php:3520


8827太阳集团(Macau)股份有限公司-Official website


在wp_ajax_crop_image函数中,,,,,,第一行就传入了一个$_POST['id']参数。。。。。。。而后还传入了$_POST['cropDetails']参数。。。。。。。都是攻击者可控的。。。。。。。并将这些值带入到了wp_crop_image函数中,,,,,,函数体如下:


8827太阳集团(Macau)股份有限公司-Official website


在28行,,,,,,会进入该if,,,,,,传入的$src是攻击者可控的,,,,,,带入到get_attached_file函数中,,,,,,函数体如下:


8827太阳集团(Macau)股份有限公司-Official website


挪用get_post_meta函数,,,,,,将wp_postmeta内外对应的post_id字段meta_key值为_wp_attached_file的meta_value值查问出来并返回。。。。。。。由上文可知,,,,,,该值是攻击者能够自己覆盖的,,,,,,是可控的。。。。。。。


回到wp_crop_image函数,,,,,,返回后的值赋值给$src_file并判断该文件存在与否。。。。。。。若不存在则挪用_load_image_edit_path函数,,,,,,跟踪该函数:


8827太阳集团(Macau)股份有限公司-Official website


进入第二个if分支中,,,,,,挪用wp_get_attachment_url函数,,,,,,查看该函数:


8827太阳集团(Macau)股份有限公司-Official website


如上图标注的所示,,,,,,最后形成的是一个url链接。。。。。。。


若是,,,,,,攻击者将meta_value更改为2019/02/evil.jpg#/../../../../../theme-compat/evil.jpg。。。。。。。


最后,,,,,,形成的url就是这样http://localhost/wp-content/uploads/2019/02/evil.jpg#/../../../../../theme-compat/evil.jpg。。。。。。。


并将这个url层层返回到wp_crop_image函数,,,,,,并带入到了wp_get_image_editor函数:


8827太阳集团(Macau)股份有限公司-Official website


跟踪该函数:


8827太阳集团(Macau)股份有限公司-Official website


其中有一步细节的操作是在_wp_image_editor_choose这个函数中:


8827太阳集团(Macau)股份有限公司-Official website


Wordpress提供了两种方式来处置图片,,,,,,Imagick是优先级最高的,,,,,,GD其次。。。。。。。这个挨次会影响最终环境的利用。。。。。。。


而Imagick和GD对图片也有分歧的处置:


Imagick不会去除掉图片中的exif部门,,,,,,所以我们能够将待执行payload代码参与到exif部门。。。。。。。


GD会去除图片的exif部门,,,,,,并且其中的phpcode很难存活。。。。。。。除非通过精心机关一张图片能力够。。。。。。。


在这里我们选择Imagick库,,,,,,选择好图片处置库之后就返回该库并挪用load步骤加载url:


8827太阳集团(Macau)股份有限公司-Official website


8827太阳集团(Macau)股份有限公司-Official website


这里有一个坑点,,,,,,就是Imagick处置类的load函数中挪用的是readImage函数,,,,,,但在高版本的Imagick上该函数不支持远程图片链接,,,,,,因而我选取Imagick-6.9.7来复现,,,,,,环境如下图:


8827太阳集团(Macau)股份有限公司-Official website


挪用完load函数后,,,,,,就是对获取到的图片内容进行裁剪处置,,,,,,而后把新天生的图片进行保留,,,,,,查看保留新文件的操作(造成目录穿越的终点):


8827太阳集团(Macau)股份有限公司-Official website


$dst_file是保留的文件名,,,,,,天生规定如上图标注所示。。。。。。。因而天生最终文件蹊径为:uploaddir/2019/02/cropped-evil.jpg#/../../../../../theme-compat/cropped-evil.jpg。。。。。。。


这里有一个把稳点,,,,,,就是会先挪用wp_mkdir_p函数来创建目录,,,,,,而后再挪用save函数保留文件。。。。。。。


save函数主题如下图:


8827太阳集团(Macau)股份有限公司-Official website

这里挪用了make_image函数,,,,,,函数体如下:


8827太阳集团(Macau)股份有限公司-Official website


这里又有一个坑点,,,,,,这里会用call_user_func_array函数来挪用Imagick的writeImage函数,,,,,,并将$filename传递进去,,,,,,值妥贴心的一点是该函数在Linux下不支持不存在的目录跳转。。。。。。。


但是为了达到目录穿越的主张,,,,,,我们这里传入的$filename就是uploaddir/2019/02/cropped-evil.jpg#/../../../../../theme-compat/cropped-evil.jpg 。。。。。。。


由于cropped-evil.jpg#是个不存在的目录,,,,,,因而该函数会挪用失败抛出谬误终止流程,,,,,,天然也无法挪用fopen和fwrite进行写文件的操作。。。。。。。


借助屡次上传裁剪就能够绕过这个坑点,,,,,,但是天生的新图片又有什么用呢??????? ?


2.3 本地文件蕴含

在wp-includes/template-loader.php:55


8827太阳集团(Macau)股份有限公司-Official website


这里挪用了get_single_template函数:


8827太阳集团(Macau)股份有限公司-Official website


第一行获取要求的对象。。。。。。。当我们通过路由浏览文章使剽里会返回WP_Post对象,,,,,,其中蕴含文章的一些属性。。。。。。。
而后将该对象带入到了get_page_template_slug函数中,,,,,,函数体如下:


8827太阳集团(Macau)股份有限公司-Official website


凭据post_id从wp_postmeta表中取出meta_key字段值为_wp_page_template的meta_value的值并返回。。。。。。。


从主题问题可知,,,,,,这里返回的meta_value的值同样是能够被攻击者自由覆盖的,,,,,,因而该值是攻击者可控的。。。。。。。


而后将该值增长到$templates数组中并传递给get_query_template函数。。。。。。。函数体如下:


8827太阳集团(Macau)股份有限公司-Official website


挪用locate_template函数,,,,,,函数体如下:


8827太阳集团(Macau)股份有限公司-Official website


这里做蹊径的拼接和判断。。。。。。。$template_name是可控的,,,,,,因而结合上文的目录穿越,,,,,,将新天生的图片放到theme-compat目录下即可。。。。。。。


而后返回该蹊径,,,,,,回到最起头的处所:


8827太阳集团(Macau)股份有限公司-Official website


挪用include将图片蕴含,,,,,,执行代码。。。。。。。

3、缝隙复现

这里,,,,,,我们选取mac os+php7.1+wordpress4.9.8+imagick6.9.7进行复现。。。。。。。


首先,,,,,,攻击者必要登录一个Author权限的账户。。。。。。。登录后增长一个名为createdir.jpg的图片:


8827太阳集团(Macau)股份有限公司-Official website


而后更新该图片信息:


8827太阳集团(Macau)股份有限公司-Official website


并使用burp抓包,,,,,,更改如图所示:


8827太阳集团(Macau)股份有限公司-Official website


而后起头裁剪图片,,,,,,点击edit Image并抓包得到nonce并机关报文。。。。。。。

8827太阳集团(Macau)股份有限公司-Official website


持续上传并裁剪一张名为finally.jpg的图片,,,,,,成功创建文件:


8827太阳集团(Macau)股份有限公司-Official website


而后新增长一篇文章,,,,,,在update时持续抓包更改如下图所示:


8827太阳集团(Macau)股份有限公司-Official website


结束后。。。。。。。查看该文章,,,,,,成功触发phpinfo!

8827太阳集团(Macau)股份有限公司-Official website

4、补丁分析

8827太阳集团(Macau)股份有限公司-Official website

增长了_wp_get_allowed_postdata步骤,,,,,,将meta_input字段从POST报文中去掉了。。。。。。。