首先給出原生的php程式碼,很簡單不做過多的解釋,就是把反序列化後的一個x替換成為兩個
<?php
function change($str){
return str_replace("xx","3",$str);
}
$name = $_GET['name'];
$age = "I am 11";
$arr = array($name,$age);
echo "反序列化字串:";
var_dump(serialize($arr));
echo "<br/>";
echo "過濾後:";
$old = change(serialize($arr));
$new = unserialize($old);
var_dump($new);
echo "<br/>此時,age=$new[1]";
正常情況下
如果此時多傳入一個x的話會怎樣,毫無疑問反序列化失敗,由於溢位(s本來是4結果多了一個字元出來),我們可以利用這一點實現字串逃逸
首先看看效果
我們傳入name=hggxxxxxxxxxxxxxxxxxxxx";i:1;s:6:"woaini";}
";i:1;s:6:"woaini";}
這一部分一共二十個字元
由於一個x會被替換為兩個,我們輸入了一共20個x,現在是40個,多出來的20個x其實取代了我們的這二十個字元";i:1;s:6:"woaini";}
,從而造成";i:1;s:6:"woaini";}
的溢位,而"
閉合了前串,使得我們的字串成功逃逸,可以被反序列化,輸出woaini
Add:
最後的;}
閉合反序列化全過程導致原來的";i:1;s:7:"I am 11";}"
被捨棄,不影響反序列化過程`
<?php
function change($str){
return str_replace("xx","3",$str);
}
$arr['name'] = $_GET['name'];
$arr['age'] = $_GET['age'];
echo "反序列化字串:";
var_dump(serialize($arr));
echo "<br/>";
echo "過濾後:";
$old = change(serialize($arr));
var_dump($old);
echo "<br/>";
$new = unserialize($old);
var_dump($new);
echo "<br/>此時,age=";
echo $new['age'];
這是正常的情況,
加了兩個x後
老規矩看看最後的效果
簡單來說,就是前面少了一半,導致後面的字元被吃掉,從而執行了我們後面的程式碼;
我們來看,這部分是age序列化後的結果
由於前面是40個x所以導致少了20個字元,所以需要後面來補上,這一部分剛好20個,後面由於有"
閉合了前面因此後面的引數就可以由我們自定義執行了