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

文章目录

  • 参考
  • 环境
  • 访问修饰符
      • 访问修饰符
      • 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 中,当对象被序列化时,对象的 非公共属性的名称会被特殊处理以表示其可见性(访问修饰符)。对此,请参考如下示例:

<?phpclass 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 序列化文本) 包含非公共属性对象的序列化文本。对此,请参考如下示例:

<?phpclass 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 编码字符。对此,请参考如下示例:

<?phpvar_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 中的内容

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

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

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

<?phpclass 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.xdnf.cn/news/147869.html

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

相关文章

SpringBoot整合RocketMQ笔记

SpringBoot版本为2.3.12.Release RocketMQ对比kafka 学习链接 https://zhuanlan.zhihu.com/p/335216381 代码实战 https://www.cnblogs.com/RedOrange/p/17401238.html Centos安装rocketmq https://blog.csdn.net/chuige2013/article/details/123783612 RocketMQ详细配置与…

C++——继承

继承的概念 在C&#xff0c;继承是一种可以代码复用的重要手段&#xff0c;它允许一个类继承另一个类的属性和方法。继承可以实现类之间的层次关系&#xff0c;提供代码重用和多态性有关的功能。同时&#xff0c;C支持多重继承&#xff0c;即一个类可以继承多个基类的特性 继…

123. 买卖股票的最佳时机 III

给定一个数组&#xff0c;它的第 i 个元素是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。 注意&#xff1a;你不能同时参与多笔交易&#xff08;你必须在再次购买前出售掉之前的股票&#xff09;。 Ans:思路&#x…

OpenCV 实现 SIFT→SURF 算法关键点检测实现

目录 1&#xff0c;SIFT算法原理 1.1&#xff0c;基本流程 1.1.1 尺度空间极值检测 1.1.2 关键点定位 1.1.3 关键点方向确定 1.1.4 关键点描述 1.1.5 总结 1.2 SURF原理 2 代码实现 3 结果展示 4&#xff0c;你肯定会遇到报错 cv2.error: OpenCV(3.4.8) C…

网络摄像头(IPC)介绍:类型、供电、镜头、夜视等

IPC&#xff08;Internet Protocol Camera&#xff0c;网络摄像头&#xff09;&#xff0c;它是一种由传统摄像机与网络技术结合所产生的新一代摄像机。它可以将视频、音频、报警及控制信号通过网络传输&#xff0c;接受网络监控主机&#xff08;NVR或监控管理平台&#xff09;…

(SAR)Sentinel-1影像自动下载

基于ASF网站提供的python代码&#xff0c;实现Sentinel-1影像的自动下载&#xff1b; 1、登录ASF网站 登录Sentinel-1影像ASF网站&#xff1a;https://search.asf.alaska.edu/&#xff1b; 点击网站最右侧Sign in图标&#xff0c;进行用户注册&#xff1b; 注册完用户之后&…

运行程序时msvcr110.dll丢失的解决方法,msvcr110.dll丢失5的个详细解决方法

在使用电脑的过程中&#xff0c;我们经常会遇到各种问题&#xff0c;其中之一就是 msvcr110.dll 丢失的问题。msvcr110.dll 是 Microsoft Visual C Redistributable 的一个组件&#xff0c;用于支持使用 Visual C 编写的应用程序。如果您的系统中丢失了这个文件&#xff0c;您可…

stm32 - 初识2

stm32 - 初识2 工程架构点灯程序寄存器方式点灯库函数的方式点灯 工程架构 启动文件 中断向量表&#xff0c;中断服务函数&#xff0c;其他中断等 中断服务函数中的&#xff0c;复位中断是整个程序的入口&#xff0c;调用systeminit&#xff0c;和main函数 点灯程序 寄存器方式…

【论文阅读】UniDiffuser: Transformer+Diffusion 用于图、文互相推理

而多模态大模型将能够打通各种模态能力&#xff0c;实现任意模态之间转化&#xff0c;被认为是通用式生成模型的未来发展方向。 最近看到不少多模态大模型的工作&#xff0c;有医学、金融混合&#xff0c;还有CV&NLP。 今天介绍&#xff1a; One Transformer Fits All Di…

华为云云耀云服务器L实例评测 | 实例场景体验之搭建接口服务:通过华为云云耀云服务器构建 API 服务

华为云云耀云服务器L实例评测 &#xff5c; 实例场景体验之搭建接口服务&#xff1a;通过华为云云耀云服务器构建 API 服务 介绍华为云云耀云服务器 华为云云耀云服务器 &#xff08;目前已经全新升级为 华为云云耀云服务器L实例&#xff09; 华为云云耀云服务器是什么华为云云…

工地临时用电之智慧用电:全方位保障用电安全

随着科技进步和智能化的发展&#xff0c;工地用电管理也迎来了智慧化的革新。智慧用电&#xff0c;作为智慧工地的重要组成部分&#xff0c;通过集中式管理和创新的技术手段&#xff0c;为工地提供了全方位的用电安全保障。 针对工地临时用 的现状及系统结构&#xff0c;力安科…

阿里云PolarDB自研数据库详细介绍_兼容MySQL、PostgreSQL和Oracle语法

阿里云PolarDB数据库是阿里巴巴自研的关系型分布式云原生数据库&#xff0c;PolarDB兼容三种数据库引擎&#xff1a;MySQL、PostgreSQL、Oracle&#xff08;语法兼容&#xff09;&#xff0c;目前提供云原生数据库PolarDB MySQL版、云原生数据库PolarDB PostgreSQL版和云原生数…

十四天学会C++之第三天(数组和字符串)

1. 数组的定义和初始化 数组是一种由相同数据类型的元素组成的集合&#xff0c;这些元素按照一定的顺序存储在连续的内存位置上。数组的大小在创建时是固定的&#xff0c;无法在运行时改变。 在C中&#xff0c;数组的定义和声明非常简单。定义一个数组&#xff1a; 数据类型…

Django之十二:模板的继承+用户列表

模板的继承 新建layout.html&#xff1a; {% load static %} <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><link rel"stylesheet" href"{% static plugins…

C++list模拟实现

list模拟实现 1.链表结点2.类模板基本框架3.构造4.插入普通迭代器实现4.1尾插4.2普通迭代器实现4.3对比list和vector的iterator4.4迭代器的价值4.5insert4.6尾插头插复用写法 5.删除erase5.1erase5.2尾删头删复用写法 6.析构emptysizeclear6.1clear6.2size6.3 empty6.4 析构 7.…

问题: 视频颜色问题,偏绿

参考 什么是杜比视界&#xff1f; - https://www.youtube.com/watch?vldXDQ6VlC7g 【哈士亓说】07&#xff1a;HDR、杜比视界究竟是个啥&#xff1f;为什么这个视频还不是HDR视频&#xff1f; - https://www.youtube.com/watch?vrgb9Xg3cJns 正文 视频应该是 杜比视界 电…

GEO生信数据挖掘(二)下载基因芯片平台文件及注释

检索到目标数据集后&#xff0c;开始数据挖掘&#xff0c;本文以阿尔兹海默症数据集GSE1297为例 目录 下载平台文件 1.AnnotGPL参数改为TRUE,联网下载芯片平台的soft文件。&#xff08;国内网速奇慢经常中断&#xff09; 2.手工去GEO官网下载 转换芯片探针ID为gene name 拓…

保姆级Anaconda安装教程

一.anaconda下载 建议使用清华大学开源软件镜像站进行下载&#xff0c;使用官网下载速度比较慢。 anaconda清华大学开源软件镜像站 &#xff1a; https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 一路next即可&#xff0c;注意添加环境变量得选项都勾上。 二.验证…

【AI视野·今日Robot 机器人论文速览 第四十六期】Tue, 3 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Tue, 3 Oct 2023 Totally 76 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers Generalized Animal Imitator: Agile Locomotion with Versatile Motion Prior Authors Ruihan Yang, Zhuoqun Chen, Jianhan M…

Java 随机数的获得方法(5种)

1. Math.random() 静态方法 产生的随机数是 0 - 1 之间的一个 double&#xff0c;即 0 < random < 1 代码&#xff1a; 结果&#xff1a; 当调用 Math.random() 方法时&#xff0c;自动创建了一个伪随机数生成器&#xff0c;实际上用的是 new java.util.Random()。当接…