亚马逊AWS官方博客
自动部署 FortiWeb WAF 实现应用密码暴力破解防护
1. 方案概述
亚马逊云科技 Fortinet 关键应用联合防御解决方案通过整合亚马逊云科技资源和 Fortinet 产品的优势,可以为客户量身打造既有针对性又满足适用性的个性化安全防护解决方案。作为安全威胁综合防御场景里的最佳实践之一,本案使用集中式部署架构,通过自动化部署快速完成整套亚马逊云科技云上基础设施搭建以及 Fortinet 产品开箱即用,展示如何通过 captcha 来阻止 bot 发起的针对应用登录的密码暴力破解。
2. 适配场景
- 支持多可用区部署。灵活适配单可用区、双可用区和三个可用区的不同业务需求;
- 解决方案符合并支持“信息安全技术:网络安全等级保护基本要求”(GB/T 22239-2019)(等保);
- 支持 FortiGate-VM 防火墙、FortiWeb-VM 应用防火墙的灵活部署。可两者联合组网,也可每种产品独立提供解决方案。
3. 方案特点
- 前置防御:FortiGate-VM 防火墙 + 亚马逊云科技 Gateway Load Balancer(GWLB),在流量入站时,进入 VPC 的第一时间进行南北向安全检查;
- 分层防御:FortiGate-VM 作为出口防火墙,应对入侵检测、恶意软件/病毒等安全威胁;FortiWeb-VM 作为 WEB 应用防火墙,提供全面的关键业务防护;
- 重点防御:FortiWeb-VM 应用防火墙拥有机器学习引擎,能够防御 OWASP Top10 攻击、机器人威胁,提供 API 防护,可以灵活定制、适配应用场景;
- 南北防护:入站业务流量通过边缘关联拦截进入防火墙做流量清洗,出站返回流量、出站实例流量通过 VPC 路由表引流至防火墙做安全检查;
- 东西检查:无论是同 VPC,还是同账号下的不同 VPC,可以按实际业务要求,分别采用 Transit Gateway(TGW)或者自定义路由引流至防火墙做流量检查;
- 紧密聚合:FortiGate-VM 防火墙、FortiWeb-VM 应用防火墙共同部署在业务 VPC 中,使业务流量的调度更加紧凑
- 自动化:通过 Terraform 自动化部署脚本,可以轻松快速的实现按需配置整套亚马逊云科技云上基础设施以及 Fortinet 产品的开箱即用。
4. 方案架构示意图
5. 方案资源规划
- VPC Prod SecOps 的子网概述
名称 | CIDR | 说明 |
subnet-natgw-az1 | 172.25.211.0/24 | 部署有 AZ1 的 NAT Gateway (natgw-az1),用于本方案中的 AZ1 实例的出站 |
subnet-natgw-az2 | 172.25.212.0/24 | 部署有 AZ2 的 NAT Gateway (natgw-az2),用于本方案中的 AZ2 实例的出站 |
subnet-nlb-public-az1 | 172.25.201.0/24 | 部署有 nlb-public 在 AZ1 的弹性网卡 eni-nlb-az1 |
subnet-nlb-public-az2 | 172.25.202.0/24 | 部署有 nlb-public 在 AZ2 的弹性网卡 eni-nlb-az2 |
subnet-gwlbe-az1 | CIDR 无须展示,请自行定义 | 部署有 GWLB 在 AZ1 的 Endpoint,对应的弹性网卡为 gwlbe-hub-az1 |
subnet-gwlbe-az2 | 部署有 GWLB 在 AZ2 的 Endpoint,对应的弹性网卡为 gwlbe-hub-az2 | |
subnet-fgt-port1-az1 | CIDR 无须展示,请自行定义 | 部署有 FortiGate-VM 的 port1 网卡,用于 FortiGate 的许可激活、特征库更新等,仅有管理流量,不承载业务流量 |
subnet-fgt-port1-az2 | ||
subnet-fgt-port2-az1 | CIDR 无须展示,请自行定义 | 部署有 FortiGate-VM 的 port2 网卡,用于通过 GENEVE 协议与亚马逊云科技的 GWLB 连接;同时图 1 中的 GWLB 也部署并关联这两个 subnets |
subnet-fgt-port2-az2 | ||
subnet-fwb-az1 | CIDR 无须展示,请自行定义 | 部署有 FortiWeb-VM |
subnet-fwb-az2 | ||
subnet-app-az1 | CIDR 无须展示,请自行定义 | 部署有 WEB 服务器实例,以及 DVWA 靶场服务器 |
subnet-app-az2 | 部署有 WEB 服务器实例 | |
subnet-faz-az1 | CIDR 无须展示,请自行定义 | 部署有 Fortinet 的日志分析产品 FortiAnalyzer-VM |
- VPC Prod SecOps 的路由表概述
名称 | 关联的 SUBNETs | 说明 |
VPC Edge Association | N/A | 控制 VPC Connect 的入站路由,即当有目标是 natgw-az1 (172.25.211.0/24)、nagw-az2 (172.25.212.0/24)、nlb-public-az1 (172.25.201.0/24)、nlb-public-az2 (172.25.202.0/24)的入站流量时,流量会被转发到对应 AZ 的 GWLB Endpoint(gwlbe-az*) |
rtb-natgw-az1 | subnet-natgw-az1 | 控制 subnet-natgw 的出站路由表,默认路由指向 gwlbe |
rtb-natgw-az2 | subnet-natgw-az2 | |
rtb-nlb-public-az1 | subnet-nlb-public-az1 | 控制 subnet-nlb-public 的出站路由表,subnet-nlb-public 部署有亚马逊云科技 NLB,默认路由指向 gwlbe |
rtb-nlb-public-az2 | subnet-nlb-public-az2 | |
rtb-gwlbe | subnet-gwlbe-az1 subnet-gwlbe-az2 |
控制 GWLB endpoint 的出站路由表,默认路由指向 IGW |
rtb-nva-mgmt | subnet-fgt-port1-az1 subnet-fgt-port1-az2 subnet-fwb-az1 subnet-fwb-az2 subnet-faz-az1 |
控制网络虚拟设备(NVA)的出站路由表,FortiGate-VM 防火墙、FortiWeb-VM 应用防火墙、FortiAnalyzer-VM 日志分析的 EIP 弹性公网 IP 均使用该路由表出站,默认路由指向 IGW |
rtb-app-az1 | subnet-app-az1 | 控制应用服务实例的出站,默认路由指向各可用区的 NAT 网关(natgw) |
rtb-app-az2 | subnet-app-az2 |
6. 方案部署说明
6.1 Terraform 概述
可以通过 Github Fortinet 中国区的仓库获取 Fortinet 中国区工程师已经编写完成的 Terraform 自动化部署工程,解决方案对应的 Terraform 工程,在 Github 上 terraform-fortinet-china/terraform-awschina/fgtvm-gwlb-with-fwb/的目录找到,如右图:
6.2 Terraform 部署
- 初始化工程项目
确保进入 fgtvm-gwlb-with-fbw 工程目录后,再运行下列命令;
如果您已经按照 Github Fortinet 中国区的仓库的说明指导完成了初始化,请忽略这一步。
- 修改 tfvars 以适配您的项目需求
ProjectName = “fgtvm-gwlb-with-fwb” | # 您的项目名称 |
CompanyName = “FTNT” | # 您的公司名称 |
enableNewVpcNgfw = true | # 是否新建 VPC 和 Internet 网关。如果 false,请参照文件中的指导,在 DryRun 时传入 ID |
enableNlbPreserveClientIp = true | # 是否开启 NLB 的保持 ClientIP 功能 该功能在本工程配置下,后续仅能通过 CLI 控制 |
enableDemoBastion = false | # 是否部署用于演示用途的堡垒机(VNC) |
该堡垒机不支持 GB/T 22239-2019 | |
regionName = “cn-northwest-1” | # 您项目部署的亚马逊云科技 Region |
# azList = [“a”] # azList = [“b”] # azList = [“c”] azList = [“a”, “b”] # azList = [“a”, “c”] # azList = [“b”, “c”] # azList = [“a”, “b”, “c”] |
# 您将要使用的可用区,以及可用区数量 选择单 AZ,双 AZ,三 AZ,其余保持注释状态即可 |
vpcName = “VPC-NGFW” | # 您的 VPC 名称,当上方 enableNewVpcNgfw 为 false 时,仅需要修改 VPC 的 CIDR,与您实际的 CIDR 保持一致即可 |
cidrVpcNgfw = “172.25.0.0/16” | |
cidrSubnetFgtPort1 | # cidrSubnetFgtPort1 为 FortiGate-VM 防火墙 Port1 对应 3 个可用区的子网。如果仅有 1 个可用区,则实际仅第一组 IP 会生效。其它的子网以此类推。 |
cidrSubnetFgtPort2 | |
cidrSubnetFwbPort1 | |
cidrSubnetNlbPublic | |
cidrSubnetNatgwVpcNgfw | |
cidrSubnetGwlbeNgfw | |
cidrSubnetApp | |
cidrSubnetBastionVncAz1 | # 演示用 VNC 堡垒机的子网 |
cntFgtByol = 0 | # FortiGate-VM BYOL 许可的部署数量 |
licenseFiles | # BYOL 的许可文件,请 copy 到本目录下 |
cntFgtPayg = 1 | # FortiGate-VM PAYG 的部署数量 |
instanceTypeFgtFixed = “c5.large” | # BYOL 和 PAGY 实例的类型。对于 BYOL 许可,请确保许可 vCPU 数量与实例类型匹配 |
portFgtHttps = “8443” | # FortiGate-VM 防火墙的 GUI 管理端口 |
versionFgt = “fgtvm70” | # FortiGate-VM 防火墙部署的版本,可后续升级 |
cntFwbByol = 1 | # FortiWeb-VM 应用防火墙的部署数量 |
instanceTypeFwbFixed = “m5.large” | # FortiWeb-VM 应用防火墙的实例类型 |
portFwbHttps = “8443” | # FortiWeb-VM 应用防火墙的 GUI 管理端口 |
portsNlb | # NLB 的监听、业务、健康检查端口定义 |
versionUbuntu = “bionic1804” | # 测试 Ubuntu 实例的版本 18.04,20.04,22.04 |
keynameUbuntu = “kpc_ubuntu” | # 测试 Ubuntu 实例的 KeyPair 名称 |
- DryRun
当您完成上步,即 Terraform 工程与您亚马逊云科技环境的适配后,您就可以执行下面的命令,测试 Terraform 是否满足部署条件。
[注] 期间可能会弹出 Warning 或者 Error,主要是由于镜像市场 Marketplace 订阅导致的,如上图,请点击进入 FortiGate-VM 的产品,选择订阅即可。
请针对 FortiWeb-VM 重复同样的订阅操作。
- 部署
如果上步的 DryRun 通过,您可以观察到 terraform 输出的 FortiGate-VM、FortiWeb-VM 登录信息以及业务 NLB 的访问 URL,取决于您是否选择部署堡垒机,输出会有不同。
6.3 FortiWeb 演示配置
FortiWeb,简称为 FWB,是 Fortinet 的 WAF 产品。可保护托管的 Web 应用免受针对已知和未知漏洞的攻击。FortiWeb 使用人工智能增强的多层次和关联检测方法,为应用程序提供针对已知漏洞和零日威胁的防护。
6.3.1 配置 FWB 的“虚拟服务器”(Virtual Server)
config server-policy vserver | # 进入 Virtual Server 的配置 |
edit “vsrv” | # 创建名为’vsrv’的 Virtual Server |
config vip-list | |
edit 0 | |
set interface port1 | # 对于云上的 FWB 实例,通常建议使用主弹性网卡对应的 port1 |
set use-interface-ip enable | # 使用实例主弹性网卡,而非 VIP |
next | |
end | |
next | |
end |
6.3.2 配置 FWB 的“服务器池”(Server Pool)
- 创建针对 Terraform 中 WEB 服务器实例的 Server Pool
当上节 Terraform 创建时,terraform.tfvar 文件中的变量 enableSimpleWebSrv = true 时,即表示部署一组简单的 WEB 应用实例,其中位于可用区 1 的 subnet-app 的 IP 为 192.168.251.72(请根据您 Terraform 部署后的实例实际 IP 填写),当从浏览器发起访问,如 http://nlb-public-98bfxxxx3f4exxxx.elb.cn-northwest-1.amazonaws.com.cn 时,请求将由 FWB 反向代理发送至这个 192.168.251.72 的 WEB 实例。
config server-policy server-pool | # 进入 Server Pool 的配置 |
edit “websrv“ | # 创建名为’websrv’的 Server Pool |
config pserver-list | |
edit 0 | |
set ip 192.168.251.72 | # 为便于理解,此处仅配置可用区 1 的 WEB 实例 |
next | |
end | |
next | |
end |
- 创建针对 Terraform 中 DVWA 靶场的 Server Pool
当上节 Terraform 创建时,terraform.tfvar 文件中的变量 enableDemoDvwa = true 时,即表示部署一个 DVWA 靶场实例,其中位于可用区 1 的 subnet-app 的 IP 为 192.168.251.112(请根据您 Terraform 部署后的实例实际 IP 填写),当从浏览器发起访问,如 http://nlb-public-98bfxxxx3f4exxxx.elb.cn-northwest-1.amazonaws.com.cn/DVWA/login.php 时,请求将由 FWB 反向代理发送至这个 192.168.251.112 的 DVWA 实例。
config server-policy server-pool | # 进入 Server Pool 的配置 |
edit “DVWA“ | # 创建名为’DVWA’的 Server Pool |
config pserver-list | |
edit 0 | |
set ip 192.168.251.112 | # 此即为 DVWA 的内网 IP |
next | |
end | |
next | |
end |
6.3.3 配置 FWB 的“WEB 保护”(Web Protection Profile)
- 创建针对 Terraform 中 WEB 服务器实例的 Web Protection Profile
config waf web-protection-profile inline-protection | # 进入 WEB 保护的配置 | |
edit “websrv-protection“ | # 创建名为’websrv-protection’的 WEB 保护 | |
set signature-rule “Standard Protection” | # Standard Protection 为 FWB 内置的特征库 | |
set file-upload-policy WebShell-Uploading | # 文件上传防护为 FWB 内置的’WebShell-Uploading’ | |
set webshell-detection-policy WebShell-Uploading | # 同上,FWB 已内置 | |
set custom-access-policy “Predefined – Advanced Protection” | # 同上,FWB 已内置 | |
set ip-intelligence enable | ||
set bot-mitigate-policy “Predefined – Bot Mitigation” | # 同上,FWB 已内置 | |
next | ||
end |
- 创建针对 Terraform 中 DVWA 靶场的 Web Protection Profile
DVWA 的 Web Protection Profile 将暂时与 WEB 服务器实例共用 websrv 这个 profile。
6.3.4 配置 FWB 的“HTTP 内容路由”(HTTP Content Routing)
- 创建针对 WEB 服务器的内容路由
config server-policy http-content-routing-policy | # 进入内容路由策略的配置 |
edit “croute-websrv“ | # 创建名为’croute-websrv’的策略 |
set server-pool websrv | # 将服务器池 websrv 与本内容路由策略关联 |
config content-routing-match-list | |
edit 1 | |
set match-condition equal | |
set match-expression nlb-public-98bfxxxx3f4exxxx.elb.cn-northwest-1.amazonaws.com.cn | # 当命中该 HTTP-HOST 时,将触发内容路由,将请求代理到服务器池 websrv |
set concatenate or | |
next | |
end | |
next | |
end |
- 创建针对 DVWA 靶场的内容路由
config server-policy http-content-routing-policy | # 进入内容路由策略的配置 |
edit “croute-dvwa“ | # 创建名为’croute-dvwa’的策略 |
set server-pool DVWA | # 将服务器池 DVWA 与本内容路由策略关联 |
config content-routing-match-list | |
edit 1 | |
set match-object http-request | # 检查 HTTP-REQUEST |
set match-condition match-dir | # 检查 HTTP URL |
set match-expression DVWA | # 当 ULR 中含有 DVWA 的目录时,触发内容路由,将请求代理到服务器池 dvwa |
set concatenate or | |
next | |
end | |
next | |
end |
- 创建“服务器策略”(Server Policy)
config server-policy policy | # 进入服务期策略(server-policy) |
edit “CONTENT-ROUTING“ | # 创建名为’CONTENT-ROUTING”的策略 |
set deployment-mode http-content-routing | |
set ssl enable | |
set vserver vsrv | |
set service HTTP | # 前端 HTTPS 访问,TLS 的卸载会发生在 NLB,所以 FWB 接收的流量均是 HTTP |
set replacemsg Predefined | |
set ssl-custom-cipher ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-ECDSA-CHACHA20-POLY1305 ECDHE-RSA-CHACHA20-POLY1305 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES256-SHA384 ECDHE-RSA-AES256-SHA384 ECDHE-ECDSA-AES128-SHA256 ECDHE-RSA-AES128-SHA256 ECDHE-ECDSA-AES256-SHA ECDHE-RSA-AES256-SHA ECDHE-ECDSA-AES128-SHA ECDHE-RSA-AES128-SHA AES256-GCM-SHA384 AES128-GCM-SHA256 AES256-SHA256 AES128-SHA256 | |
config http-content-routing-list | |
edit 2 | # 暂时从 2 开始,1 预留给 lambda |
set content-routing-policy-name croute-dvwa | # 使用上步创建的内容路由策略“croute-dvwa” |
set web-protection-profile websrv-protection | # 暂时使用”WEB 保护”创建的 websrv-protection |
next | |
edit 3 | |
set content-routing-policy-name croute-websrv | # 使用上步创建的内容路由策略“croute-websrv” |
set web-protection-profile websrv-protection | # 使用”WEB 保护”创建的 websrv-protection |
next | |
end | |
set tlog enable | # 启用流量日志 |
next | |
end |
6.4 防暴力破解配置
我们将对 websrv 的 URL(http://nlb-public-98bfxxxx3f4exxxx.elb.cn-northwest-1.amazonaws.com.cn)和对 DVWA 的 URL(https://nlb-public-98bfxxxx3f4exxxx.elb.cn-northwest-1.amazonaws.com.cn/DVWA/login.php)的 HTTP 访问更新为 HTTPS 访问,即 websrv(https://nlb-public-98bfxxxx3f4exxxx.elb.cn-northwest-1.amazonaws.com.cn)和 DVWA(https://nlb-public-98bfxxxx3f4exxxx.elb.cn-northwest-1.amazonaws.com.cn/DVWA/login.php)。
6.4.1 识别应用的登录失败
如下图所示,打开浏览器的开发者模式,在 DVWA 的 login.php 页面,输入错误账号,并尝试登录(正确账号为:admin/password),可以观察到如下图的“Login failed”的 div 字段,并记录下该字段的 HTML,如 class=”message”>Login failed
6.4.2 在 FWB 上创建针对登陆失败的自定义特征
- 在下面标红的配置中,填入上步通过浏览器开发者模式获取到的,可以证明是 Login failed 的 HTML,并注意转义字符需要使用’\\”或”\\\”
config waf custom-protection-rule | # 进入 WAF 自定义特征规则定义 |
edit “CustSignature-BruteForce“ | # 创建名为”CustSignature-BruteForce” |
set type response | # 设置规则将匹配的 HTTP 类型为响应 |
config meet-condition | |
edit 0 | |
set response-target RESPONSE_BODY | # 设置在 response body 中检测匹配 |
set expression “class\\=\\\”message\\\”>Login failed” | # 设置匹配检测的 HTML 字段 |
next | |
end | |
next | |
end |
- 上步创建了识别 Login failed 的自定义规则 CustSignature-BruteForce,本步创建自定义规则组 BruteForce,并关联自定义规则 CustSignature-BruteForce
config waf custom-protection-group | # 进入 WAF 自定义特征规则组定义 |
edit “BruteForce“ | # 创建名为”BruteForce”的特征组 |
config type-list | |
edit 0 | |
set custom-protection-rule CustSignature-BruteForce | # 设置该特征组成员为上步创建的规则 |
next | |
end | |
next | |
end |
- 上步创建了识别 Login failed 的自定义规则组,本步创建 WAF 特征,如 DVWA-BruteForce,并关联自定义规则组 BruteForce
config waf signature | # 进入 WAF 特征定义 |
edit “DVWA-BruteForce“ | # 创建名为”DVWA-BruteForce”的特征 |
set custom-protection-group BruteForce | # 设置该特征使用上步创建的自定义规则组 |
next | |
end |
6.4.3 在 FWB 上创建针对 DVWA 密码暴力破解的防御规则
上节创建了识别登陆失败的自定义 WAF 特征,本节的目标是识别到该特征后,如何定义防御动作触发的规则。
- 如下所示,创建防御规则 BruteForceThreshold,并关联上节创建的登陆失败特征 CustSignature-BruteForce,定义当 10 秒内,匹配两次该特征,即触发防暴破
config waf custom-access rule | # 进入 WAF 防御规则定义 |
edit “BruteForceThreshold“ | # 创建名为”BruteForceThreshold”的定义 |
set action block-period | # 设置该规则动作为“周期阻断” |
set bot-confirmation enable | |
set bot-recognition captcha-enforcement | # 设置判断 bot 方式为 captcha |
config custom-signature | # 进入关联 WAF 特征定义 |
edit 0 | |
set custom-signature-enable enable | |
set custom-signature-type custom-signature | |
set custom-signature-name CustSignature-BruteForce | # 设置 WAF 特征为上节创建的自定义特征 |
next | |
end | |
config occurrence | # 设置该特征的触发阈值 |
edit 0 | |
set occurrence-num 2 | # 在 10 秒内,触发两次 login failed |
set within 10 | |
next | |
end | |
next | |
end |
- 上步创建了防御规则 BruteForceThreshold,本步创建防御规则组 BruteForceIdentification,并关联防御规则 BruteFroceThreshold
config waf custom-access policy | # 进入 WAF 防御规则组定义 |
edit “BruteForceIdentification“ | # 创建名为”BruteForceIdentification”的规则组 |
config rule | |
edit 0 | |
set rule-name BruteForceThreshold | # 设置该组使用的防御规则 |
next | |
end | |
next | |
end |
6.4.4 在 FWB 上更新针对 DVWA 的“WEB 保护”
- 创建 DVWA 防暴破专门的 WEB 保护 dvwa-protection,如下所示
config waf web-protection-profile inline-protection | # 进入 WEB 保护的配置 |
edit “dvwa-protection“ | # 创建名为”dvwa-protection”的规则组 |
set signature-rule DVWA-BruteForce | # WAF 特征关联 DVWA-BruteForce |
set custom-access-policy BruteForceIdentification | # WAF 防御规则关联 BruteForceIdentification |
set ip-intelligence enable | |
set bot-mitigate-policy “Predefined – Bot Mitigation” | # FWB 内置防御规则组 |
next | |
end |
- 将 websrv-protection 更新为专门为 DVWA 防暴破定义的 WEB 保护 dvwa-protection
config server-policy policy | # 进入服务期策略(server-policy) |
edit “CONTENT-ROUTING“ | # 进入为’CONTENT-ROUTING”的策略 |
config http-content-routing-list | |
edit 2 | # 进入 2,编辑 DVWA |
set web-protection-profile dvwa-protection | # 将 websrv-protection 修改为上步创建的 dvwa-protection |
next | |
end | |
next | |
end |
7. 方案效果展示
- 访问 URL,如 https://nlb-public-98bfxxxx3f4exxxx.elb.cn-northwest-1.amazonaws.com.cn/DVWA/login.php,在如下图出现的页面中,10 秒内连续 2 次输入错误账号并尝试登录。
- 当第 3 次尝试登陆时,将触发 FWB 执行防暴破规则,弹出 captcha 验证界面,如下图所示,即通过 captcha 阻止 bot 发起的针对应用登录的暴力密码破解。
您可以在亚马逊云科技 Marketplace 中订阅并采购本方案中的 Fortinet 相关产品:
FortiGate:
BYOL(Graviton):FortiGate Next-Generation Firewall (ARM64/Graviton)
BYOL:FortiGate Next-Generation Firewall (BYOL)
FortiWeb:
FortiWeb Web Application Firewall WAF VM (BYOL)