Drupal遠程代碼執行漏洞分析
閱讀: 273
近日,流行的開源內容管理框架Drupal曝出一個遠程代碼執行漏洞,漏洞威脅等級為高危,攻擊者可以利用該漏洞執行惡意代碼,導致網站完全被控制。漏洞對應的CVE編號為CVE-2018-7600。
本篇文章對Drupal 8 – CVE-2017-7600漏洞進行了詳細分析。這個漏洞看起來是一個漏洞,其實我認為,它是由兩個小的雞肋問題組成的。具體是什麼呢?
漏洞分析
這個漏洞的根本原因出在drupal對錶單的渲染上:
可見,在drupal中,我們不需要直接寫html表單,而是先創建一個數組,表單呈現引擎通過位於drupalcorelibDrupalCoreFormFormBuilder.php文件中的buildForm方法構造出一個名為$form表單,然後成對應的html表單進行呈現。
通過下圖buildform的定義,可以看出它是用來構造一個表單的
最終的$form是如下圖這個樣子:
這個漏洞,恰恰就出在了這裡。
但是對於一個drupal框架的應用程序來說,後台表單數組都是開發者寫好的,像這個樣子
攻擊者是無法改變表單數組元素的key值的。
很多應用都提供了如下的一個便利的方法:
比如要註冊一個用戶,用戶名、密碼、郵箱、電話,這些東西都填好了。當點擊提交的時候,網站告訴你,用戶名已存在。
這時候,你會發現,密碼、郵箱、電話這些元素不需要你再次填寫了,頁面已經將保存下來了。
drupal系統同樣有這樣的功能,具體如何實現的呢?下面我們做個試驗:
我們先提交個正常的表單
先在buildform函數返回處下斷後
填寫表單並提交
頁面跳轉到註冊成功頁面,
我們在buildform函數返回處下的斷點根本沒有斷下來。
接著我們再按著上面的表單一模一樣的註冊一個看看:
但這次呢,在斷點處成功斷下了:
在這處斷點,我們把name的值改為」kingsguard_test_1」試試
這次的返回頁面如下:
整個流程是:
用戶填寫表單->表單沒有問題->返回註冊成功頁面
用戶填寫表單->表單內容有問題(例如用戶名已被註冊)->調用buildform方法,把用戶傳入的內容一同構造為表單數組->渲染表單數組為html頁面返回
這就是剛剛在buildform斷點處把name值由kingsguard改為kingsguard_test_1,返回的頁面里username值也變成kingsguard_test_1的原因。
到這裡,攻擊鏈已經很明確了,攻擊者傳入的值,可以通過buildform(方法構造表單數組,並且這個表單數組接下來還會被drupal表單呈現引擎解析為html頁面。
當我們在這個註冊表單頁面里,如果想上傳一張圖片
這時候發送的請求如下
當上傳成功後,往往有一個縮略圖顯示在那,如下圖菊花處:
這個縮略圖,是通過drupalcoremodulesfilesrcElementManagedFile.php文件中的uploadAjaxCallback方法來解析。
注意,還記的上文buildform方法嗎?buildform生成$form數組後,將生成的$form數組傳遞給uploadAjaxCallback方法來解析,目的是在返回頁面上顯示那個縮率的菊花。
既然流程已經捋順了,我們通過構造poc來動態調試下,發送如下圖post包:
首先會進入buildform函數來構造表單數組,接下來這個表單數組($form)會進入uploadAjaxCallback方法。
看下這個uploadAjaxCallback方法:
傳入uploadAjaxCallback方法中的$form變數,就是buildform方法生成的表單數組:
$form數組傳入uploadAjaxCallback方法中後,可以看到有這麼一行(下圖紅框處):
$form_parents變數竟然可以從get中傳入,意味著這個變數可控,其實就是我們poc中的element_parents=account/mail/%23value。
通過poc,此處的$form_parents變數如下圖
$form_parents變數和$form通過NestedArray::getValue方法後,結果值賦給$form
新的form變數如下:
接下來看這裡的renderRoot方法:
此處傳入的$form變數為:
繼續看renderRoot方法:
裡面調用了render方法
繼續看render方法:
裡面調用了doRender方法
繼續看doRender方法:
在這個方法的505行
調用call_user_func方法
此處的參數如下:
可見,這裡的
$callable=」exec」
$elements[『#children』]=」kingsguard_text」(這裡我們傳入的惡意代碼,這裡我就不演示了)
總結:
這個漏洞看起來是一個漏洞,其實我認為,它是由兩個小的雞肋的問題組成的,第一次就是在buildform處,用戶傳入的變數沒有受到限制,導致可以傳入mail[#post_render]、mail[#type]這樣的變數,但是單單這個問題,還不嚴重,因為對於最終渲染的html頁面來說,傳入的數組仍然是數組,不能被當成元素來解析。但是偏偏uploadAjaxCallback方法中的$form_parents變數是直接通過get(『element_parents』)得來的,這下兩個一結合,$form_parents把之前傳入的數值當成元素了,這下就造成了一個大洞。
文章出處:綠盟科技博客
你可能歡
※英國說要對俄國發動網路戰
※Snort-開源網路入侵檢測工具
TAG:黑白之道 |