Author: p0wd3r(知道創宇404安全實驗室)
Date: 2017-03-05
0x00漏洞概述
漏洞簡介
近日exploit-db上公佈了一個Wordpress < 4.7.1的用戶名枚舉漏洞:https://www.exploit-db.com/exploits/41497/,實際上該漏洞於1月14號就已經在互聯網上公佈,並賦予了CVE-2017-5487。利用該漏洞攻擊者可以在未授權狀態下獲取之前發佈過文章的用戶的用戶名、id等資訊。
漏洞影響
未授權狀態下獲取之前發佈過文章的用戶的用戶名、id等資訊。
觸發前提:Wordpress配寘REST API
影響版本:< 4.7.1
0x01漏洞複現
環境搭建
下載相應版本的Wordpress,然後配寘REST API,具體參見:https://www.seebug.org/vuldb/ssvid-92637
複現
我們先看exploit-db上給出的exp:
可以看到它是利用REST API來獲取用戶的資訊,對應的檔案是wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php,接下來使用exp並且開啟動態調試。
wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php
首先程式進入get_items_permissions_check函數:
get_items_permissions_check
函數中有三個條件語句,如果條件成立就返回錯誤。但是仔細看每一個的條件都是$request[xxx] &&!current_user_can('list_users'),這也就意味者只要前面的語句不成立,那麼後面的current_user_can('list_users')就失去了作用。至於$request['roles']、$request['context']和$request['orderby']的值,通過調試我們可以看到,三者值如下:
$request[xxx] && ! current_user_can( 'list_users' )
current_user_can('list_users')
$request['roles']
$request['context']
$request['orderby']
均不符合條件,所以函數返回true,成功通過了許可權檢查。
true
接下來程式進入了get_items函數,先是設定了一些査詢參數然後使用$query = new WP_User_Query($prepared_args);進行査詢,我們直接在WP_User_Query的query函數處下中斷點:
get_items
$query = new WP_User_Query( $prepared_args );
WP_User_Query
query
$this->request即為執行的査詢,其值如下:
$this->request
可見該API可以獲取的用戶必須滿足以下幾個條件:
- 發表過文章
- 文章的當前狀態是publish
publish
- 文章類型是post、page、attachment其中之一
post
page
attachment
在我們的環境中,admin用戶默認會有文章,所以我們執行exp後會得到admin的一些資訊:
接下來我們再創建一個新的用戶tommy,再執行exp發現結果和上面一樣,原因就是因為還沒有發文章。我們登入tommy並發佈一篇文章,然後再執行exp:
這回就可以獲取tommy的資訊了。
0x02補丁分析
Wordpress官方給出的補丁如下:
Only show users that have authored a post of a post type that has show_in_rest set to true.
show_in_rest
意思是僅當用戶發表的文章的類型的show_in_rest内容為true時,才可以獲取該用戶的資訊。
show_in_rest
true
在程式碼層面上,補丁設定了$prepared_args['has_published_posts']的值,該值在構造査詢語句時會用到:
$prepared_args['has_published_posts']
將査詢中的$post_type設定為show_in_rest=true的那些類型,那麼哪些類型的show_in_rest為true呢?
$post_type
show_in_rest=true
show_in_rest
true
在wp-includes/post.php中的create_initial_post_types函數中可以看到post、page和attachment的show_in_rest均為true,和補丁前査詢中的類型一致,也就是說其實最新版本在默認情况下還是可以使用這個exp的,實際測試的結果也是如此:
wp-includes/post.php
create_initial_post_types
post
page
attachment
show_in_rest
true
至於為什麼這樣,筆者認為可能該API的設計意圖就是讓其他人獲得發佈過文章的用戶的用戶名,因為文章已經公開了,用戶名自然也就公開了。這次補丁給了用戶更多的定制化空間,因為用戶可以自己通過register_post_type來創建文章類型,補丁中提供的show_in_rest内容可以讓用戶自己選擇用戶資訊對於API的可見性。
register_post_type
show_in_rest
本文寫得實在倉促,如果哪裡有不對的地方,還望大家多多指教。
0x03參攷
- https://www.seebug.org/vuldb/ssvid-92732
- https://www.exploit-db.com/exploits/41497/?rss
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5487
- https://github.com/WordPress/WordPress/commit/daf358983cc1ce0c77bf6d2de2ebbb43df2add60
本文由Seebug Paper發佈,如需轉載請注明來源。本文地址:https://paper.seebug.org/239/