- Phar反序列化
- 什么是phar文件
- 常见的流包装器
- phar文件必要的结构组成
- 受影响的文件操作函数
- 漏洞利用条件
- phar生成
- 绕过方式
- 例题
- SWPUCTF 2018]SimplePHP
- [NSSCTF]prize_p1
- PHP对象
- 绕过异常
- phar://反序列化
- 处理getflag()类
- 签名修改
- 参考文献
phar文件本质上是一种压缩文件,会以序列化的形式存储用户自定义的meta-data。当受影响的文件操作函数调用phar文件时,会自动反序列化meta-data内的内容。(漏洞利用点)
什么是phar文件在软件中,PHAR(PHP归档)文件是一种打包格式,通过将许多PHP代码文件和其他资源(例如图像,样式表等)捆绑到一个归档文件中来实现应用程序和库的分发
php通过用户定义和内置的“流包装器”实现复杂的文件处理功能。内置包装器可用于文件系统函数,如(fopen(),copy(),file_exists()和filesize()。 phar://就是一种内置的流包装器
常见的流包装器file:// — 访问本地文件系统,在用文件系统函数时默认就使用该包装器
http:// — 访问 HTTP(s) 网址
ftp:// — 访问 FTP(s) URLs
php:// — 访问各个输入/输出流(I/O streams)
zlib:// — 压缩流
data:// — 数据(RFC 2397)
glob:// — 查找匹配的文件路径模式
phar:// — PHP 归档
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — 音频流
expect:// — 处理交互式的流
phar文件必要的结构组成
stub:phar文件的标志,必须以 xxx __HALT_COMPILER();?> 结尾,否则无法识别。xxx可以为自定义内容。
manifest:phar文件本质上是一种压缩文件,其中每个被压缩文件的权限、属性等信息都放在这部分。这部分还会以序列化的形式存储用户自定义的meta-data,这是漏洞利用最核心的地方。
content:被压缩文件的内容
signature (可空):签名,放在末尾。
受影响的文件操作函数-
phar可以上传到服务器端(存在文件上传)
-
要有可用的魔术方法作为“跳板”。
-
文件操作函数的参数可控,且
:
、/
、phar
等特殊字符没有被过滤
得到phar文件,修改后缀为jpg,上传。
得到文件名的两种方法
方法1:
function upload_file_do()
{
global $_FILES;
$filename = md5($_FILES["file"]["name"] . $_SERVER["REMOTE_ADDR"]) . ".jpg";
//mkdir("upload",0777);
if (file_exists("upload/" . $filename)) {
unlink($filename);
}
move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $filename);
echo 'alert("上传成功!");';
}
文件名是$filename = md5($_FILES["file"]["name"] . $_SERVER["REMOTE_ADDR"]) . ".jpg";
路径是url+/upload/文件名
(但是这种方法感觉不对,得不出flag,个人做的时候出现问题了)
方法2:
直接访问,URL+/upload/可以查看文件名
最后直接
file=phar://upload/文件名,就可以得到flag
[NSSCTF]prize_p1
考点:
- phar反序列化
- 绕过Error异常
- phar签名修改
- GC进制(垃圾回收系统)
wp:
打开,直接审计代码
config == 'w') {
$data = $_POST[0];
if (preg_match('/get|flag|post|php|filter|base64|rot13|read|data/i', $data)) {
die("我知道你想干吗,我的建议是不要那样做。");
}
file_put_contents("./tmp/a.txt", $data);
} else if ($this->config == 'r') {
$data = $_POST[0];
if (preg_match('/get|flag|post|php|filter|base64|rot13|read|data/i', $data)) {
die("我知道你想干吗,我的建议是不要那样做。");
}
echo file_get_contents($data);
}
}
}
if (preg_match('/get|flag|post|php|filter|base64|rot13|read|data/i', $_GET[0])) {
die("我知道你想干吗,我的建议是不要那样做。");
}
unserialize($_GET[0]);
throw new Error("那么就从这里开始起航吧");
分析代码,其中getflag
的__destruct
方法触发即可得到flag,A
的__destruct
方法触发即可写/tmp/a.txt
或者任意文件读。
__destruct
是PHP对象的一个魔术方法,称为析构函数,顾名思义这是当该对象被销毁的时候自动执行的一个函数。其中以下情况会触发__destruct
- 主动调用
unset($obj)
- 主动调用
$obj = NULL
- 程序自动结束
除此之外,PHP还拥有垃圾回收Garbage collection
即我们常说的GC
机制。
PHP中GC
使用引用计数和回收周期自动管理内存对象,那么这时候当我们的对象变成了“垃圾”,就会被GC
机制自动回收掉,回收过程中,就会调用函数的__destruct
。
刚才我们提到了引用计数,其实当一个对象没有任何引用的时候,则会被视为“垃圾”,即
$a = new show();
这是一个show
对象,被a
变量应用,所以它不是“垃圾”。如果是
new show();
或
$a = new show();$a = 2;
上面都是对象没有被饮用或开始有引用之后失去了引用的情况,我们可以考虑下列实例代码。
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?