WordPress能夠說是當今最受歡迎的(我想說沒有之一)基於PHP的開源CMS,其目前的全球用戶高達數百萬,並擁有超過4600萬次的超高下載量。它是一個開源的系統,其次它的功能也十分強大,源代碼能夠在這裏找到。也正由於此,WordPress也成了衆多黑客的攻擊目標,一旦得手也就意味着數百萬用戶的淪陷。這種普遍的採用使其成爲網絡犯罪分子的一個有趣目標。此次實驗的漏洞是在WordPress核心中的一個通過身份驗證的任意文件刪除漏洞CVE-2018-20714php
該漏洞可能致使攻擊者執行任意代碼。該漏洞自發現到報告給WordPress安全團隊7個月,但仍未修補。自首次報告以來已通過去很長時間沒有任何補丁或具體計劃。如今wordpress4.9.6及如下版本都存在此漏洞。mysql
爲了利用下面討論的漏洞,攻擊者須要得到預先編輯和刪除媒體文件的權限。也就是擁有做者權限。這裏咱們也要了解一下wordpress有哪些權限用戶。git
咱們發現做者權限用戶本來只能夠發佈和管理本身的帖子,但經過這個漏洞卻能夠劫持整個網站並在服務器上執行任意代碼,也就是經過這個WordPress漏洞,黑客可輕鬆控制網站。github
該漏洞存在於用戶永久刪除上傳圖像的縮略圖時在後臺運行的WordPress核心功能之一。sql
至少一個做者賬戶的要求會在某種程度上自動下降此漏洞的嚴重程度,這可能會被流氓內容撰稿人或黑客利用網絡釣魚,密碼重用或其餘攻擊以某種方式獲取做者的憑證所利用。數據庫
利用此漏洞可使攻擊者可以刪除WordPress安裝的任何文件(+ PHP進程用戶具備刪除權限的服務器上的任何其餘文件)。除了擦除整個WordPress安裝的可能性,若是沒有可用的當前備份可能會帶來災難性的後果,攻擊者能夠利用任意文件刪除的能力來規避一些安全措施並在Web服務器上執行任意代碼。更準確地說,能夠刪除如下文件:安全
可是,應該注意的是,因爲攻擊者沒法直接讀取wp-config.php文件的內容來知道現有的「數據庫名稱」,「mysql用戶名」及其「密碼」,因此他能夠從新設置目標站點在他的控制下使用遠程數據庫服務器。一旦完成,攻擊者能夠建立一個新的管理員賬戶並徹底控制網站,包括在服務器上執行任意代碼的能力。「除了刪除整個WordPress安裝的可能性,若是沒有當前的備份可用會形成災難性的後果,攻擊者能夠利用任意文件刪除的功能來規避一些安全措施並在Web服務器上執行任意代碼服務器
前往wordpress中文官網https://cn.wordpress.org/download/releases/下載有此漏洞的版本cookie
(1)安裝wordpress網絡
WordPress 4.9.6
安裝成功後,在後臺添加一個「做者」權限帳戶 「xy」 只有寫做功能,用於測試
(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
(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()
函數在接收刪除文件參數時未進行安全處理,直接進行執行致使。
(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的值的時候,就須要引發咱們的注意,要查看數值是否合法。