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


尊龙凯时 - 人生就是搏!


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


尊龙凯时 - 人生就是搏!


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


尊龙凯时 - 人生就是搏!


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


尊龙凯时 - 人生就是搏!


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


尊龙凯时 - 人生就是搏!


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


wp_postmeta表结构如下:


尊龙凯时 - 人生就是搏!

通过该函数,攻击者可以自由增添和修改对应post_id的meta_key和meta_value的值。


2.2 目录穿越问题

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


尊龙凯时 - 人生就是搏!


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


尊龙凯时 - 人生就是搏!


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


尊龙凯时 - 人生就是搏!


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


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


尊龙凯时 - 人生就是搏!


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


尊龙凯时 - 人生就是搏!


如上图标注的所示,最后形成的是一个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函数:


尊龙凯时 - 人生就是搏!


跟踪该函数:


尊龙凯时 - 人生就是搏!


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


尊龙凯时 - 人生就是搏!


Wordpress提供了两种方法来处置惩罚图片,Imagick是优先级最高的,GD其次。这个顺序会影响最终情形的使用。


而Imagick和GD对图片也有差别的处置惩罚:


Imagick不会去除掉图片中的exif部分,以是我们可以将待执行payload代码加入到exif部分。


GD会去除图片的exif部分,并且其中的phpcode很难存活。除非通过全心结构一张图片才可以。


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


尊龙凯时 - 人生就是搏!


尊龙凯时 - 人生就是搏!


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


尊龙凯时 - 人生就是搏!


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


尊龙凯时 - 人生就是搏!


$dst_file是生涯的文件名,生陋习则如上图标注所示。因今天生最终文件路径为:uploaddir/2019/02/cropped-evil.jpg#/../../../../../theme-compat/cropped-evil.jpg。


这里有一个注重点,就是会先挪用wp_mkdir_p函数来建设目录,然后再挪用save函数生涯文件。


save函数焦点如下图:


尊龙凯时 - 人生就是搏!

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


尊龙凯时 - 人生就是搏!


这里又有一个坑点,这里会用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


尊龙凯时 - 人生就是搏!


这里挪用了get_single_template函数:


尊龙凯时 - 人生就是搏!


第一行获取请求的工具。当我们通过路由浏览文章时这里会返回WP_Post工具,其中包括文章的一些属性。
然后将该工具带入到了get_page_template_slug函数中,函数体如下:


尊龙凯时 - 人生就是搏!


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


从焦点问题可知,这里返回的meta_value的值同样是可以被攻击者自由笼罩的,因此该值是攻击者可控的。


然后将该值添加到$templates数组中并转达给get_query_template函数。函数体如下:


尊龙凯时 - 人生就是搏!


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


尊龙凯时 - 人生就是搏!


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


然后返回该路径,回到最最先的地方:


尊龙凯时 - 人生就是搏!


挪用include将图片包括,执行代码。

3、误差复现

这里,我们接纳mac os+php7.1+wordpress4.9.8+imagick6.9.7举行复现。


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


尊龙凯时 - 人生就是搏!


然后更新该图片信息:


尊龙凯时 - 人生就是搏!


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


尊龙凯时 - 人生就是搏!


然后最先裁剪图片,点击edit Image并抓包获得nonce并结构报文。

尊龙凯时 - 人生就是搏!


继续上传并裁剪一张名为finally.jpg的图片,乐成建设文件:


尊龙凯时 - 人生就是搏!


然后新增添一篇文章,在update时继续抓包更改如下图所示:


尊龙凯时 - 人生就是搏!


完毕后。审查该文章,乐成触发phpinfo!

尊龙凯时 - 人生就是搏!

4、补丁剖析

尊龙凯时 - 人生就是搏!

添加了_wp_get_allowed_postdata要领,将meta_input字段从POST报文中去掉了。