PHP 反序列化漏洞:身份标识

news2024/11/28 11:33:32

文章目录

  • 参考
  • 环境
  • 访问修饰符
      • 访问修饰符
      • PHP 与访问修饰符
  • 手写身份标识
      • 身份标识
      • 定义身份标识
      • 控制字符 NUL
          • 在 PHP 中如何表示空字符?
      • 通过空字符尝试构建包含非公共属性对象的序列化文本
  • 空字符的传输
      • 控制字符的不可打印性
      • 结论
      • 另辟蹊径
          • URL 字符编码
            • 将非 ASCII 字符文本转换为 ASCII 字符文本
            • 去除语义
            • 将不可见字符(如空格)转换为可见文本
          • URL Encode

参考

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

环境

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

访问修饰符

访问修饰符

访问修饰符在面向对象编程中起着重要的作用,它们提供了 对类的属性和方法的访问级别控制。访问修饰符能够为你的程序带来以下优点:

  1. 封装性(Encapsulation)
    访问修饰符允许将类的内部实现细节隐藏起来,仅暴露必要的公有接口给外部使用。这样可以有效地封装数据和行为,提高代码的可维护性和可重用性。

  2. 访问控制(Access Control)
    通过访问修饰符,可以控制类的成员对外部的可见性和可访问性。不同的访问修饰符可以限制属性和方法的访问范围,只允许特定的代码段访问,从而提供了更好的安全性和数据保护。

PHP 与访问修饰符

PHP 支持三种访问修饰符:publicprotected 以及 private,这些修饰符所提供的访问级别具体如下。

修饰符
(Modifier)
访问级别
(Access Level)
类内部
(Inside Class)
子类
(In Subclass)
外部
(Outside Class)
public公有可访问可访问可访问
protected受保护可访问可访问不可访问
private私有可访问不可访问不可访问

注:

在 PHP 中,访问修饰符是可以省略的,但这仅仅针对于类中的方法而言。默认情况下,如果没有指定访问修饰符,方法都将被视为公有成员。

手写身份标识

身份标识

在 PHP 中,当对象被序列化时,对象的 非公共属性的名称会被特殊处理以表示其可见性(访问修饰符)。对此,请参考如下示例:

<?php


class MyClass
{
    # 私有属性
    private $name = 'RedHeart';
    # 受保护属性
    protected $nation = 'China';
}

var_dump(serialize(new MyClass()));

执行效果

string(82) "O:7:"MyClass":2:{s:13:" MyClass name";s:8:"RedHeart";s:9:" * nation";s:5:"China";}"

MyClass 类中的私有属性名称 name 在转化为序列化文本后,成了 s:13:" MyClass name;",相比原先的 name 增加了两个空格(实际上是 控制字符 NUL,无法通过空格进行代替)及所属类的名称 MyClass

这样的处理方式是为了 在反序列化对象时能够正确地还原属性的可见性。当 PHP 在反序列化时遇到这些特殊的前缀,PHP 会 知道如何正确地设置属性的可见性。公共属性不会有这种特殊处理,它们在序列化后的文本中保持原始的属性名。

定义身份标识

身份标识即 对象的属性所使用的访问修饰符在序列化文本中的体现,私有属性与受保护属性的身份标识分别是 NUL所属类的名称NULNUL*NUL ,公有属性则无身份标识以与前两者相区分。

控制字符 NUL

控制字符 NUL 也被称为 空字符,是 ASCII 表中的第一个字符,其 十进制值0。在 ASCII 表中,控制字符是一系列 非打印字符用于控制硬件设备或通信协议的行为,而 NUL 的主要作用是标记字符串的结束

在 PHP 中如何表示空字符?

在 PHP 中,你可以通过转移字符 \0 表示空字符 NUL。但需要注意的是,在 PHP 中,转义字符仅有在 双引号 内才会被认为是转义字符,若转义字符存在于 单引号 中,则该转义字符将被视为普通字符。对此,请参考如下示例:

<?php


# 位于单引号中的 “转义字符”
var_dump('\0');
var_dump('Hello\0World');

# 位于双引号中的 转义字符
var_dump("\0");
var_dump("Hello\0World");

执行效果

string(2) "\0"
string(12) "Hello\0World"
string(1) " "
string(11) "Hello World"

通过空字符尝试构建包含非公共属性对象的序列化文本

既然知道了如何在 PHP 中表示 空字符,那么我们就能够通过这一特性来 手写(不使用 serialize() 函数来获取需要使用到的 PHP 序列化文本) 包含非公共属性对象的序列化文本。对此,请参考如下示例:

<?php


class MyClass {}

# 构造需要使用到的序列化文本
$serialize_text = 'O:7:"MyClass":2:{s:13:"' . "\0MyClass\0" . 'name";s:8:"RedHeart";s:9:"' . "\0*\0" . 'nation";s:5:"China";}';

# 对序列化文本执行反序列化操作
var_dump(unserialize($serialize_text));

执行效果

object(MyClass)#1 (2) {
  ["name":"MyClass":private]=>
  string(8) "RedHeart"
  ["nation":protected]=>
  string(5) "China"
}

由于序列化文本中的引号需要使用 双引号,而该序列化文本中需要使用到的引号个数 较多(若较少的话,可以在字符串最外层使用双引号,对字符串内部的双引号进行转义),故在序列化文本最外侧使用了单引号。通过 拼接双引号包裹的含有转义字符的文本实现身份标识的书写

空字符的传输

控制字符的不可打印性

在 ASCII 表中,控制字符是一系列 非打印字符用于控制硬件设备或通信协议的行为。因为控制字符产生的本意并不是为了展示内容,因此当你尝试将控制字符进行 复制粘贴 等操作时,对于不同的环境可能会有不同的结果,应具体分析。可能的情况如下:

  • 在一些文本编辑器中,这些字符可能会显示为 特定的符号(空格、 等)完全不显示(此时,你连复制 ”控制字符“ 都没有可能)
  • 在一些终端或控制台应用中,这些字符可能会直接 按照其原始的控制功能来执行

结论

<?php


# 尝试输出空字符 NUL
var_dump("\0");

# 将复制到的空字符 NUL 作为 ord 函数的参数进行输出
var_dump(ord(' '));

执行效果

在 PHP 编辑器 PHPStorm 中,我得到 "\0" 的输出并尝试将其中的空字符复制并粘贴于 ord() 函数中以作为该函数的参数。

在尝试 两次(第一次执行示例代码是为了获得空字符,第二次则是为了获得 ord() 函数的输出结果) 后,得到上述界面(蓝色部分即复制内容,是空字符 NUL 在 PHPStorm 中的显示效果)。ord() 函数能够得到某个字符对应的 ASCII 码,此处的结果是 32,对应的字符是可打印字符 空格

所以,结论是 空字符这类控制字符是无法通过复制粘贴这一操作进行传输的

另辟蹊径

URL 字符编码

URL 字符编码是一套转换依据,其功能主要有以下三点:

  1. 将非 ASCII 字符文本转换为 ASCII 字符文本
  2. 去除语义
  3. 将不可见字符(如空格)转换为可见文本
将非 ASCII 字符文本转换为 ASCII 字符文本

URL 中的中文等非 ASCII 字符在 通过网络传输前 需要通过 URL 编码进行转换以使其符合 URL 的设计原则(URL 基于 ASCII 字符集进行设计)

在 PHP 中,可通过内置函数 urlencode() 将非 ASCII 文本转换为 URL 编码字符。对此,请参考如下示例:

<?php


var_dump(urlencode('Hello World'));
var_dump(urlencode('你好,中国'));
var_dump(urlencode('你好I am a space世界'));

执行效果

string(11) "Hello+World"
string(45) "%E4%BD%A0%E5%A5%BD%EF%BC%8C%E4%B8%AD%E5%9B%BD"
string(48) "%E4%BD%A0%E5%A5%BDI+am+a+space%E4%B8%96%E7%95%8C"
去除语义

URL 中的 特殊字符 需要通过 URL 字符编码来进行转换以使其 失去其在 URL 中的特殊含义

举个栗子

查询字符串由 一个或多个参数 组成,每个参数之间使用 & 符号 进行 分隔。如果查询字符串中的某一个参数中包含 & 符号,请问 阁下如何让程序将这个 & 理解为参数中的内容而不是参数与参数之间的连接标识呢?

此时,URL 字符编码 去除语义 的作用就体现出来了。通过将参数中的 & 进行 URL 编码以使得程序不再将其作为参数与参数之间的连接符来进行看待而只是将其视为普通的文本内容。

具体而言

?username=RedHeart&myflag=&x&

这段查询字符串仅包含两个参数,username 的参数值为 RedHeart,而 myflag 的参数值为 &x&

但实际上,这段查询字符串将被程序理解为三个参数,其中 username 的参数值为 RedHeart,而 myflagx 的参数值均为 空(什么也没有)

解决方案

将参数中的具有 URL 语义的特殊字符 & 转换为其对应的 URL 编码 %26,使 & 失去其语义即可。

?username=RedHeart&myflag=%26x%26
将不可见字符(如空格)转换为可见文本

空格和其他 空白字符 在 URL 中 不易阅读,可能导致 混淆或误解。通过将空白字符转换为 可识别 的形式,能够增强 URL 的 可读性及准确性

注:

在 URL 中,空格将被转换为 +,而制表符将被转换为 %09

URL Encode

在尝试利用 PHP 反序列化漏洞时,往往需要使用到 URL。如果将 包含身份标识的序列化文本进行 URL 编码处理,那么其中的 控制字符就能同 URL 一同转移了。对此,请参考如下示例:

网页源码文件 index.php 中的内容

<?php


class MyClass {}

# 尝试将 URL 中的查询字符串中的 X 参数的值进行反序列并将结果进行输出
var_dump(unserialize($_GET['X']));

为了获得 URL 编码后的序列化文本,我们可以使用如下两种方案:

通过序列化构造的对象来获得序列化文本并将其进行 URL 编码处理

<?php


class MyClass
{
    private $name = 'RedHeart';
    protected $nation = 'China';
}

# 将序列化结果进行 URL 编码处理
var_dump(urlencode(serialize(new MyClass)));

将构造的序列化文本进行 URL 编码处理

<?php


# 构造需要使用到的序列化文本
$serialize_text = 'O:7:"MyClass":2:{s:13:"' . "\0MyClass\0" . 'name";s:8:"RedHeart";s:9:"' . "\0*\0" . 'nation";s:5:"China";}';

# 将构造的序列化文本进行 URL 编码处理
var_dump(urlencode($serialize_text));

URL 编码处理后的序列化文本如下:

O%3A7%3A%22MyClass%22%3A2%3A%7Bs%3A13%3A%22%00MyClass%00name%22%3Bs%3A8%3A%22RedHeart%22%3Bs%3A9%3A%22%00%2A%00nation%22%3Bs%3A5%3A%22China%22%3B%7D

使用这段文本作为 X 参数的值并尝试通过浏览器访问 index.php 页面,得到如下界面:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c#设计模式-结构型模式 之 组合模式

&#x1f680;简介 组合模式又名部分整体模式&#xff0c;是一种 结构型设计模式 &#xff0c;是用于把一组相似的对象当作一个 单一的对象 。组合模式 依据树形结构来组合对象 &#xff0c;用来表示部分以及整体层&#xff0c;它可以让你将对象组合成树形结构&#xff0c;并且…

UE5报错及解决办法

1、编译报错&#xff0c;内容如下&#xff1a; Unable to build while Live Coding is active. Exit the editor and game, or press CtrlAltF11 if iterating on code in the editor or game 解决办法 取消Enable Live Coding勾选

摆脱推荐算法,实现万物皆可『RSS』

前言 相信各位对推荐算法已经很熟悉了&#xff0c;平台基于推荐算法不断推送我们感兴趣的信息&#xff0c;但是身处推荐算法中心&#xff0c;有时我们可能感觉视野越来越闭塞&#xff0c;原来节约我们时间的推荐系统&#xff0c;这时却成了困住我们的信息茧房 那么也许 RSS&a…

007:连续跌三天,第四天上涨的概率--可视化优化1

接着006&#xff0c;有一些问题&#xff0c;要手动改文件&#xff0c;麻烦&#xff0c;直接出来一个按钮&#xff0c;点击出现弹窗可以选择文件。 二来就是&#xff0c;所统计的数据&#xff0c;没有展示细节。应该展示的细节包括&#xff1a;股票代码&#xff0c;K线周期&…

JDK11优化了哪些功能以及新增了哪些特性功能|JDK各个版本的特性分析

一、前言 上一期讲了JDK10的一些新特性&#xff0c;需要回顾的朋友们可以去该专栏回顾一下 这一期讲一讲JDK11的一些新功能 二、新增特性 以下是JDK 11的一些新增或变化的特性&#xff1a; 1. 纯字符串类型的 HTTP 客户端: JDK 11 引入了一个新的 HTTP 协议的客户端 API&…

【STM32基础 CubeMX】定时器的使用

文章目录 前言一、定时器是什么二、CubeMX配置定时器三、代码分析3.1 CubeMX代码分析3.2 几个库函数以中断的方式开启定时器定时器中断函数 四、定时器应用4.1 定时器闪烁LED 总结 前言 在嵌入式系统开发中&#xff0c;精确地控制时间和时序是至关重要的。STM32微控制器提供了…

错误:F13 is an invalid placement site

在vivado中绑定引脚时提示&#xff1a;F13 is an invalid placement site f13引脚在板子上是接千兆网的rxclk端的。在进一步不排查出现这样的问题提示 Illegal to place instance u_gmii_to_rgmii/u_rgmii_rx/BUFIO_inst on site TIEOFF_X0Y326. The location site type (TIEOF…

14:00面试测试岗,14:06就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到9月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%,…

Java编程技巧:跨域

目录 1、跨域概念2、后端CORS&#xff08;跨域资源共享&#xff09;配置原理3、既然请求跨域了&#xff0c;那么请求到底发出去没有&#xff1f;4、通过后端CORS&#xff08;跨域资源共享&#xff09;配置解决跨域问题代码4.1、SpringBoot&#xff08;FilterRegistrationBean&a…

鼠标移动视差玻璃态效果

效果展示 页面结构组成 从页面上可以看到页面的结构比较简单&#xff0c;主要的元素如下&#xff1a; 背景图片文字带有清晰中心圆的毛玻璃 但是在怎么组织这几个元素的层次关系就需要需要考虑一下&#xff0c;并且中间的圆怎么实现也是需要考虑的。 CSS 知识点 clip-path…

【红外图像】利用红外图像处理技术对不同制冷剂充装的制冷系统进行性能评估(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

使用 Elastic 输入包自定义你的数据摄取

作者&#xff1a;Ishleen Kaur Elastic 通过集成&#xff08;integrations&#xff09;实现了外部数据源和 Elastic Observability Solution 之间数据流的收集、转换和分析。 集成包通过封装多个组件来实现这一点&#xff0c;包括代理配置 (agent configuration)、数据收集输入…

基于微信小程序的二手闲置交易市场小程序设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

基于SpringBoot的仿京东商城系统

前台部分实现效果截图 后台部分实现效果截图 源码地址&#xff1a;https://download.csdn.net/download/qq_50954361/87647905

以太网协议介绍(ARP、UDP、ICMP、IP)

以太网协议介绍 一、ARP协议 请求&#xff1a; 应答&#xff1a; ARP协议&#xff1a; 0x0001 0x0800 6 4硬件类型&#xff1a;2个字节&#xff0c;arp协议不仅能在以太网上运行还能在其他类型的硬件上运行。以太网用1来表示&#xff1b; 协议类型&#xff1a;两字节。指的是a…

Xilinx AXI DataMover使用说明与测试

Xilinx AXI DataMover使用说明与测试 1 架构说明2 IP设置说明2.1 接口说明2.2 设置说明 3 测试说明3.1 S2MM测试3.2 MM2S测试 本文主要介绍Xilinx AXI DataMover的使用和测试方法。 1 架构说明 在Xilinx的数据传输总线中&#xff0c;AXI Memory Map接口和AXI Stream接口是最常…

Java Spring拦截器优化实践: 专注于API路径拦截

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

Spring IOC之AnnotationConfigApplicationContext

博主介绍:✌全网粉丝近5W,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验✌ 博主作品:《Java项目案例》主要基于SpringBoot+MyBatis/MyBatis-plus…

C进阶 -- 自定义类型

&#x1f3c6;结构体 &#x1f36d;✨&#x1f387;&#x1f386;&#x1f645;‍♀️ &#x1f36d;结构体是一些值的集合&#xff0c;这些值称为 成员变量。结构的每个成员可以是不同的变量。 &#x1f947; 结构体类型的声明 struct Student {int age;//成员变量 }stu;/…