前言
最近学习PHP反序列化的时候遇到了yii2反序列化的利用,就顺便搭了一下环境,跟着网上各种大师傅们的文章进行了一波复现和学习,提高自己代码审计的能力。
漏洞出现在yii2.0.38之前的版本中,在2.0.38进行了修复,CVE编号是CVE-2020-15148:
Yii 2 (yiisoft/yii2) before version 2.0.38 is vulnerable to remote code execution if the application calls
unserialize()on arbitrary user input. This is fixed in version 2.0.38. A possible workaround without upgrading is available in the linked advisory.
至于环境的安装,直接从github上找yii2,下载下来2.0.37版本,然后修改config/web.php文件里cookieValidationKey的值,随便什么值都行。然后正常的部署一下就行了,就像thinkphp那样,根目录是/yii2/web。
CVE-2020-15148复现
这个反序列化的入口点是一个__destruct(),在BatchQueryResult类中

继续跟进一下reset():

但是继续跟进close(),发现没有什么利用的办法,正常可能链就断了,但是大师傅们的思路就是不一样,这里的_dataReader是可控的,那么调用了close的方法,是不是可以想办法触发__call呢?
全局搜索一下__call,最后在\vendor\fzaninotto\faker\src\Faker\Generator.php找到了一个合适的__call方法:

因为close是无参方法,所以__call中的$method是close,attributes为空。继续跟进format方法:

看到call_user_func_array的时候肯定就很兴奋了。继续跟进一下getFormatter:
public function getFormatter($formatter)
{
if (isset($this->formatters[$formatter])) {
return $this->formatters[$formatter];
}
foreach ($this->providers as $provider) {
if (method_exists($provider, $formatter)) {
$this->formatters[$formatter] = array($provider, $formatter);
return $this->formatters[$formatter];
}
}
throw new \InvalidArgumentException(sprintf('Unknown formatter "%s"', $formatter));
}
因为$this->formatters是可控的,因此getFormatter方法的返回值也是我们可控的,因此call_user_func_array($this->getFormatter($formatter), $arguments);中,回调函数是我们可控的,但是$arguments为空,所以相当于我们现在能干两件事,可以调用yii2中任意的一个无参方法,或者调用原生php的类似phpinfo()这样的无参方法,但是第二种肯定不能RCE,因此还要在yii2中已有的无参方法中进行挖掘:
function \w+\(\)

但是无参函数实在是太多了,一个一个挖起来实在费力。这里就是大师傅们的经验和智慧了,直接搜索含有call_user_function的无参函数:
function \w+\(\) ?\n?\{
(.*\n)+call_user_func
但是这个正则在我这里查不到,我感觉我这里的phpstorm搜索好像有点问题。
最后找到的rest/CreateAction.php以及rest/IndexAction.php都很好用。这里分析一下IndexAction.php:
主要是它的run方法:

太直接了,$this->checkAccess和$this->id都是我们可控的,相当于直接函数名和参数都可控了,反序列化链至此结束。
理一下就是这样:
class BatchQueryResult ->__destruct()
↓↓↓
class BatchQueryResult ->reset()
↓↓↓
class Generator ->__call()
↓↓↓
class Generator ->format()
↓↓↓
class Generator ->getFormatter()
↓↓↓
class IndexAction ->run()

本文详细介绍了Yii2框架在2.0.38之前版本存在的反序列化漏洞,通过复现CVE-2020-15148,展示了如何利用__destruct、__call、__toString等魔术方法进行远程代码执行。文章讲解了不同利用链的挖掘过程,包括BatchQueryResult、RunProcess和DiskKeyCache类,并提供了相应的POC构造,揭示了在不同版本中寻找和利用反序列化链的思路。
最低0.47元/天 解锁文章
6681





