作者:
騰訊安全中心
·
2015/08/18 11:18
這是這幾天一直關注的漏洞了,wordpress
上個禮拜釋出的4.2.4版本,其中提到修補了可能存在的SQL漏洞和多個XSS。 Check point
也很快發出了分析,我也來分析與復現一下最新的這個漏洞。
0x01 GP混用造成的越權漏洞
首先,說明一下背景。wordpress
中使用者許可權分為訂閱者、投稿者、作者、編輯和管理員。
許可權最低的是訂閱者,訂閱者只有訂閱文章的許可權,wordpress
開啟註冊後預設註冊的使用者就是訂閱者。國內很多知名網站,如Freebuf
,使用者註冊後身份即為“訂閱者”。
我們先看到一個提權漏洞,透過這個提權漏洞,我們作為一個訂閱者,可以越權在資料庫裡插入一篇文章。
Wordpress
檢查使用者許可權是呼叫current_user_can
函式,我們看到這個函式:
呼叫的has_cap
方法,跟進
再次跟進map_meta_cap
函式:
可以見到,這個函式是真正檢查許可權的。出錯誤的程式碼在檢查’edit_post’
和’edit_page’
的部分:
可見,這裡當$post
不存在的時候,直接break
出switch
邏輯了,後面所有檢查的程式碼都沒有執行。
$post
是要編輯的文章的ID,也就是說,如果我要編輯一篇不存在的文章,這裡不檢查許可權直接返回。
正常情況下是沒有問題的,因為不存在的文章也沒有編輯一說了。
我們再看到後臺編輯文章的部分:/wp-admin/post.php
這裡首先獲取$_GET[‘post’]
,找不到才獲取$_POST[‘post_ID’]
,也就是可以說此時的$post_ID
是來自GET
的。
但我們後面呼叫current_user_can
函式時傳入的post_ID
卻是來自POST
的:
這裡就是一個邏輯問題,當我們在GET引數中傳入正確的postid
(這樣在get_post
的時候不會產生錯誤),而在POST
引數中傳入一個不存在的postid
,那麼就能夠繞過檢查edit_post
許可權的步驟。
但是這個邏輯錯誤暫時不能造成嚴重的危害,因為實際上編輯文章的程式碼在edit_post
函式中,而這個函式取的post_ID
來自$_POST
。
0x02獲取_wpnonce繞過CSRF防禦
wordpress
對於CSRF漏洞的防禦措施是使用_wpnonce
(也就是token),而且它的token很嚴格,不同的操作有不同的token。
比如我們這裡,如果想呼叫edit_post函式,需要經過以下邏輯:
check_admin_referer
就是檢查_wpnonce
的函式,當$post_type==’postajaxpost’
的時候,此時_wpnonce
的名字就是“add-postajaxpost”
。
那麼怎麼獲取名字為”add-postajaxpost”
的_wpnonce
呢?
看到上面一點的位置:
有個post-quickdraft-save
操作。這個操作是用來臨時儲存草稿的,只要使用者訪問這個操作,就會在資料庫post
表中插入一個status
為auto-draft
的新文章。
如上圖畫出來的步驟,因為我們不知道名字為”add-post”
的_wpnonce
,所以進入到wp_dashboard_quick_press
函式,跟進:
見上圖,很幸運的是,在這個函式中wordpress
居然自己把此時的_wpnonce
輸出在表單裡了。
所以,只要我們訪問一次post-quickdraft-save
,就可以獲得add-post
的_wpnonce
,從而繞過check_admin_referer
函式。
0x03 競爭漏洞導致的邏輯漏洞
這一節實際上是這個提權洞的真正核心,在我們拿到_wpnonce
後,進入edit_post
函式。
我們目的是去update一篇文章,但剛才0x01中說到,如果要繞過許可權檢查的函式,需要傳入一個“不存在”的文章id。那麼即使可以執行update,我們也不可能修改已經存在的文章呀?
這裡實際上涉及到一個由競爭造成的邏輯漏洞。看到edit_post
函式程式碼:
上面兩個圖應該很直觀了。在0x01中說到的current_user_can
被繞過以後,到最終執行update
語句中間,這一段程式碼的執行時間是真空的。
比如我們傳入的tax_input=1,2,3,4…10000
,那麼實際上那條查詢語句就要執行10000次,這是需要執行很長時間的。(在我自己的虛擬機器上測試,執行10000次這條語句,大概需要5~10秒左右)
那麼假設在這段時間內,有新插入的文章,那麼我們之前那個“不存在”的id,不就可能可以存在了嗎(只需要把id設定為最新一篇文章id+1)? 但有個問題是,我們怎麼在這段時間內插入一篇新的文章?因為在0x02中為了獲取_wpnonce
,已經執行過post-quickdraft-save
了。執行post-quickdraft-save
可以在資料庫插入一篇status
為auto-draft
的文章,但每個使用者最多隻會插入一篇文章。
在check-point
的原文中,它提到的方法是,等待一個星期,wordpress
會自動將這篇文章刪除,而_wpnonce
會多保留一天,這樣在這天我們再次執行post-quickdraft-save
又可以插入一篇文章了。
我自己想了一下,其實沒必要這麼麻煩。如果我們能夠再註冊一個身份為訂閱者的賬號,就可以再插入一篇文章了,所以我的POC是不需要等待一個禮拜的。
這三個漏洞組合起來,造成了一個提權漏洞。針對第一篇文章描述的提權漏洞,我寫了一個EXP,執行後訂閱者就可以在垃圾桶內插入一篇文章:
訪問文章編輯頁面可以看到這篇文章:
0x04 untrash文章時造成的SQL隱碼攻擊漏洞
那麼,僅僅是一個這樣的提權漏洞,實際上沒有太大意義。Check-point
第二篇文章裡提到了一個因為這個提權漏洞導致的SQL隱碼攻擊。
先說這個注入的原理。
/wp-includes/post.php
如上圖。Wordpress
很多地方執行SQL語句使用的預編譯,但僅限於直接接受使用者輸入的地方。而上圖中明顯是一個二次操作,先用get_post_meta
函式從資料庫中取出meta,之後以字串拼接的方式插入SQL語句。
這個地方造成一個二次注入。
我們來看看第一次是如何入庫的。首先wp_trash_post
是將文章刪除的方法,其中刪除文章後又呼叫wp_trash_post_comments
將文章下的評論也刪除了:
跟進wp_trash_post_comments
函式:
如上圖,可以看到這個“comment_approved”
其實也是從資料庫中取出來的。所以這個注入我稱之為“三次注入”。
那麼我再繼續跟進,看看最早的comment_approved
是從哪來的。
實際上看到圖中的SQL語句就大概知道了,這個comment_approved
是comments
(評論)表的一個欄位,我分別看了新增評論、修改評論兩個函式,發現修改評論的函式(edit_comment
)中,有涉及到這個欄位:
所以,這一連串操作最後造成的結果就是一個SQL隱碼攻擊漏洞。
總結一下1234,整個利用過程如下:
利用快速草稿插入文章->越權編輯文章->插入評論->修改評論(惡意資料入庫)->刪除文章(惡意資料進入另一個庫)->反刪除文章(惡意資料被取出,直接插入SQL語句導致注入)
0x05 原文隱藏的部分與真實利用過程的研究
這裡不得不提到check-point
的原文,原文的第二篇全文隻字未提wordpress
的token
也就是_wpnonce
,但wordpress後臺幾乎所有操作都需要特定的_wpnonce
。在第一步中我們透過一處洩露點獲取了“add-postajaxpost
”的_wpnonce
,但實際上後面的每一步(增加、編輯評論、trash
文章、untrash
文章)都需要不同的_wpnonce
,那麼這些_wpnonce
我們怎麼獲得?
經過我的分析,最後實在找不到在訂閱者許可權下怎麼獲得“增加評論”和“反刪除文章”的_wpnonce
,而“修改評論”、“刪除文章”的_wpnonce
倒是可以在後臺找到。
另外,雖然前臺也可以增加評論,但前臺增加評論會檢查所屬文章是否是草稿、狀態是否是public
或private
,我們沒法給這篇文章以及其派生的預覽文章增加評論。
所以我把基礎賬號的許可權提升一下,提升到可以發表文章與編輯文章的作者許可權,再來對注入漏洞進行復現。
首先發表一篇文章,並在該文下回復一條評論:
我們再來修改這條評論:
在文章編輯頁面找到trash
的_wpnonce
,將該評論所屬的文章丟入垃圾箱:
再找到反刪除的_wpnonce
,從垃圾箱裡反刪除這篇文章:
檢視SQL執行記錄,發現已經注入成功,引入單引號:
最後,我來總結一下這個漏洞。
這個漏洞有兩個核心點,一是利用一個競爭條件邏輯錯誤,造成的一個越權漏洞;二是利用一個三次操作,導致最後的SQL隱碼攻擊漏洞。
這兩個核心技術點都是很有代表性的,通篇學習下來,不得不佩服洞主的思路和對wordpress
的研究深度。
但我也很遺憾,沒能分析出在最低許可權下怎樣去注入,主要還是_wpnonce
的獲取導致漏洞利用上出現了一些問題。
另外,該SQL隱碼攻擊有一個不得不說的雞肋點,在汙染資料第一次入庫的時候,資料庫中儲存這個資料的欄位只有20字元長度,所以導致最後我們的注入點是一個“存在長度限制”的注入點,對於這個長度限制的利用,我也暫時沒有想出更好的方法。
雖然存在長度限制,但因為注入點出現在update語句的評論表中,所以透過這個漏洞,可以將一整個站的評論全部置為0,對於像Freebuf這類社交性質的網站來說危害還是巨大的。
所以,我對這個SQL隱碼攻擊的評價是:利用上(可能)比較雞肋,但思路是絕對一流的,值得學習。
本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!