当前位置: 首页 > news >正文

PHP 反序列化漏洞:__PHP_Incomplete_Class 与 serialize(unserialize($x)) !== $x;

文章目录

  • 参考
  • 环境
  • 声明
  • __PHP_Incomplete_Class
      • 灵显
      • 为什么需要 __PHP_Incomplete_Class?
      • 不可访问的属性
  • serialize(unserialize($x)) === $x;
  • serialize(unserialize($x)) !== $x;
      • 雾现
      • __PHP_Incomplete_Class 对象与其序列化文本的差异
      • 试构造 __PHP__Incomplete_Class 对象的序列化文本
      • serialize() 函数在处理 __PHP_Incomplete_Class 对象时所进行的特殊操作
      • 雾散
      • 下限

参考

项目描述
搜索引擎BingGoogle
AI 大模型文心一言通义千问讯飞星火认知大模型ChatGPT
PHP 手册PHP Manual
EkiPHP序列化冷知识

环境

项目描述
PHP8.0.0
PHP 编辑器PhpStorm 2023.1.1(专业版)

声明

实际上 __PHP_Incomplete_Class 是一个类,暂且使用 __PHP_Incomplete_Class 对象 来指代 __PHP_Incomplete_Class 类的实例对象。

__PHP_Incomplete_Class

灵显

在 PHP 中,当你尝试将序列化文本进行反序列化操作以获得一个 对象 时,若 与序列化文本相关联的类还没有在当前 PHP 上下文中被定义或包含时,PHP 就会使用 __PHP_Incomplete_Class 对象来代替这个对象。对此,请参考如下示例:

<?php$result = unserialize('O:7:"MyClass":2:{s:4:"name";s:8:"RedHeart";s:6:"nation";s:5:"China";}');
var_dump($result);

执行效果

由于在使用 unserialize() 函数将序列化文本反序列化为对象时,相关的类并尚未被定义或被包含,于是 PHP 使用 __PHP_Incomplete_Class 对象作为反序列化操作的结果。

object(__PHP_Incomplete_Class)#1 (3) {["__PHP_Incomplete_Class_Name"]=>string(7) "MyClass"["name"]=>string(8) "RedHeart"["nation"]=>string(5) "China"
}

__PHP_Incomplete_Class 对象中包含了 序列化文本尝试创建的对象的信息,包括了该对象 所属类的名称 以及 该对象的属性及其值

为什么需要 __PHP_Incomplete_Class?

PHP 通过这种方式来 防止因错误导致程序的崩溃,提高程序的可靠性与可用性。如果 PHP 试图反序列化一个不存在的类,而没有任何 后备机制,那么这可能会导致 致命错误或者不可预期的行为。通过使用 __PHP_Incomplete_Class 对象,PHP 可以告诉您在反序列过程中出现的问题并继续运行。

不可访问的属性

__PHP_Incomplete_Class 是一个特殊的对象,当你试图访问这个对象的属性时,PHP 将抛出 Warning 异常。当你尝试访问这个 不完整 的对象的属性时,PHP 会 认为这是不安全的(所属类的定义并未在当前上下文中给出。记住,不要随便接收陌生人给的东西🤐),并给出警告。对此,请参考如下示例:

<?php$result = unserialize('O:7:"MyClass":2:{s:4:"name";s:8:"RedHeart";s:6:"nation";s:5:"China";}');var_dump($result);# 尝试访问 __PHP_Incomplete_Class 对象的属性
var_dump($result -> name);

执行效果

PHP Warning:  main(): The script tried to access a property on an incomplete object. Please ensure that the class definition "MyClass" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition in C:\test.php on line 9
object(__PHP_Incomplete_Class)#1 (3) {["__PHP_Incomplete_Class_Name"]=>string(7) "MyClass"["name"]=>string(8) "RedHeart"["nation"]=>string(5) "China"
}Warning: main(): The script tried to access a property on an incomplete object. Please ensure that the class definition "MyClass" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide an autoloader to load the class definition in C:\test.php on line 9
NULL

serialize(unserialize($x)) === $x;

serialize(unserialize($x)) === $x; 中,$x 为一个序列化文本,将一个序列化文本通过 unserialize() 进行反序列化操作后将得到该序列化文本所描述的数据格式,再将这数据格式用序列化文本进行描述将得到原内容即 $x

这一操作就像执行了 1 + 1 后再执行了 1 - 1 ,两个操作相互抵消。在对数据进行处理前与数据进行处理后,数据相等。所以毫无悬念的 serialize(unserialize($x) ) === $x;。对此,请参考如下示例:

<?php$serialize_text = 'O:7:"MyClass":2:{s:4:"name";s:8:"RedHeart";s:6:"nation";s:5:"China";}';var_dump(serialize(unserialize($serialize_text)) === $serialize_text);

执行效果

bool(true)

serialize(unserialize($x)) !== $x;

雾现

__PHP_Incomplete_Class 的出现使 serialize(unserialize($x)) !== $x; 也成为了可能。对此,请先参考如下示例,稍后我将对其进行解释。

<?php$serialize_text = 'O:22:"__PHP_Incomplete_Class":2:{s:4:"name";s:8:"RedHeart";s:6:"nation";s:5:"China";}';var_dump(serialize(unserialize($serialize_text)) !== $serialize_text);

执行效果

bool(true)

__PHP_Incomplete_Class 对象与其序列化文本的差异

序列化文本

O:7:"MyClass":2:{s:4:"name";s:8:"RedHeart";s:6:"nation";s:5:"China";}

对象 __PHP_Incomplete_Class

object(__PHP_Incomplete_Class)#1 (3) {["__PHP_Incomplete_Class_Name"]=>string(7) "MyClass"["name"]=>string(8) "RedHeart"["nation"]=>string(5) "China"
}

序列化文本 与其对应的 __PHP_Incomplete_Class 对象存在如下差异:

  1. 所属类名称
    序列化文本在反序列化为 __PHP_Incomplete_Class 对象后,对象所属类的名称由 MyClass 变为了其 __PHP__Incomplete_Class
  2. 对象的属性个数
    序列化文本所描述的属性个数要比 __PHP_Incomplete_Class 对象的属性个数少 1
  3. __PHP_Incomplete_Class_Name 属性
    __PHP_Incomplete_Class 对象中包含了 __PHP_Incomplete_Class_Name 属性,而其序列化文本中则没有与该属性相关的描述。

试构造 __PHP__Incomplete_Class 对象的序列化文本

__PHP__Incomplete_Class 与其序列化文本存在差异的原因是 PHP 发现了这个对象是一个 __PHP_Incomplete_Class 对象。而 PHP 是通过检查被序列化对象所属类的名称发现的。如果我们尝试描述一个所属类为 __PHP_Incomplete_Class 的对象的序列化文本,这会发生什么有趣的事情呢?为此,请参考如下示例:

<?phpvar_dump(unserialize('O:22:"__PHP_InComplete_Class":2:{s:4:"name";s:8:"RedHeart";s:6:"nation";s:5:"China";}'));

执行效果

由于 PHP 上下文中已经包含了 __PHP_Incomplete_Class 的类定义,所以当我们将序列化文本进行反序列化后并没有产生一个描述 __PHP_Incomplete_Class 对象的另一个 __PHP_Incomplete_Class 对象。

object(__PHP_Incomplete_Class)#2 (2) {["name"]=>string(8) "RedHeart"["nation"]=>string(5) "China"
}

如果我们尝试将这个人为构造的 __PHP_Incomplete_Class 对象进行序列化操作将会发生什么呢?对此,请参考如下示例:

<?phpvar_dump(serialize(unserialize('O:22:"__PHP_Incomplete_Class":2:{s:4:"name";s:8:"RedHeart";s:6:"nation";s:5:"China";}')));

执行效果

string(85) "O:22:"__PHP_Incomplete_Class":1:{s:4:"name";s:8:"RedHeart";s:6:"nation";s:5:"China";}"

神奇的事情发生了。在将人为构造的 __PHP_Incomplete_Class 对象进行序列化后,序列化文本中描述对象属性个数的数值由原先的 2 变为了 1

serialize() 函数在处理 __PHP_Incomplete_Class 对象时所进行的特殊操作

unserialize() 在发现当前 PHP 上下文中没有包含相关类的类定义时将创建一个 __PHP_Incomplete_Class 对象。而 serialize() 在发现需要进行序列化的对象是 __PHP_Incomplete_Class 后,将对其进行 特殊处理 以得到描述实际对象而非 __PHP_Incomplete_Class 对象的序列化文本,而这里就包含了 将属性的描述值减一 这一步。
那么对象所属类的名称是否会发生替换,序列化文本中的 __PHP_Incomplete_Class_Name 是否会被自动删除以使得序列化文本中的属性个数描述值与实际相符呢?对此,请参考如下示例:

<?phpvar_dump(serialize(unserialize('O:22:"__PHP_Incomplete_Class":3:{s:27:"__PHP_Incomplete_Class_Name";s:7:"MyClass";s:4:"name";s:8:"RedHeart";s:6:"nation";s:5:"China";}')));

执行效果

string(69) "O:7:"MyClass":2:{s:4:"name";s:8:"RedHeart";s:6:"nation";s:5:"China";}"

结合前面观察到的种种现象,我们可以总结出 serialize() 函数对 __PHP_Incomplete_Class 对象执行了如下 特殊操作(操作描述顺序并非 serialize 函数的实际操作顺序)

  1. __PHP_Incomplete_Class 对象中的 属性个数减一 并将其作为序列化文本中 对实际对象属性个数的描述值
  2. __PHP_Incomplete_Class 对象的 __PHP_Incomplete_Class_Name 作为序列化文本中 对象所属类的描述值。若未从 __PHP_Incomplete_Class 对象 中检查到 __PHP_Incomplete_Class_Name 属性,则跳过此步。
  3. __PHP_Incomplete_Class 对象的序列化文本中对 __PHP_Incomplete_Class_Name 属性的描述删去。若没有发现相关描述,则跳过此步。

雾散

回到 serialize(unserialize($x)) !== $x;。让我们再尝试对如下示例进行分析:

<?php$serialize_text = 'O:22:"__PHP_Incomplete_Class":2:{s:4:"name";s:8:"RedHeart";s:6:"nation";s:5:"China";}';var_dump(serialize(unserialize($serialize_text)) !== $serialize_text);

执行效果

bool(true)

由于 serialize 函数将对 __PHP_Incomplete_Class 进行特殊操作,故反序列化后得到的 __PHP_Incomplete_Class 对象再进行序列化操作后,序列化文本中对属性个数的描述值将为 1 而不是 2。于是导致了 serialize(unserialize($x)) !== $x;

下限

serialize() 函数对 __PHP_Incomplete_Class 对象执行特殊操作的过程中,若 __PHP_Incomplete_Class 对象中的属性个数为零,则 __PHP_Incomplete_Class 的序列化结果中的属性个数描述值也将为零,两者不会存在 1 的差距。对此,请参考如下示例:

<?phpvar_dump(serialize(unserialize('O:22:"__PHP_Incomplete_Class":0:{}')));

执行效果

string(34) "O:22:"__PHP_Incomplete_Class":0:{}"

对象(由反序列化操作得到的对象)所属类为 __PHP_Incomplete_Class 且该对象的属性个数 不为零 时,serialize(unserialize($x)) !== $x; 恒成立,仅当该对象的属性个数 为零 时, serialize(unserialize($x)) === $x; 成立。

相关文章:

PHP 反序列化漏洞:__PHP_Incomplete_Class 与 serialize(unserialize($x)) !== $x;

文章目录 参考环境声明__PHP_Incomplete_Class灵显为什么需要 __PHP_Incomplete_Class&#xff1f;不可访问的属性 serialize(unserialize($x)) $x;serialize(unserialize($x)) ! $x;雾现__PHP_Incomplete_Class 对象与其序列化文本的差异试构造 __PHP__Incomplete_Class 对象…...

TempleteMethod

TempleteMethod 动机 在软件构建过程中&#xff0c;对于某一项任务&#xff0c;它常常有稳定的整体操作结构&#xff0c;但各个子步骤却有很多改变的需求&#xff0c;或者由于固有的原因 &#xff08;比如框架与应用之间的关系&#xff09;而无法和任务的整体结构同时实现。如…...

1558. 得到目标数组的最少函数调用次数

1558. 得到目标数组的最少函数调用次数 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a; 原题链接&#xff1a; 1558. 得到目标数组的最少函数调用次数 https://leetcode.cn/problems/minimum-numbers-of-function-calls-to-make-target…...

子域名扫描, 后台扫描

子域名和后台扫描 一, 子域名扫描 在渗透测试的早期阶段&#xff0c;子域名扫描是一个非常重要的步骤&#xff0c;它有助于识别目标组织的网络结构和在线资源。 子域名扫描应该在获得适当的权限和授权的情况下进行&#xff0c;以确保所有活动都是合法和合规的。 1. 原因与目…...

毛玻璃带有光影效果的卡片

效果展示 页面结构组成 从效果展示可以看到&#xff0c;页面的主要元素是卡片&#xff0c;卡片的内容呈现上都是比较常规的布局&#xff0c;只是卡片上带有光影效果。 CSS / JavaScript 知识点 transformVanillaTilt.js 使用 页面基础结构实现 <div class"contain…...

【Java】面向过程和面向对象思想||对象和类

1.面向过程和面向对象思想 两者都贯穿于软件分析、设计和开发的各个阶段&#xff0c;对应面向对象就分别称为面向对象的分析&#xff08;OOA&#xff09;、面向对象的设计&#xff08;OOD&#xff09;和面向对象的编程&#xff08;OOP&#xff09;。C语言是一种典型的面向过程语…...

孤举者难起,众行者易趋,openGauss 5.1.0版本正式发布!

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…...

软考——软件设计师中级2023年11月备考(1.计算机组成原理)

一、计算机组成原理 1.数据的表示 1.1 十进制转R进制 方法&#xff1a;对十进制数除R取余&#xff0c;最后对余数取倒序 如&#xff1a; 1.2 原码反码补码 1.3 浮点数 1.4 校验码 —— 海明码 &#xff08;非重点&#xff0c;了解即可&#xff09; 海明码的构成方法&…...

前端JavaScript入门到精通,javascript核心进阶ES6语法、API、js高级等基础知识和实战 —— Web APIs(四)

思维导图 一、日期对象 1.1 实例化 实例化&#xff0c;默认得到当前时间&#xff0c;也可以指定时间 1.2 日期对象方法 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible&q…...

【前端】HTML5 Audio 预加载 按照队列顺序播放音频, 可以陆续往队列中加内容

【前端】Audio 按照队列顺序播放音频, 可以陆续往队列中加内容 var 音频库 {} var 当前音频集合 [] /*** 将文本添加到队列中* 持续去播放* 播放过的音频会自动从队列中删除* * 已规划* 要保障同时进行加载的数据不能超过5个(线程池 5)* * param 文本*/播放音频队列(文本){i…...

【单片机】13-实时时钟DS1302

1.RTC的简介 1.什么是实时时钟&#xff08;RTC&#xff09; &#xff08;rtc for real time clock) &#xff08;1&#xff09;时间点和时间段的概念区分 &#xff08;2&#xff09;单片机为什么需要时间点【一定的时间点干什么事情】 &#xff08;3&#xff09;RTC如何存在于…...

springboot和vue:十三、VueX简介与安装与推荐视频+前端数据模拟MockJS

VueX简介与安装与推荐视频 VueX用于管理分散在vue各个组件中的数据。每一个VueX的核心都是一个store&#xff0c;当store中的状态发生变化时&#xff0c;与之绑定的视图也将重新渲染。store中的状态不允许被直接修改&#xff0c;只能显示提交mutationVueX中有五个重要的概念&a…...

[React] Zustand状态管理库

文章目录 1.Zustand介绍2.创建一个store3.使用方法3.1 获取状态3.2 更新状态3.3 访问存储状态3.4 处理异步数据3.5 在状态中访问和存储数组3.6 持续状态 4.总结 1.Zustand介绍 状态管理一直是现代程序应用中的重要组成部分, Zustand使用 hooks 来管理状态无需样板代码。 更少…...

【ChatGPT】ChatGPT发展历史

更多优质文章请看底部&#xff1a;ChatGPT与日本首相交流核废水事件-精准Prompt... hello&#xff0c;我是小索奇&#xff0c;在AI日益庞大的环境下&#xff0c;接下来将为大家不断的ChatGPT学习 ChatGPT使用了 Transformer 结构&#xff0c;建立在 OpenAI的 GPT-3.5 大型语言模…...

分布式文件存储系统Minio实战

分布式文件系统应用场景 互联网海量非结构化数据的存储需求电商网站&#xff1a;海量商品图片视频网站&#xff1a;海量视频文件网盘 : 海量文件社交网站&#xff1a;海量图片 1. Minio介绍 MinIO 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存…...

【MySQL】MySQL 官方安装包形式

MySQL 官方提供3种包&#xff1a; 1. 源码包 mysql-5.7.42.tar.gz mysql-5.7.42-aarch64.tar.gz http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.34.tar.gz http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.42.tar.gz需要用户根据自己的CPU架构选择对应的…...

使用sqlmap获取数据步骤

文章目录 1.使用sqlmap获取所有数据库2.使用sqlmap获取当前连接数据库3.使用sqlmap获取当前数据库下所有表名4.使用sqlmap获取当前数据库下某个表下所有列名5.使用sqlmap获取当前数据库下某个表下指定字段的数据6.测试当前用户是否是管理员7.使用burpsqlmap批量检测8.脱库命令9…...

[论文笔记]GLM

引言 今天带来论文GLM: General Language Model Pretraining with Autoregressive Blank Infilling的笔记。论文中文标题为 通用语言模型预训练与自回归填空。 有很多不同类型的预训练架构,包括自编码模型(BERT、RoBERTa、ALBERT)、自回归模型(GPT系列)以及编码器-解码器模型…...

漏洞扫描环境:win10系统用VMware Workstation打开虚拟机若干问题

win10系统用VMware Workstation打开虚拟机若干问题 一 .VMware打开虚拟机就蓝屏重启怎么解决&#xff1f;一. VMware打开虚拟机就蓝屏重启怎么解决&#xff1f;方法一&#xff1a;1、同时按下CTRLSHIFTESC打开任务管理器功能&#xff0c;之后依次点击-详细信息-性能后出现下列界…...

OpenCV实现模板匹配和霍夫线检测,霍夫圆检测

一&#xff0c;模板匹配 1.1代码实现 import cv2 as cv import numpy as np import matplotlib.pyplot as plt from pylab import mplmpl.rcParams[font.sans-serif] [SimHei]#图像和模板的读取 img cv.imread("cat.png") template cv.imread(r"E:\All_in\o…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...

go 里面的指针

指针 在 Go 中&#xff0c;指针&#xff08;pointer&#xff09;是一个变量的内存地址&#xff0c;就像 C 语言那样&#xff1a; a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10&#xff0c;通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...