Web应用防火墙(WAF)
2017 年,某电商平台遭遇了一次大规模数据泄露,数千万用户的账户信息被窃取。事后分析发现:攻击者利用了 Web 应用中的一个 SQL 注入漏洞,而平台已经部署了防火墙和 IDS。
问题出在哪里?传统防火墙和 IDS 针对的是网络层攻击,它们无法理解 HTTP 协议的应用层语义。SQL 注入的恶意请求伪装成正常的数据库查询语句,通过了所有网络层检测。
Web 应用防火墙(WAF)就是为了解决这个问题而诞生的。它是 Web 应用的安全门卫,理解 HTTP 语义,能够识别和阻止应用层攻击。
WAF 的定义与作用
WAF 是一种专门用于保护 Web 应用的安全设备或服务。它位于 Web 服务器之前,检查 HTTP/HTTPS 请求和响应,识别并阻止恶意流量。
WAF 与传统防火墙的区别
WAF 的部署模式
1. 反向代理模式
WAF 作为反向代理部署在 Web 服务器之前:
- 所有客户端请求先到 WAF
- WAF 检测后转发给后端服务器
- 服务器响应先到 WAF,WAF 检查后再返回客户端
优点:完整检测和过滤,保护范围广
缺点:所有流量经过 WAF,是性能瓶颈点
2. 透明桥接模式
WAF 以「透明网桥」方式串接在网络中:
- 对客户端和服务器都是透明的
- 不改变网络拓扑
- 需要物理旁路保护
优点:部署简单,不影响现有网络
缺点:无法终止 SSL,只能检测明文流量
3. 旁路模式(镜像检测)
WAF 通过镜像流量进行检测:
- 交换机/ TAP 复制流量到 WAF
- WAF 只检测,不阻断
- 发现攻击时发送 RST 阻断或联动防火墙
优点:不影响正常业务,对性能无影响
缺点:无法实时阻断,依赖联动机制
4. 云 WAF 模式
流量通过 DNS 牵引到云端 WAF:
优点:弹性扩展,防御大规模 DDoS
缺点:需要 DNS 改造,延迟略有增加
WAF 的检测技术
签名检测(Signature-Based)
基于已知攻击特征库进行匹配:
# 简化示例:SQL 注入检测规则
rules:
- name: sql-injection-classic
pattern: "(?i)(union.*select|select.*from|insert.*into|delete.*from|drop.*table)"
action: block
severity: high
- name: sql-injection-encoded
pattern: "(%27|%22|%3D|%3E|%3C|%2D|%2B|%2F|%5C)"
context: url_param
action: block
severity: medium
优点:检测准确率高,误报率低
缺点:无法检测未知攻击
行为检测(Behavior-Based)
基于正常用户行为建立基线:
- 正常请求的 URL 模式、参数类型、访问频率
- 异常行为:短时间内大量请求、异常参数、超长请求
// 简化示例:基于速率的异常检测
public class RateLimitDetector {
private final Map<String, RateWindow> clientStats = new ConcurrentHashMap<>();
private static final int MAX_REQUESTS_PER_MINUTE = 100;
public DetectionResult detect(String clientIp, String requestUri) {
RateWindow window = clientStats.computeIfAbsent(
clientIp, k -> new RateWindow()
);
if (window.incrementAndGet() > MAX_REQUESTS_PER_MINUTE) {
return DetectionResult.builder()
.threat(true)
.reason("Rate limit exceeded")
.score(0.9)
.build();
}
// 检测异常扫描行为
if (window.getUniqueUris().size() > 1000) {
return DetectionResult.builder()
.threat(true)
.reason("Possible directory scanning")
.score(0.8)
.build();
}
return DetectionResult.builder().threat(false).build();
}
}
机器学习检测
现代 WAF 使用 ML 模型识别新型攻击:
- 学习正常流量模式
- 检测偏离正常模式的请求
- 自动适应应用的变化
优点:能检测未知攻击
缺点:需要大量训练数据,误报率可能较高
WAF 的核心功能
1. SQL 注入防护
识别试图在 SQL 查询中注入恶意代码的请求:
// 攻击示例
// 正常查询: SELECT * FROM users WHERE id = 1
// 注入攻击: SELECT * FROM users WHERE id = 1 OR 1=1
// WAF 检测点
public class SqlInjectionDetector {
// 检测常见的 SQL 注入模式
public boolean isSqlInjection(String input) {
String[] sqlKeywords = {
"union", "select", "insert", "update", "delete",
"drop", "exec", "execute", "script", "javascript"
};
String lowerInput = input.toLowerCase();
for (String keyword : sqlKeywords) {
if (lowerInput.contains(keyword)) {
// 进一步分析上下文,区分正常内容和注入
if (looksLikeInjection(lowerInput, keyword)) {
return true;
}
}
}
return false;
}
}
2. XSS(跨站脚本)防护
检测试图在网页中注入恶意 JavaScript 的请求:
- 反射型 XSS:URL 参数中嵌入脚本
- 存储型 XSS:表单提交中嵌入脚本
- DOM 型 XSS:客户端 JavaScript 处理用户输入
3. CSRF(跨站请求伪造)防护
验证请求是否来自合法的来源:
// CSRF Token 验证
public class CsrfProtectionFilter {
public boolean validateRequest(HttpRequest request) {
String csrfToken = request.getHeader("X-CSRF-Token");
String sessionToken = sessionManager.getCsrfToken(request.getSessionId());
// Token 存在且匹配
if (csrfToken != null && csrfToken.equals(sessionToken)) {
// 验证 Referer/Origin 头
String referer = request.getHeader("Referer");
String origin = request.getHeader("Origin");
return isValidOrigin(referer, origin, request.getHost());
}
return false;
}
}
4. 命令注入防护
检测试图在系统命令中注入恶意命令的请求:
- Shell 注入:
; cat /etc/passwd
- 命令替换:
`whoami`
- 管道注入:
| ls -la
WAF 的绕过技术简介
知己知彼,了解 WAF 绕过技术才能更好地防御:
编码绕过
- URL 编码:
%27 = '、%3D = =
- 双重编码:
%2527
- Unicode 编码:
\u0027
大小写混合
- SQL 不区分大小写:
UnIoN SeLeCt
- 过滤器只检查小写时可用
注释注入
- 内联注释:
UN/**/ION SEL/**/ECT
- 注释替代空格:
SELECT/**/*/**/FROM
HTTP 协议混淆
- 分块传输编码
- HTTP/2 协议头部注入
- 协议版本混淆
WAF 的性能影响
优化策略:
- 使用硬件加速(SSL 卸载)
- 规则预编译
- 白名单跳过不检测的路径
- 异步日志处理
云 WAF vs 自建 WAF
代表产品:Cloudflare WAF、AWS WAF、Azure Application Gateway、阿里云 WAF
关键洞察
WAF 不是银弹。它只能保护 Web 应用,无法防止业务逻辑漏洞(如垂直越权、水平越权)。真正的安全需要 WAF + 安全编码 + 渗透测试 + 员工培训的综合防护。
思考题
问题 1:WAF 的误报可能阻断正常用户的请求。在不影响安全性的前提下,如何降低 WAF 的误报率?
参考答案
误报管理是 WAF 运营的核心挑战。以下是系统性降低误报的方法:
第一阶段:学习模式
- 上线初期使用「检测模式」(只告警不阻断)
- 收集所有告警,分析是否为真实攻击
- 根据分析结果调整规则
第二阶段:精细化规则
# 避免误报的精细化规则示例
# 宽泛规则(误报率高)
- name: "block-sql-keywords"
pattern: "select.*from"
action: block # 误报:正常用户搜索 "select from"
# 精细化规则(低误报)
- name: "block-sql-injection"
pattern: "(union.*select|select.*from.*where.*=.*['\"])"
context:
- parameter_name: ["id", "user_id", "category"]
- content_type: ["application/x-www-form-urlencoded"]
negative_pattern: "^\\d+$" # 排除纯数字参数
action: block
第三阶段:建立白名单
- 内部工具的正常请求模式
- 第三方集成的特殊 Header
- 监控探针的健康检查请求
第四阶段:用户画像
- 识别不同用户群体的正常行为
- 对高信任用户降低检测强度
- 对异常用户提高检测强度
第五阶段:渐进式阻断
- 发现可疑请求时,不直接阻断
- 先返回验证码或挑战页面
- 通过验证后才放行
问题 2:在 API 保护场景下,WAF 如何处理 API 的参数校验和协议合规性?
参考答案
API 保护需要 WAF 具备协议层和语义层的检测能力:
协议层合规性
# API 协议合规规则示例
api_compliance:
- name: "enforce-json-content-type"
condition: "request.content_type != 'application/json'"
action: block
severity: high
- name: "enforce-api-version"
condition: "request.header['API-Version'] not in ['v1', 'v2']"
action: block
- name: "rate-limit-per-api-key"
limit: 1000
window: 60 # per second
key: "request.header['X-API-Key']"
参数校验
# 参数校验规则
parameter_validation:
- name: "validate-user-id"
path: "/users/{userId}"
parameter: "userId"
type: "integer"
min: 1
max: 1000000
- name: "validate-email-format"
path: "/users"
parameter: "email"
pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
- name: "validate-json-schema"
path: "/orders"
parameter: "body"
schema: "order.schema.json"
API 速率控制
# 速率控制策略
rate_limiting:
- name: "per-user-rate-limit"
key: "authenticated_user"
limit: 100
window: 60
- name: "per-api-endpoint-limit"
key: "request.path"
limits:
"/api/search": 20 # 更严格的限制
"/api/batch": 5
"/api/export": 1
异常行为检测
- 检测 API 参数结构的异常变化
- 检测异常的批量请求模式
- 检测 API 密钥的滥用
推荐产品:AWS WAF + API Gateway、Kong、Apigee