作者:啟明星辰ADLab
公眾號:https://mp.weixin.qq.com/s/9DMGLOvFJUjq8MaMr9eg6A
一、漏洞介紹
2月19日,Rips在博客上披露了一個關于Wordpress 5.0.0遠程代碼執行漏洞(https://blog.ripstech.com/2019/wordpress-image-remote-code-execution/)。該漏洞為CVE-2019-8942和 CVE-2019-8943組合漏洞,漏洞代碼在Wordpress核心中已存在了6年。
漏洞由三部分構成:
-
(核心問題)PostMeta可以被覆蓋。攻擊者可以控制POST中
meta_input字段的值,從而自由更改wp_postmeta表中的meta_key與meta_value的值。 -
更新附件時,攻擊者可自由設置對應附件的
_wp_attached_file的值,并結合裁剪功能實現目錄穿越,從而將惡意圖片保存到任意目錄。 -
更新文章時,攻擊者可以自由設置文章的
_wp_page_template的值,并結合模板功能實現本地文件包含,從而最終造成代碼執行。
二、漏洞分析
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將圖片包含,執行代碼。
三、漏洞復現
這里采用mac os+php7.1+wordpress4.9.8+imagick6.9.7復現。
首先,攻擊者需要登錄一個Author權限的賬戶。登錄后添加一個名為createdir.jpg的圖片:

然后更新該圖片信息:
并使用burp抓包,更改如圖所示:
然后開始裁剪圖片,點擊edit Image并抓包得到nonce并構造報文。

繼續上傳并裁剪一張名為finally.jpg的圖片,成功創建文件:
然后新增加一篇文章,在update時繼續抓包更改如下圖所示:
完畢后。查看該文章,成功觸發phpinfo!
四、補丁分析
添加了_wp_get_allowed_postdata方法,將meta_input字段從POST報文中去掉了。
啟明星辰積極防御實驗室(ADLab)
ADLab成立于1999年,是中國安全行業最早成立的攻防技術研究實驗室之一,微軟MAPP計劃核心成員,“黑雀攻擊”概念首推者。截止目前,ADLab已通過CVE累計發布安全漏洞近1000個,通過 CNVD/CNNVD累計發布安全漏洞近500個,持續保持國際網絡安全領域一流水準。實驗室研究方向涵蓋操作系統與應用系統安全研究、移動智能終端安全研究、物聯網智能設備安全研究、Web安全研究、工控系統安全研究、云安全研究。研究成果應用于產品核心技術研究、國家重點科技項目攻關、專業安全服務等。

本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/825/