第一章 漏洞簡介及危害分析
1.1漏洞介紹
WordPress可以說是當今最受歡迎的(我想說沒有之一)基於PHP的開源CMS,其目前的全球用戶高達數百萬,並擁有超過4600萬次的超高下載量。它是一個開源的系統,其次它的功能也十分強大,源代碼可以在這里找到。也正因為此,WordPress也成了眾多黑客的攻擊目標,一旦得手也就意味着數百萬用戶的淪陷。這種廣泛的采用使其成為網絡犯罪分子的一個有趣目標。這次實驗的漏洞是在WordPress核心中的一個經過身份驗證的任意文件刪除漏洞CVE-2018-20714
該漏洞可能導致攻擊者執行任意代碼。該漏洞自發現到報告給WordPress安全團隊7個月,但仍未修補。自首次報告以來已經過去很長時間沒有任何補丁或具體計划。現在wordpress4.9.6及以下版本都存在此漏洞。
1.2漏洞的利用條件
為了利用下面討論的漏洞,攻擊者需要獲得預先編輯和刪除媒體文件的權限。也就是擁有作者權限。這里我們也要了解一下wordpress有哪些權限用戶。
- 超級管理員(Super Admin) – 有權訪問站點網絡管理功能和所有其他功能。
- 管理員(Administrator) – 有權訪問單個站點內的所有管理功能。
- 編輯(Editor) – 可以發布和管理帖子,包括其他用戶的帖子。
- 作者(Author) – 可以發布和管理自己帖子。
- 貢獻者(Contributor ) – 可以編寫和管理他們自己的帖子但不能發布。
- 訂閱者(Subscriber ) – 只能管理他們個人資料的人。
我們發現作者權限用戶原本只可以發布和管理自己的帖子,但通過這個漏洞卻可以劫持整個網站並在服務器上執行任意代碼,也就是通過這個WordPress漏洞,黑客可輕松控制網站。
該漏洞存在於用戶永久刪除上傳圖像的縮略圖時在后台運行的WordPress核心功能之一。
1.3漏洞的危害
至少一個作者帳戶的要求會在某種程度上自動降低此漏洞的嚴重程度,這可能會被流氓內容撰稿人或黑客利用網絡釣魚,密碼重用或其他攻擊以某種方式獲取作者的憑證所利用。
利用此漏洞可以使攻擊者能夠刪除WordPress安裝的任何文件(+ PHP進程用戶具有刪除權限的服務器上的任何其他文件)。除了擦除整個WordPress安裝的可能性,如果沒有可用的當前備份可能會帶來災難性的后果,攻擊者可以利用任意文件刪除的能力來規避一些安全措施並在Web服務器上執行任意代碼。更准確地說,可以刪除以下文件:
- .htaccess:通常,刪除此文件不會產生任何安全后果。但是,在某些情況下,.htaccess文件包含與安全性相關的約束(例如,對某些文件夾的訪問約束)。刪除此文件將停用這些安全約束。
- index.php文件:通常將空的index.php文件放入目錄中,以防止Web服務器無法執行此操作的目錄列表。刪除這些文件會向攻擊者授予受此度量保護的目錄中所有文件的列表。
- wp-config.php:刪除WordPress安裝的這個文件會在下次訪問網站時觸發WordPress安裝過程。這是因為wp-config.php包含數據庫憑據,並且沒有它的存在,WordPress就像尚未安裝一樣。攻擊者可以刪除此文件,使用他為管理員帳戶選擇的憑據進行安裝過程,最后在服務器上執行任意代碼。
但是,應該注意的是,由於攻擊者無法直接讀取wp-config.php文件的內容來知道現有的“數據庫名稱”,“mysql用戶名”及其“密碼”,所以他可以重新設置目標站點在他的控制下使用遠程數據庫服務器。一旦完成,攻擊者可以創建一個新的管理員帳戶並完全控制網站,包括在服務器上執行任意代碼的能力。“除了刪除整個WordPress安裝的可能性,如果沒有當前的備份可用會造成災難性的后果,攻擊者可以利用任意文件刪除的功能來規避一些安全措施並在Web服務器上執行任意代碼
第二章 漏洞環境搭建及復現
2.1.搭建環境
前往wordpress中文官網https://cn.wordpress.org/download/releases/下載有此漏洞的版本
(1)安裝wordpress

WordPress 4.9.6

安裝成功后,在后台添加一個“作者”權限賬戶 “xy” 只有寫作功能,用於測試
2.2漏洞復現測試
(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

第三章 漏洞代碼審計以及臨時手動修復
3.1 源碼審計
(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()函數在接收刪除文件參數時未進行安全處理,直接進行執行導致。
3.2臨時手動修復
(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的值的時候,就需要引起我們的注意,要查看數值是否合法。
