Web应用防火墙(WAF)在保护网站安全方面发挥着至关重要的作用,尤其是在防范文件上传漏洞方面。然而,攻击者不断演进其技术,试图绕过WAF的检测。本文将深入探讨文件上传绕过WAF的最新方法和技巧,重点关注雷池、宝塔和安全狗等主流WAF产品,旨在为安全研究人员和开发者提供有价值的参考,以更好地理解和应对这些挑战。请注意,本文内容仅供学习和研究,严禁用于非法用途。
WAF文件上传防护机制概述
WAF在文件上传防护中,通常会从以下几个方面进行检测和拦截:
- 文件类型检测: WAF会检查上传文件的MIME类型(Content-Type)和文件扩展名,判断是否为可执行文件或恶意文件类型。例如,阻止上传
.php
、.jsp
、.asp
等脚本文件。 - 文件内容检测: WAF会对上传文件的内容进行深度分析,通过特征码匹配、沙箱分析等方式,检测文件中是否包含恶意代码(如WebShell特征码)。
- 文件名检测: WAF会检查文件名是否包含特殊字符、双扩展名等异常情况,以防止攻击者通过文件名混淆绕过检测。
- 请求包结构检测: WAF会分析HTTP请求包的结构,特别是
multipart/form-data
部分的Content-Disposition
和boundary
等字段,确保其符合HTTP协议规范,防止畸形请求绕过。 - 目录权限检测: 部分WAF或服务器安全配置会限制特定目录的写入权限或执行权限,防止恶意文件被上传到敏感目录或被执行。
理解这些防护机制是绕过WAF的基础,攻击者往往会针对这些检测点进行各种变形和混淆,以达到绕过的目的。
通用文件上传WAF绕过技巧
1. 文件名与扩展名绕过
-
替换文件扩展名: WAF通常会维护一个黑名单或白名单来限制文件上传的类型。攻击者可以尝试将恶意文件的扩展名替换为WAF允许的、但服务器端可能存在解析漏洞的扩展名。例如,将
.php
文件改为.phtml
、.php3
、.php4
、.php5
、.phpt
、.jspx
、.asp
、.asa
、.cer
、.cdx
等。此外,还可以尝试大小写混淆,如将.php
改为.PHP
,因为某些WAF可能对大小写不敏感或规则不完善。 -
双扩展名: 某些服务器在处理文件时,会从右向左解析文件扩展名,直到遇到一个它能识别的扩展名。如果WAF只检查第一个扩展名,攻击者可以利用此特性。例如,上传
shell.php.jpg
,如果服务器解析.jpg
失败,可能会继续解析.php
。 -
特殊字符绕过: 在文件名中插入特殊字符,如
%00
(空字节)、换行符(%0a
、%0d
)、分号(;
)等,可能导致WAF或服务器解析文件名时出现差异。例如,shell.php%00.jpg
在某些环境下,%00
后面的内容会被截断,从而将文件保存为shell.php
。
2. 请求包畸形构造
-
Content-Disposition畸形: WAF通过解析HTTP请求中的
Content-Disposition
头部来获取文件名和表单字段信息。通过对该头部进行畸形构造,可以干扰WAF的正常解析。- 三重等号:
filename===muma.php
。一些WAF可能无法正确处理多个等号的情况。 - 换行符插入: 在
filename
或name
字段中插入换行符(如%0a
、%0d
),例如filename="shell.php%0a.jpg"
。这可能导致WAF无法识别完整的文件名。 - 引号变换: 灵活使用单引号、双引号或不使用引号,甚至去除末尾引号,例如
filename=shell.php
或filename='shell.php
。WAF可能对引号的处理不一致。 - 多个分号: 在
filename
前添加多个分号,如filename=;;;shell.php
,可能导致WAF解析错误。 - 多个等号: 在
Content-Disposition
字段中使用多个等号,如name===="file_x"; filename===="test.php"
。 - 变换Content-Disposition值: WAF可能期望
Content-Disposition
的值严格为form-data
。尝试使用大小写混淆(fOrM-DaTA
)、插入特殊字符(form-da+ta
)、或使用非标准值(form-dataxx
)甚至留空,都可能绕过。
- 三重等号:
-
Boundary畸形:
Content-Type
头部中的boundary
用于分隔multipart/form-data
请求体中的各个部分。对boundary
进行畸形构造,可以使WAF无法正确识别文件边界。- 大小写混淆:
mUltiPart/ForM-dATa
。 - 插入空格或逗号: 在
multipart/form-data
与boundary
之间插入空格、逗号或任意字符,例如Content-Type: multipart/form-data x boundary=----WebKitFormBoundarye111
。 - 在boundary前插入任意值:
Content-Type: multipart/form-data;bypass&123**{|}boundary=----WebKitFormBoundarye111
。 - 在boundary末尾插入逗号或分号:
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarye111;123abc
。
- 大小写混淆:
-
参数顺序交换: 某些WAF可能依赖于HTTP请求中参数的固定顺序。交换
name
和filename
的顺序,或者交换Content-Disposition
和Content-Type
的顺序,都可能绕过WAF的检测逻辑。
3. 数据编码与混淆
-
URL编码/Unicode编码: 对文件名、路径或文件内容进行多重URL编码或Unicode编码,WAF可能无法完全解码或在解码过程中出现错误,从而绕过检测。例如,将
.php
编码为%2e%70%68%70
或%u002e%u0070%u0068%u0070
。 -
分块传输编码(Chunked Transfer Encoding): 将HTTP请求体分成多个小块进行传输。WAF在处理分块传输时可能存在缺陷,无法完整地重组请求体进行检测,从而导致恶意文件绕过。攻击者可以在分块数据中插入垃圾数据或在敏感部分进行分块。
-
数据溢出/垃圾数据填充: 在文件名、参数值或
boundary
中填充大量无意义的垃圾数据,使得WAF在处理这些超长数据时出现性能瓶颈或解析错误,从而跳过对关键部分的检测。
4. 利用WAF或服务器特性
-
利用代码缺陷: 某些应用程序在处理文件上传时,其代码逻辑可能存在缺陷。例如,如果应用程序通过
lastIndexOf('.')
来获取文件扩展名,当文件名中不包含.
时,lastIndexOf('.')
会返回-1
,导致整个文件名被当作扩展名。如果WAF只检测文件后缀,而未对整个文件名进行检测,则可能绕过。例如,上传文件名为jsp
而不是test.jsp
,WAF可能不会拦截。 -
利用服务器解析漏洞: 不同的Web服务器(如Apache、Nginx、IIS)对文件解析的规则可能存在差异。攻击者可以利用这些差异来绕过WAF。例如,Apache的
AddHandler
指令可能导致shell.php.rar
被解析为PHP文件。 -
白名单绕过: 如果WAF配置了白名单,但白名单规则不严谨,攻击者可以尝试伪装成白名单中的合法文件类型。例如,上传一个图片文件,但其内容是WebShell,然后利用图片解析漏洞或文件包含漏洞来执行。
-
HTTP参数污染(HPP): 在HTTP请求中重复使用相同的参数名。WAF可能只处理第一个或最后一个参数,而服务器端可能处理所有参数或以不同的方式组合它们,从而导致绕过。例如,
filename=shell.php&filename=shell.jpg
。 -
HTTP走私(HTTP Smuggling): 利用HTTP协议解析的差异,构造特殊的HTTP请求,使得前端WAF和后端服务器对请求的解析结果不一致,从而绕过WAF的检测。这通常涉及
Content-Length
和Transfer-Encoding
头部的使用。
针对特定WAF的绕过技巧
1. 雷池WAF绕过
雷池WAF(SafeLine)以其“语义分析算法”为核心,旨在提供更精准的检测和更低的误报率。然而,即使是先进的WAF也可能存在绕过空间,通常是利用其对某些特殊语法或协议解析的差异。以下是一些针对雷池WAF文件上传的绕过思路和技巧:
-
利用代码缺陷绕过:
- 文件名解析差异: 某些应用程序在获取文件扩展名时,可能存在逻辑缺陷。例如,如果应用程序使用
lastIndexOf('.')
来获取文件扩展名,当文件名中不包含.
时,lastIndexOf('.')
会返回-1
,导致整个文件名被当作扩展名。如果雷池WAF主要依赖文件后缀进行检测,而未对整个文件名进行深度分析,则可能被绕过。例如,直接上传文件名为jsp
(而不是test.jsp
)的WebShell,雷池WAF可能不会拦截,并成功上传。攻击者可以尝试上传一个不带扩展名的文件,但其内容是恶意脚本,依赖后端应用程序的解析缺陷来执行。 - 双重扩展名与解析顺序: 尝试使用
shell.php.jpg
、shell.php%00.jpg
等双重扩展名或空字节截断的方式。虽然雷池WAF对这类攻击有较强的防护能力,但在特定配置或旧版本中,仍可能存在绕过机会。关键在于利用Web服务器对文件解析的优先级和WAF对文件名的检测逻辑之间的差异。
- 文件名解析差异: 某些应用程序在获取文件扩展名时,可能存在逻辑缺陷。例如,如果应用程序使用
-
0x00截断: 尽管0x00截断在现代系统中已不常见,但在某些特定配置或老旧系统中,仍可能有效。通过在文件名中插入
%00
(空字节),WAF可能在%00
处停止解析,而后端服务器继续解析,从而绕过文件类型检测。例如,上传shell.php%00.jpg
,WAF可能只检测到.jpg
,但服务器实际保存为shell.php
。 -
WAF对文件内容不做匹配: 部分WAF产品为了降低误报,可能对用户上传文件的内容不做匹配,直接放行。这种情况下,即使文件内容是WebShell,只要文件名和MIME类型通过了WAF的初步检测,文件也可能被成功上传。攻击者可以利用这种特性,上传经过编码或混淆的WebShell,然后通过其他漏洞(如文件包含)来执行。例如,将WebShell代码进行Base64编码或XOR加密,然后上传到服务器,再通过其他方式解码执行。
-
分块传输编码(Chunked Transfer Encoding): 理论上,分块传输编码可以用于绕过雷池WAF对请求体的完整性检测。通过将恶意Payload分散在多个分块中,并可能在分块之间插入垃圾数据,使得WAF难以完整重组并检测出恶意内容。攻击者可以尝试将WebShell代码分割成多个小块,并在每个块之间插入大量垃圾数据,从而混淆WAF的检测。
-
HTTP参数污染(HPP): 在HTTP请求中重复使用相同的参数名。WAF可能只处理第一个或最后一个参数,而服务器端可能处理所有参数或以不同的方式组合它们,从而导致绕过。例如,
filename=shell.php&filename=shell.jpg
,WAF可能只检测shell.jpg
,但服务器最终处理的是shell.php
。 -
利用协议差异: 尝试使用非标准的HTTP协议头或请求方式,例如使用
Content-Type
的多种变体,或者在boundary
中插入特殊字符,使得雷池WAF在解析HTTP请求时出现偏差,从而放行恶意文件。 -
模糊测试与规则绕过: 针对雷池WAF的规则进行模糊测试,尝试各种畸形请求、特殊字符组合、编码方式等,以发现其规则的盲区或缺陷。例如,尝试在文件名、路径或文件内容中插入各种Unicode字符、宽字节字符、特殊符号等,观察WAF的响应。
-
利用云WAF特性: 如果雷池WAF部署在云端,可以尝试利用云WAF的某些特性进行绕过,例如源站IP泄露、CDN回源绕过等。通过直接访问源站IP,绕过云WAF的防护。
2. 宝塔WAF绕过
宝塔面板自带的WAF是许多站长常用的防护工具,其防护规则相对灵活,但仍存在多种绕过可能性。以下是针对宝塔WAF文件上传的详细绕过方法:
-
目录穿越绕过:
- 非标准目录穿越路径: 宝塔WAF通常会限制
../../
这种形式的目录穿越,以防止攻击者访问非授权目录。然而,攻击者可以尝试使用非标准的目录穿越路径,例如.././../
、..%2f.%2f..%2f
、..\/..\/
等。这些变体可能在某些版本的宝塔WAF中未被完全识别,从而绕过其路径检测。攻击者可以利用此特性,将恶意文件上传到非Web可访问目录(如/tmp
),然后通过目录穿越漏洞将其解析为可执行文件。例如,上传一个包含PHP代码的HTML文件,然后利用.././../
进行目录穿越,使其被Web服务器解析为PHP。 - 结合文件名解析: 尝试将目录穿越与文件名解析漏洞结合。例如,上传一个名为
shell.php/.
的文件,如果宝塔WAF只检查.php
,而服务器在处理/.
时将其视为目录,则可能绕过。
- 非标准目录穿越路径: 宝塔WAF通常会限制
-
HTML文件写入PHP代码:
- 上传HTML文件: 宝塔WAF通常会拦截直接上传的PHP、JSP等脚本文件。攻击者可以尝试上传一个合法的HTML文件(例如
index.html
),然后在该HTML文件中写入PHP代码(例如<?php phpinfo(); ?>
)。由于HTML文件本身不是可执行文件,WAF可能不会拦截。之后,如果能找到解析HTML文件的漏洞(例如,通过配置Web服务器使其将特定HTML文件解析为PHP,或者通过文件包含漏洞),就可以执行其中的PHP代码。 - 结合MIME类型欺骗: 在上传HTML文件时,将
Content-Type
设置为text/html
,以符合WAF对HTML文件的检测。但文件内容却是PHP代码。如果WAF不对HTML文件内容进行深度检测,则可能绕过。
- 上传HTML文件: 宝塔WAF通常会拦截直接上传的PHP、JSP等脚本文件。攻击者可以尝试上传一个合法的HTML文件(例如
-
文件名污染与特殊字符:
- 换行符(
\n
、\r
)和空字节(%00
): 宝塔WAF可能对文件名中的某些特殊字符处理不当。例如,在文件名中插入换行符(\n
)、回车符(\r
)或空字节(%00
)等,可能导致WAF无法正确识别文件名,从而绕过其后缀检测。例如,上传1.php\n.jpg
,在某些情况下可能被解析为1.php
。%00
截断在较老的系统或配置中仍可能有效,即shell.php%00.jpg
可能被保存为shell.php
。 - 点号(
.
)和空格(shell.php.
或shell.php
。某些系统会自动去除这些字符,而WAF可能在检测时未考虑到这些情况。 - 特殊编码字符: 使用URL编码、Unicode编码或其他字符编码方式对文件名进行混淆,例如将
.php
编码为%2e%70%68%70
或%u002e%u0070%u0068%u0070
。宝塔WAF可能无法完全解码或在解码过程中出现错误。
- 换行符(
-
删除Content-Type头: 某些情况下,删除HTTP请求中的
Content-Type
头部可能绕过宝塔WAF的检测。因为WAF在进行文件类型判断时,通常会依赖Content-Type
头部信息。如果该头部缺失,WAF可能无法正确识别文件类型,从而放行。但这种方法可能导致后端应用程序无法正确处理文件上传。 -
垃圾数据填充与数据溢出:
- Content-Disposition字段填充: 在HTTP请求的
Content-Disposition
字段或文件内容中填充大量垃圾数据,使得请求包变得非常大。这可能导致宝塔WAF在处理时出现性能瓶颈或解析错误,从而跳过对恶意内容的检测。例如,在filename
前插入大量A
字符。 - 分块传输编码: 利用分块传输编码将恶意Payload分散在多个小块中,并可能在分块之间插入垃圾数据。宝塔WAF在处理分块传输时可能存在缺陷,无法完整地重组请求体进行检测,从而导致恶意文件绕过。
- Content-Disposition字段填充: 在HTTP请求的
-
利用服务器特性与配置不当:
- Nginx/Apache解析漏洞: 宝塔面板通常运行在Nginx或Apache等Web服务器上。可以尝试利用这些Web服务器的解析特性来绕过。例如,Nginx的
php.ini
配置不当可能导致shell.jpg/a.php
被解析为PHP文件(Nginx的cgi.fix_pathinfo
配置)。Apache的AddHandler
指令或.htaccess
文件配置不当也可能导致非PHP文件被解析为PHP文件。 - FastCGI解析漏洞: 如果Web服务器使用FastCGI处理PHP,可能存在FastCGI解析漏洞。例如,
shell.jpg%00.php
可能被FastCGI解析为PHP文件。 - MIME类型配置: 检查Web服务器的MIME类型配置,是否存在可以将非脚本文件解析为脚本文件的配置。
- Nginx/Apache解析漏洞: 宝塔面板通常运行在Nginx或Apache等Web服务器上。可以尝试利用这些Web服务器的解析特性来绕过。例如,Nginx的
-
HTTP参数污染(HPP): 在HTTP请求中重复使用相同的参数名。WAF可能只处理第一个或最后一个参数,而服务器端可能处理所有参数或以不同的方式组合它们,从而导致绕过。例如,
filename=shell.php&filename=shell.jpg
,宝塔WAF可能只检测shell.jpg
,但服务器最终处理的是shell.php
。 -
文件内容混淆与加密: 对WebShell内容进行混淆、加密或编码,以绕过宝塔WAF的内容检测。例如,使用Base64编码、XOR加密、字符串拼接、注释混淆等方式。WAF通常会对常见的WebShell特征码进行匹配,但对混淆后的代码可能无法识别。
3. 安全狗WAF绕过
安全狗是一款常见的国产WAF产品,其防护策略也在不断升级。针对安全狗的文件上传绕过,可以尝试以下方法:
-
畸形数据包绕过:
- 三重等号畸形:
filename===muma.php
。安全狗在某些版本中可能无法正确处理这种畸形文件名,从而绕过检测。 - 复写filename:
filename=;fimename="muma.php"
。通过在filename
字段中插入分号并重复filename
,可能导致安全狗解析错误。 - 脏数据溢出: 在
Content-Disposition
字段中填充大量垃圾数据。由于安全狗对请求包的解析可能存在长度限制或性能瓶颈,过长的垃圾数据可能导致其跳过对关键部分的检测,从而放行恶意文件。
- 三重等号畸形:
-
分块传输编码: 安全狗在处理分块传输时可能存在缺陷。攻击者可以利用分块传输将恶意Payload分散在多个小块中,并可能在分块之间插入垃圾数据,使得安全狗难以完整重组并检测出恶意内容。这在POST请求中尤为有效。
-
文件名后缀空格绕过: 某些版本的安全狗在文件后缀名检测时,可能没有过滤文件名中的空格。攻击者可以尝试在文件后缀名后添加空格,例如
shell.php
,从而绕过安全狗的后缀名检测。 -
MIME类型绕过: 尝试修改
Content-Type
头部信息,将其伪装成安全狗允许的MIME类型,例如image/jpeg
或image/png
,即使实际上传的是WebShell。如果安全狗主要依赖MIME类型进行初步判断,则可能被绕过。 -
利用白名单机制: 如果安全狗配置了白名单,可以尝试伪装成白名单中的合法文件类型,例如上传一个图片文件,但其内容是WebShell,然后利用其他漏洞(如文件包含)来执行。
-
利用服务器解析特性: 结合Web服务器(如Apache、Nginx)的解析特性进行绕过。例如,利用Apache的
AddHandler
指令或Nginx的php.ini
配置不当等,使得非PHP文件被解析为PHP文件。
总结与防御建议
文件上传漏洞是Web应用中常见的且危害巨大的漏洞之一,WAF作为重要的安全防护手段,在一定程度上能够抵御此类攻击。然而,道高一尺魔高一丈,攻击者总能通过各种技巧绕过WAF的检测。本文详细介绍了文件上传绕过WAF的通用技巧,以及针对雷池、宝塔、安全狗等特定WAF的绕过方法。可以看出,绕过WAF的核心思想在于利用WAF检测机制的缺陷、HTTP协议解析的差异以及服务器或应用程序的特性。
为了有效防御文件上传漏洞,建议采取以下综合性防御措施:
-
严格的文件类型校验:
- 白名单机制: 优先采用白名单机制,只允许上传明确允许的文件类型,而不是黑名单。对允许上传的文件类型进行严格限制,例如只允许上传图片、文档等非可执行文件。
- 多维度校验: 不仅要检查文件扩展名,还要结合MIME类型(Content-Type)、文件魔术字节(Magic Byte)等多种方式进行综合判断,防止通过修改扩展名绕过。
-
安全的文件内容检测:
- 深度内容扫描: 对上传的文件进行内容扫描,检测是否包含恶意代码、WebShell特征码等。可以使用杀毒引擎、沙箱分析等技术。
- 图片二次渲染: 对于图片文件,可以进行二次渲染,破坏其中可能隐藏的恶意代码,同时不影响图片正常显示。
-
安全的文件存储与访问:
- 分离存储: 将用户上传的文件存储在独立的、非Web可访问的目录中,并设置严格的访问权限,禁止直接执行。
- 随机文件名: 对上传的文件使用随机生成的文件名,避免攻击者猜测文件名进行访问或利用。
- 禁止执行权限: 存储用户上传文件的目录应禁止执行脚本的权限,即使文件被上传成功,也无法被执行。
-
加固WAF配置:
- 及时更新规则: 保持WAF规则库的及时更新,以应对最新的攻击手法。
- 自定义规则: 针对业务特点和已知漏洞,定制WAF规则,弥补通用规则的不足。
- 日志审计: 开启WAF的详细日志,并定期进行审计,及时发现和分析异常行为。
-
代码层面安全:
- 安全编码实践: 开发人员应遵循安全编码规范,避免在代码中出现文件解析缺陷、目录穿越等漏洞。
- 输入验证: 对所有用户输入进行严格的验证和过滤,包括文件名、文件路径等。
-
系统层面安全:
- 最小权限原则: Web服务器和应用程序应以最小权限运行。
- 定期漏洞扫描: 对Web应用和服务器进行定期的漏洞扫描和渗透测试,及时发现并修复潜在的安全问题。
通过以上多层次、全方位的防御措施,可以大大提高Web应用抵御文件上传攻击的能力,从而更好地保护网站安全。