這篇文章主要講解了“PHP繞過(guò)禁用函數(shù)漏洞的原理”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“PHP繞過(guò)禁用函數(shù)漏洞的原理”吧!
公司主營(yíng)業(yè)務(wù):成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)、移動(dòng)網(wǎng)站開(kāi)發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。創(chuàng)新互聯(lián)公司是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開(kāi)放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來(lái)驚喜。創(chuàng)新互聯(lián)公司推出新田免費(fèi)做網(wǎng)站回饋大家。
PHP 發(fā)布公告,舊版本的 php_array_merge_recursive 函數(shù)中存在UAF風(fēng)險(xiǎn),被利用可能導(dǎo)致用來(lái)繞過(guò)禁用函數(shù)。
受影響的版本
PHP 7.2 - 7.4.9
安全專家建議用戶盡快升級(jí)到安全版本,以解決風(fēng)險(xiǎn)。
一、array_merge_recursive 函數(shù)實(shí)現(xiàn)
在 array_merge_recursive 函數(shù)的實(shí)現(xiàn)中,通過(guò)遍歷源數(shù)組鍵值,如果鍵值不存在,則將對(duì)應(yīng)的值直接插入目標(biāo)數(shù)組;如果鍵值存在,則查詢相應(yīng)的目標(biāo)數(shù)組。在目標(biāo)數(shù)組不存在此鍵值時(shí),將鍵值與相應(yīng)的值插入目標(biāo)數(shù)組;如果存在相同的鍵值,則會(huì)嘗試將相應(yīng)的值加入到目標(biāo)數(shù)組中。具體處理如下圖,在目標(biāo)值為 NULL 時(shí),將其轉(zhuǎn)變?yōu)閿?shù)組類型并在數(shù)組中加入 NULL,在源數(shù)組中的值為對(duì)象類型時(shí)將其轉(zhuǎn)換為數(shù)組類型,嘗試為 src_entry 添加引用后將 src_zval 添加到數(shù)組中;如果源數(shù)組中的值類型為數(shù)組則遞歸調(diào)用 php_array_merge_recursive 函數(shù)。
二、原理分析
在嘗試為源數(shù)組中的值添加引用計(jì)數(shù)的時(shí)候錯(cuò)誤地調(diào)用了 Z_TRY_ADDREF_P(src_entry), src_entry 此時(shí)為對(duì)源數(shù)組中的值的引用,此時(shí)引用計(jì)數(shù)被添加到了引用而不是源數(shù)組中的值。
如果在 array_merge_recursive 函數(shù)中傳入可變的字符串(通過(guò)直接賦值獲得的字符串不可變,在嘗試添加引用計(jì)數(shù)時(shí)會(huì)失?。藭r(shí) src_zval 即可變字符串的引用計(jì)數(shù)并沒(méi)有增加,在數(shù)組被銷毀時(shí),因?yàn)榭勺冏址囊糜?jì)數(shù)提前變?yōu)?0 導(dǎo)致 UAF。
三、利用分析
注: 以下調(diào)試直接在 php 調(diào)試而不是在服務(wù)器加載 php 調(diào)試,但是差別不大。
1、在字符串被釋放后,創(chuàng)建一個(gè)新的對(duì)象占位,進(jìn)行類型混淆,此時(shí)字符串的 len 被新創(chuàng)建對(duì)象的 ce 覆蓋。ce 是一個(gè)地址,所以后續(xù)不會(huì)影響字符串的寫入。
占位前后對(duì)比圖如下:
字符串對(duì)象被釋放后,創(chuàng)建對(duì)象前:
創(chuàng)建對(duì)象后:
2、讀取新創(chuàng)建對(duì)象的 handlers 方便之后泄露內(nèi)存信息,handers 的值即為上圖的 0x0000000008dfe500,在后面可以達(dá)到任意內(nèi)存讀取后可以用來(lái)泄露 php 基地址。讀取新創(chuàng)建對(duì)象中包含堆地址的區(qū)域,獲取被釋放的字符串地址,例如可以讀取 0x7ffffb080540 中的堆地址,減去 0xc8 即為字符串對(duì)象中的字符串地址 hex(0x00007ffffb0805b0 - 0xc8) = 0x7ffffb0804e8 即為字符串對(duì)象的 val 屬性的地址。
3、將新創(chuàng)建對(duì)象的一個(gè)屬性的值指向的類型改寫為引用,引用的地址為一個(gè)偽造的引用字符串對(duì)象??梢詫⑿聞?chuàng)建對(duì)象的第一個(gè)屬性即 properties_table 數(shù)組中的第一個(gè)元素的類型改為引用,地址改為偽造的引用字符串對(duì)象的地址。地址0x7ffffb0804f8 保存的即為新創(chuàng)建對(duì)象的第一個(gè)屬性的地址,地址0x7ffffb080500 中存儲(chǔ)的 0xa 代表引用類型。
其指向的地址 0x00007ffffb080548 保存的為偽造引用對(duì)象的地址,偽造的對(duì)象的第三個(gè)八字節(jié)需置為 6 (引用對(duì)象的類型)。引用字符串對(duì)象的內(nèi)存布局如下圖。可以看到,引用中保存類型為 0x6 代表字符串類型,但是地址為 0x0,之后可以通過(guò)寫入任意地址來(lái)達(dá)到內(nèi)存讀取。
4、通過(guò)修改偽造的字符串的起始地址來(lái)達(dá)到任意內(nèi)存讀取,利用之前泄露的 handlers 地址來(lái)獲取 elf 基址,之后遍歷內(nèi)存獲取 zif_system 函數(shù)的地址。
5、偽造一個(gè)閉包對(duì)象,從一個(gè)真實(shí)存在的閉包對(duì)象拷貝其存儲(chǔ)的值,修改函數(shù)類型為內(nèi)置函數(shù)類型,has_dimension 屬性地址為 zif_system,修改后如下圖。
6、修改對(duì)象的一個(gè)屬性地址為偽造的閉包對(duì)象的地址,調(diào)用對(duì)象的屬性函數(shù)即可完成禁用函數(shù)的繞過(guò)。
一、在7.4.5 版本中進(jìn)行攻擊嘗試
在目標(biāo)服務(wù)器上傳利用腳本,執(zhí)行命令。
(視頻地址:https://v.qq.com/x/page/c31651dla6g.html)
二、7.4.10 版本修復(fù)分析
修改 Z_TRY_ADDREF_P(src_entry) 為 Z_TRY_ADDREF_P(src_zval)。
感謝各位的閱讀,以上就是“PHP繞過(guò)禁用函數(shù)漏洞的原理”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)PHP繞過(guò)禁用函數(shù)漏洞的原理這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!