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.rhkb.cn/news/146395.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【进阶C语言】自定义类型

本节内容大致目录如下&#xff1a; 1.结构体 2.位段 3.枚举 4.联合&#xff08;共用体&#xff09; 以上都是C语言中的自定义类型&#xff0c;可以根据我们的需要去定义。 一、结构体 一些基础知识在初阶C语言的时候已经介绍过&#xff0c;在这里粗略概括&#xff1b;重…

wxWidgets(1):在Ubuntu 环境中搭建wxWidgets 库环境,安装库和CodeBlocks的IDE,可以运行demo界面了,继续学习中

1&#xff0c;选择使用 wxWidgets 框架 选择这个主要是因为完全的开源&#xff0c;不想折腾 Qt的库&#xff0c;而且打包的文件比较大。 网络上面有很多的对比&#xff0c;而且使用QT的人比较多。 但是我觉得wxwidgets 更加偏向 c 语法本身&#xff0c;也有助学习C。 没有太多…

RAID知识点总结

目录 RAID类型 RAID的数据组织及存取方式 RAID热备与重构 RAID逻辑卷 常见的RAID RAID0 RAID 1 RAID3 RAID 5 RAID 6 RAID组合 RAID 10 RAID 50 总结 RAID技术对比 RAID的应用场景 RAID2.0 使用RAID2.0的原因 RAID2.0的发展 RAID2.0技术&#xff1a;两层虚拟…

【深入探究人工智能】:历史、应用、技术与未来

深入探究人工智能 前言人工智能的历史人工智能的应用人工智能的技术人工智能的未来当代的人工智能产物结语&#x1f340;小结&#x1f340; &#x1f389;博客主页&#xff1a;小智_x0___0x_ &#x1f389;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &am…

力扣-338.比特位计数

Idea 直接暴力做法&#xff1a;计算从0到n&#xff0c;每一位数的二进制中1的个数&#xff0c;遍历其二进制的每一位即可得到1的个数 AC Code class Solution { public:vector<int> countBits(int n) {vector<int> ans;ans.emplace_back(0);for(int i 1; i < …

数学建模之Matlab基础操作

作者由于后续课程也要学习Matlab&#xff0c;并且之前也进行了一些数学建模的练习&#xff08;虽然是论文手&#xff09;&#xff0c;所以花了几天零碎时间学习Matlab的基础操作&#xff0c;特此整理。 基本运算 a55 %加法&#xff0c;同理减法 b2^3 %立方 c5*2 %乘法 x 1; …

【C语言数据结构——————栈和队列4000字详解】

欢迎阅读新一期的c语言数据结构模块————栈和队列 ✒️个人主页&#xff1a;-_Joker_- &#x1f3f7;️专栏&#xff1a;C语言 &#x1f4dc;代码仓库&#xff1a;c_code &#x1f339;&#x1f339;欢迎大佬们的阅读和三连关注&#xff0c;顺着评论回访&#x1f339;&#…

Unity把UGUI再World模式下显示到相机最前方

Unity把UGUI再World模式下显示到相机最前方 通过脚本修改Shader 再VR里有时候要把3D的UI显示到相机最前方&#xff0c;加个UI相机会坏事&#xff0c;可以通过修改unity_GUIZTestMode来解决。 测试用例 测试用例如下&#xff1a; 场景包含一个红色的盒子&#xff0c;一个UI…

洛谷P1102 A-B 数对题解

目录 题目A-B 数对题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1提示传送门 代码解释亲测 题目 A-B 数对 题目背景 出题是一件痛苦的事情&#xff01; 相同的题目看多了也会有审美疲劳&#xff0c;于是我舍弃了大家所熟悉的 AB Problem&#xff0c;改用 …

使用WPS自动化转换办公文档: 将Word, PowerPoint和Excel文件转换为PDF

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

【Linux】RPM包使用详解

&#x1f341; 博主 "开着拖拉机回家"带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——&#x1f390;开着拖拉机回家_大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341; 希望本文能够给您带来一定的帮助&#x1f338;文…

WebSocket的那些事(6- RabbitMQ STOMP目的地详解)

目录 一、目的地类型二、Exchange类型目的地三、Queue类型目的地四、AMQ Queue类型目的地五、Topic类型目的地 一、目的地类型 在上节 WebSocket的那些事&#xff08;5-Spring STOMP支持之连接外部消息代理&#xff09;中我们已经简单介绍了各种目的地类型&#xff0c;如下图&…

分布式搜索引擎es-3

文章目录 数据聚合聚合的种类RestAPI实现聚合 自动补全自定义拼音分词器自动补全查询案例&#xff1a;实现酒店搜索框自动补全自动补全的javaAPI实现搜索框自动补全 口述自动补全数据同步集群集群的分布式存储集群分布式查询集群故障转移 数据聚合 什么是聚合&#xff1f; 聚合…

多网卡场景数据包接收时ip匹配规则

多网卡场景数据包接收时ip匹配规则 mac地址匹配规则 接收数据包时数据包中的目的mac地址匹配接收网卡的mac地址后&#xff0c;数据包才会继续被传递到网络层处理 ip地址匹配规则 图1&#xff1a; 参见&#xff1a;https://zhuanlan.zhihu.com/p/529160026?utm_id0 图2&am…

Vue中的数据分页与分页组件设计

Vue中的数据分页与分页组件设计 在前端开发中&#xff0c;数据分页是一个常见的需求&#xff0c;特别是当处理大量数据时。Vue作为一款流行的JavaScript框架&#xff0c;提供了强大的工具和生态系统来实现数据分页。本文将介绍如何在Vue中进行数据分页&#xff0c;以及如何设计…

【Django 笔记】第一个demo

1. pip 安装 2. django 指令 D:\software\python3\anconda3\Lib\site-packages\django\bin>django-adminType django-admin help <subcommand> for help on a specific subcommand.Available subcommands:[django]checkcompilemessagescreatecachetabledbshelldiff…

Vue中如何进行图表绘制

Vue中的图表绘制&#xff1a;数据可视化的艺术 数据可视化是现代Web应用程序的重要组成部分之一。Vue.js作为一种流行的JavaScript框架&#xff0c;提供了许多强大的工具和库&#xff0c;用于在前端应用程序中创建各种图表和数据可视化。本文将深入探讨在Vue中进行图表绘制的方…

WPF 实现点击按钮跳转页面功能

方法1. 配置环境 首先添加prism依赖项&#xff0c;配置好所有文件。需要配置的有两个文件&#xff1a;App.xaml.cs和App.xaml App.xaml.cs using System.Data; using System.Linq; using System.Threading.Tasks; using System.Windows;namespace PrismDemo {/// <summa…

R语言中更改R包安装路径

看到这些包下载到我的C盘&#xff0c;我蛮不爽的&#xff1a; 所以决定毫不犹豫的改到D盘&#xff1a; 首先&#xff0c;我们需要在RStudio中新建一个初始启动文件&#xff1a; file.edit(~/.Rprofile) 然后去你喜欢的环境新建一个文件夹存放安装的包的位置&#xff0c;我喜欢…

美容店预约小程序搭建流程

随着科技的不断发展&#xff0c;小程序已经成为了人们生活中不可或缺的一部分。对于美容店来说&#xff0c;搭建一个预约小程序不仅可以提高工作效率&#xff0c;还可以增加客户数量、提高服务质量。那么&#xff0c;如何搭建一个美容店预约小程序呢&#xff1f;本文将为你详细…