成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

PHP7.0.0格式化字符串漏洞與EIP劫持分析

安全 漏洞
PHP7.0.0的這個格式化字符串漏洞是15年12月在exploit-db上發現的。發現該漏洞多了一個CVE編號:CVE-2015-8617,于是深入地看了看這個漏洞,在這里對該格式化字符串漏洞進行一些簡要分析,并討論一下利用該漏洞劫持EIP的潛在方法,供各位讀者參考。

PHP7.0.0的這個格式化字符串漏洞是15年12月在exploit-db上發現的。當初發現時,筆者還在北京東北方向的某信息安全公司上班,那時比較忙,并未能深入探究。最近幾天無意間又看到了這個漏洞,發現該漏洞多了一個CVE編號:CVE-2015-8617,于是深入地看了看這個漏洞,在這里對該格式化字符串漏洞進行一些簡要分析,并討論一下利用該漏洞劫持EIP的潛在方法,供各位讀者參考。

1.引言

在PHP中有兩個常見的格式化字符串函數,分別是sppintf()和vsppintf(),它們分別對應sprintf()函數和vsprintf()函數,這兩個函數的聲明為:

  1. PHPAPI int spprintf( char **pbuf, size_t max_len, const char *format, ...);  
  2. PHPAPI int vspprintf(char **pbuf, size_t max_len, const char *format, va_list ap); 

通過其函數聲明可以看到,spprintf()接收可變數量的參數,而vspprintf()僅接收4個參數。

雖然這兩個函數的內部實現原理是類似的,但筆者不打算就此點進行深入討論,如有感興趣讀者,可以看一看《程序員的自我修養》一書。關于格式化字符串漏洞的分析文章普遍集中于sprintf()函數,而在本文中則需要重點討論一下vsprintf()函數,即著重討論下PHP中的vspprintf()函數。

2.漏洞分析

本文所研究的vspprintf()函數在zend_throw_error()函數中,當觸發漏洞時,zend_throw_error()函數由zend_throw_or_error()函數調用。zend_throw_or_error()函數不是很長,所以復制其代碼如下:

  1. static void zend_throw_or_error(int fetch_type, zend_class_entry *exception_ce, const char *format, ...) 
  2.  { va_list va; char *message = NULL; va_start(va, format); zend_vspprintf(&message, 0, format, va); if (fetch_type & ZEND_FETCH_CLASS_EXCEPTION) { zend_throw_error(exception_ce, message); //vul_func //zend_throw_error(exception_ce, "%s", message); patched in the subsequent version } else { zend_error(E_ERROR, "%s", message); } efree(message); va_end(va); } 

在上述代碼段中,觸發漏洞的函數調用已用紅色筆標明出,由于調用時少了一個參數導致觸發了格式化字符串漏洞。該漏洞的補丁也用紅色筆在代碼中標明了。

關于該格式化字符串漏洞,并沒有很多需要分析說明的地方,下面開始分別從windows和linux兩個環境中討論利用該漏洞劫持EIP的方法。

3.windows環境下分析

為了減少在win7環境下的分析難度,筆者暫且把ASLR關掉。若計劃實現穩定的EIP劫持,可能還需要通過其他手段獲取一些模塊基址,當然這PHP7.0.0格式化字符串漏洞本身也可以泄露一部分有用的內存數據。

在windows版本的PHP中,其漏洞函數位于php7ts.dll動態鏈接庫中,構造php頁面如下:

  1. $name="%n%n"; $name::doSomething(); ?> 

通過調試器啟動PHP解析該php頁面,執行到程序崩潰時,通過棧回溯,可以找到vspprintf()函數調用(該函數是導出函數,也可以直接在導出表中找到此函數),在該函數的函數頭下斷點,重新執行,找到即將觸發漏洞的某次調用。此時,觀察棧中的數據:

上圖中,棧頂是函數返回地址,即返回到zend_throw_error()函數中,接下來的是vspprintf()函數的四個參數。其中,0441E890即為va_list類型的參數。

這里需要指出的是,如果是傳統的spprintf()函數的格式化字符串溢出,則只需要不斷地利用%x遞增棧上參數數量,最后利用%n實現覆蓋函數返回地址即可有效地實現劫持EIP。但是此處是vspprintf()函數的,只接受4個參數,所以如果打算繼續劫持EIP,則需要研究一下va_list,va_list在不同環境下的定義略有不同,這里我們可以粗略地定義va_list類型如下:

  1. #define va_list void* 

即認為va_list是一個指向可變數量參數的指針。在vspprintf()函數中,對于%x的處理是直接取va_list指向的內容,如下圖:

其中,0441E890即為va_list的起始地址,通過圖1的第四個參數可以觀察到。對于第一個%x,則輸出0565D3C0;對于第二個%x,則輸出96E436E2;對于第三個%x,則輸出0441E8C4,以此類推下去。

在vspprintf()函數中,對于%n的處理則較為麻煩,它不會像%x那樣直接依次地讀寫下去,而是取va_list指向的參數表的每個參數作為指針,進而覆蓋該指針所指向的內容。結合圖2,具體敘述如下:對于第一個%n,則覆蓋0565D3C0所指向的內容,對于第二個%n,則覆蓋96E436E2所指向的內容,此時PHP就崩潰了,因為該地址是無效的。

此時,是無法直接覆蓋函數的返回地址。為實現劫持EIP的目的,需要在棧上找一個二級指針。該二級指針取值第一次為保存函數返回地址變量的地址,取值兩次為函數返回地址變量的值。但筆者在棧上并沒有找到所需的二級指針,所以,筆者只能選擇構造一個這樣子的指針,其構造方法如下:

1,首先在棧上選擇一個合適位置,該位置存儲內容指向棧的另一個位置,指向位置大于且接近該位置的地址。

復制部分棧內容如下:

0441E890 0565D3C0

0441E894 96E436E2

0441E898 0441E8C4

正如上表所示,0441E8C4就是4字節對齊的,大于且接近0441E898,是一個非常合適的棧位置。

2,通過上一步找到的合適位置,覆蓋0441E8C4的內容,使其指向棧上保存函數返回地址的地址。

在筆者調試時,將其覆蓋為0441E82C,即當前函數返回到vspprintf()函數的返回地址:

3,第一次覆蓋之后,用%x繼續在棧上滑行,直到0441E8C4的位置,此時將會第二次覆蓋0441E82C的內容,使其指向我們需要跳轉的位置,比方說跳轉到04422222的位置。

按照上述思路,其棧空間的內容大致如下:

0441E824 96E40112

0441E828 96E43659

0441E82C 04422222

基于此,筆者嘗試構造php頁面如下:

  1. $name="%71428125x%x%n%x%x%x%x%x%x%x%x%x%14788x%n"; $name::doSomething(); ?> 

當PHP解析該頁面的時候,首先輸出2個%x后,遇到第一個%n,則會覆蓋0441E8C4覆蓋為0441E82C;繼續跳過10個%x后,遇到第二個%n,則會覆蓋0441E82C覆蓋為04422222。

其運行結果如下圖所示:

單步執行后,就會來到04422222的位置:

Windows環境下的分析就到此位置,至于出現的幾個常數:71428125和14788以及10個%x從何而來,相信讀者自己也能想到。至于是否可以在棧上構造一些合適的數據,最后通過ROP實現EXP,這點也留給讀者自己考慮分析一下吧。

4.Linux環境下分析

Linux環境下,同樣先把ASLR關掉,用以減少我們的分析難度。與Windows環境下的分析略有不同,由于Linux環境下的棧基址比較高,如下圖所示:

聲明一個如此之長的字符串,容易出現各種各樣的問題,所以筆者只好放棄直接覆蓋函數返回地址實現劫持EIP的方法。

這里考慮另一種劫持EIP的方法,覆蓋對象虛表的方法(一般情況下有三種常見的方法,在筆者之前的分析《kill.exe溢出漏洞分析與EXP討論》中有提到,感興趣的讀者可以看一下)。構造合適的php頁面,令PHP不崩潰,而是讓其繼續下去的話,就會發現PHP接下來將要調用_object_init_ex()函數,初始化異常對象。該初始化函數會進一步調用object_and_properties_init()函數,而在此函數中,會調用對象虛表中的函數,關鍵代碼段如下:

  1. object_and_properties_init() { … mov ebx, [esp+0Ch+class_type] … mov eax, [ebx+0FCh] … call eax ; call [[esp+0Ch+class_type]+0FCh] … } 

考慮到此時存儲在[esp+0Ch+class_type]+0FCh的值比較小,可以嘗試利用此處的call eax實現劫持EIP。

選擇在第3章節描述的二次覆蓋方法,可以構造棧空間如下:

08948F5C 08945D4C

08948F60 08945D50

08948F64 08955555

基于以上討論,筆者構造php頁面如下:

  1. ini_set("memory_limit""2G"); $name="%143953757x%n%x%x%x%x%x%x%x%x%x%x%50621x%n"; $name::doSomething(); ?> 

當PHP在解析該頁時,第一次遇到%n將會覆蓋8FFFBFCC位置的數據為08948F64;而第二次遇到%n時,將08948F4位置的數據覆蓋為08955555。此后,程序會正常執行,直到call eax指令的位置:

此時,PHP將跳轉到我們指定的地址繼續執行,在上圖中為8955555地址。

值得慶幸的是,在Linux環境中,并沒有Windows環境的CFG保護。如果存在CFG保護,即有/GUARD:CF標記,將可能導致此種利用方式失敗。

Linux環境下的分析也就到此位置,至于出現的幾個常數:143953757和50621以及11個%x從何而來,相信讀者自己也能想到。至于是否可以實現有效的EXP,這點也留給讀者自己考慮分析一下吧。

5.小結

本文簡要地分析了PHP7.0.0格式化字符串漏洞,并在windows和linux兩種不同的環境下,給出了運用該漏洞劫持EIP的方法。但需要指出的是,本文所有的分析都在禁用了ASLR的場景之下進行的,若打算實際利用該漏洞,還需要獲取一些模塊基址等其他有用信息。

責任編輯:武曉燕 來源: 紅黑聯盟
相關推薦

2017-01-16 16:33:06

Python 字符串漏洞

2024-12-09 08:10:00

Python字符串格式化

2017-01-17 15:47:18

2009-11-26 18:36:52

PHP函數sprint

2021-06-09 07:55:18

Python格式化字符串

2024-02-22 09:46:04

C++字符串格式化開發

2009-09-02 15:56:49

C#格式化字符串

2009-09-03 18:05:04

ASP.NET字符串格

2010-02-01 16:46:07

C++格式化字符串

2009-09-03 18:45:06

GridView格式化

2022-05-09 14:04:27

Python字符串格式化輸出

2020-06-28 08:26:41

Python開發工具

2024-03-06 08:41:14

Python字符串格式化工具

2022-03-28 10:56:11

Python字符串格式化

2024-03-28 10:17:03

JDK 17字符串十六進制

2024-05-27 00:10:00

2010-11-26 13:10:17

2009-11-25 09:13:41

PHP數組轉字符串PHP字符串轉數組

2015-12-07 09:23:13

PHP 7速度正式發布

2024-02-26 08:00:00

Pythonformat()字符串
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲精美视频 | 欧美国产激情 | 国产福利在线视频 | 黄色毛片大全 | 亚洲一级毛片 | 久久久久黑人 | 亚洲欧美日韩成人在线 | 在线观看视频91 | 色噜噜狠狠色综合中国 | 男女午夜激情视频 | 欧美日韩国产在线 | 精品国产一区二区三区日日嗨 | 天天干天天干 | 欧美一区二区三区国产 | 亚洲精品一区二区在线观看 | 日韩伦理一区二区 | 成人在线看片 | 午夜精品久久久久久久久久久久久 | 色爱综合 | 一级片av | 日日操夜夜操天天操 | 五月激情综合 | 久久久久国产一区二区三区 | 在线观看亚 | 一区二区三区欧美大片 | 日韩免费 | 欧美色综合天天久久综合精品 | 亚洲视频在线播放 | 91视频电影 | 黄色片免费 | 夜色www国产精品资源站 | 国产四区 | 69性欧美高清影院 | 欧美在线视频一区二区 | 色欧美片视频在线观看 | 日韩伦理电影免费在线观看 | 第一福利社区1024 | 午夜视频网站 | 日韩中文字幕 | 成人av色| 亚洲一区中文 |