您好,登錄后才能下訂單哦!
這篇文章主要講解了“php反序列化之字符串逃逸實例分析”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“php反序列化之字符串逃逸實例分析”吧!
PHP反序列化的字符串逃逸,一共分有兩種情況,情況一:過濾后字符串變多,情況二:過濾后字符變少(本篇文章默認已有反序列化相關知識基礎)
以ctfshow-web262為例講解:
error_reporting(0);class message{ public $from; public $msg; public $to; public $token='user'; public function __construct($f,$m,$t){ $this->from = $f; $this->msg = $m; $this->to = $t; }}$f = $_GET['f'];$m = $_GET['m'];$t = $_GET['t'];if(isset($f) && isset($m) && isset($t)){ $msg = new message($f,$m,$t); $umsg = str_replace('fuck', 'loveU', serialize($msg)); setcookie('msg',base64_encode($umsg)); echo 'Your message has been sent';}highlight_file(__FILE__);
這段代碼,首先要get傳入3個參數,然后序列化傳入的包含有這三個參數的msg函數,之后將里面包含的fuck字符串替換成為loveU,重新賦值給umsg變量,并將該變量base64編碼,設置為cookie
根據題中注釋提示,得到message.php內容,為
highlight_file(__FILE__);include('flag.php');class message{ public $from; public $msg; public $to; public $token='user'; public function __construct($f,$m,$t){ $this->from = $f; $this->msg = $m; $this->to = $t; }}if(isset($_COOKIE['msg'])){ $msg = unserialize(base64_decode($_COOKIE['msg'])); if($msg->token=='admin'){ echo $flag; }}
如果設置了cookie且msg中的token為admin,即可輸出flag
由index.php內容可知,進行了一步replace,導致每輸入一個fuck,就會多生成一位,故我們可以利用這個特點進行字符串逃逸,首先本地嘗試一下
由題可知,我們需要修改原class類中的token值為admin,然后一起傳入三個參數,f,m,t,我們可以利用其中一個參數,這里利用的參數是m,為了避免需要逃逸的字符串太多,我們可以先寫f t參數,本地隨便傳入值,輸出序列化結果
下圖中";s:2:"to";s:1:"1";s:5:"token";s:5:"admin";}
即為我們要逃逸的部分,一共44個字符,故我們需要m輸入44個fuck來逃逸
逃逸成功,上下兩個字符串均為正常的序列化字符串,復制payload前往執行
這道題就用到了php反序列化中字符串逃逸的知識
首先看本地實驗的正常返回結果
當傳入x時,定義的替換函數,將一個x替換為兩個x后得到的
o
l
d
的
值
為
‘
a
:
2
:
i
:
0
;
s
:
4
:
"
h
a
n
x
x
"
;
i
:
1
;
s
:
7
:
"
I
a
m
11
"
;
‘
,
長
度
不
匹
配
,
會
出
現
報
錯
,
進
而
導
致
old的值為`a:2:{i:0;s:4:"hanxx";i:1;s:7:"I am 11";}`,長度不匹配,會出現報錯,進而導致
old的值為‘a:2:i:0;s:4:"hanxx";i:1;s:7:"Iam11";‘,長度不匹配,會出現報錯,進而導致old的進一步反序列化失敗
當然如果我們可以將hanx
的字符串長度由4改為5時,雖然最開始輸入了4個字符但正常執行,并且name由hanx
變為了hanxx
PHP 在反序列化時,底層代碼是以 ;
作為字段的分隔,以 }
作為結尾(字符串除外),并且是根據長度判斷內容的 ,同時反序列化的過程中必須嚴格按照序列化規則才能成功實現反序列化 。
由上面的輸出結果可以看到x被換成了xx,然而序列化的結果中數值仍然是原來的4,我們可以根據字符串在經過過濾函數后字符串變多的特點找到漏洞
漏洞原理:我們可以利用等長的可以用來閉合的字符串傳入數據,假設我們需要傳入age為woaini,故我們可以利用";i:1;s:6:"woaini";}
這個字符串,該字符串一共20位,我們可以通過補充20個x來實現字符串逃逸,最終構造的payload如下:
name=maoxxxxxxxxxxxxxxxxxxxx";i:1;s:6:"woaini";}
因為題中已知會將一個x替換為兩個x,故我們可以令x的數量與上面payload中";i:1;s:6:"woaini";}
的數量相等,這樣既滿足了,序列化之前,name的長度為40(不算前面的mao),又滿足了替換后x擴大一倍,導致引號閉合,那么長度仍為40位,但是我們通過字符串逃逸,傳入了想要的age的值
由圖可知,傳入的age值成功溢出,字符串逃逸成功!
本地測試如上,初始時name和sign沒有賦值,number為2020,存在字符串逃逸漏洞,假設我們通過構造反序列化字符串逃逸,使number值由2020變為2002為成功,則可以嘗試構造序列化字符串
首先代碼中通過get傳入name和sign參數,之后進行反序列化,并將反序列化的結果進行字符串替換,輸出替換后的結果,把反序列化的結果賦值給fake,分別輸出經過改造后的name、sign、number值
正常輸入得到正常輸出:
當輸入包含有lemon或者shy時,會替換為空,字符串變短導致代碼中反序列化失敗,輸出錯誤:
在上面的反序列化字符串中,控制number值的字符串為";s:6:"number";s:4:"2020";}
總長為27,所以我們需要在name變量中設置被過濾的字符進行置空,該置空部分的字符串,需要保證我們在第二個變量輸入人為補充的序列化字符串時,位數正好,不報錯
這里sign輸入了YKing";s:4:"sign";s:4:"evan";s:6:"number";s:4:"2002";}
其中,YKing用于湊字數,補充前面的name變量的長度,保證后續可以正常反序列化,然后輸入了手工構造的sign變量,并賦值,值為多少無所謂,保證序列化正確即可,最后將我們想要的number值2002,補充到sign變量中,并通過}
閉合,導致原題中的2020無法反序列化,進而實現number值的覆蓋
name變量的長度,保證后續可以正常反序列化,然后輸入了手工構造的sign變量,并賦值,值為多少無所謂,保證序列化正確即可,最后將我們想要的number值2002,補充到sign變量中,并通過}
閉合,導致原題中的2020無法反序列化,進而實現number值的覆蓋
感謝各位的閱讀,以上就是“php反序列化之字符串逃逸實例分析”的內容了,經過本文的學習后,相信大家對php反序列化之字符串逃逸實例分析這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。