🎯 Mục Tiêu Lab
Upgrade AppGW Standard_v2 lên WAF_v2 SKU (hoặc deploy mới)
Tạo WAF Policy với OWASP CRS 3.2 managed ruleset
Gắn WAF Policy vào Application Gateway ở chế độ Prevention
Test SQL Injection và XSS payload — xác nhận WAF chặn (HTTP 403)
Thêm custom rule IP exclusion (whitelist IP admin)
Xem WAF logs (ApplicationGatewayFirewallLog) trong Log Analytics
📋 Chuẩn Bị
- Hoàn thành Lab 26 — AppGW Standard_v2 đang chạy
- Log Analytics Workspace (tạo mới hoặc từ Lab 25)
- curl hoặc Postman để test WAF
- Chỉ test WAF trên lab của bạn — không bao giờ test trên hệ thống người khác
- WAF_v2 tốn thêm ~$0.444/giờ so với Standard_v2
- Detection mode: log only. Prevention mode: block + log
🏗️ Kịch Bản
Web app từ Lab 26 cần được bảo vệ khỏi OWASP Top 10 attacks. WAF Policy với OWASP CRS 3.2 phân tích mọi HTTP request ở Layer 7, block SQL Injection, XSS và các tấn công phổ biến trước khi request tới backend.
Attacker → SQL Injection / XSS payload
│
▼
[App Gateway WAF_v2] ← WAF Policy (OWASP CRS 3.2)
│ ├─ Managed Rules: SQLi, XSS, RCE
│ HTTP 403 ├─ Custom Rules: IP block/allow
◄─── BLOCKED └─ Mode: Prevention
│
│ Normal requests only
▼
[Backend Nginx VM] ← protected
🧪 Các Bước Thực Hiện
Upgrade AppGW lên WAF_v2 SKU
AppGW Standard_v2 có thể upgrade lên WAF_v2 in-place mà không cần xóa và tạo lại. Quá trình mất ~2–5 phút.
- 1.1appgw-lab26 (từ Lab 26) → Configuration → Tier: đổi từ Standard V2 sang WAF V2 → Save
- 1.2Đợi ~3 phút → Notifications báo "Successfully updated" → kiểm tra Overview: Tier = WAF V2
- 1.3Web Application Firewall (WAF) → WAF status: Enabled → WAF mode: Detection (sẽ đổi sang Prevention sau)
RG="rg-lab26-appgw"
# Upgrade AppGW từ Standard_v2 lên WAF_v2
az network application-gateway update \
--resource-group $RG \
--name appgw-lab26 \
--sku WAF_v2
# Xác nhận SKU đã đổi
az network application-gateway show \
--resource-group $RG \
--name appgw-lab26 \
--query "{sku:sku.name,tier:sku.tier,state:provisioningState}" \
--output table
Tạo WAF Policy với OWASP CRS 3.2
WAF Policy là resource riêng biệt, có thể tái dùng trên nhiều AppGW hoặc listener. OWASP CRS 3.2 là phiên bản mới nhất được khuyến nghị 2026.
- 2.1Web Application Firewall policies → + Create → Policy for: Regional WAF (Application Gateway)
- 2.2RG: rg-lab26-appgw → Name:
waf-policy-lab27→ Region: Southeast Asia - 2.3Tab Managed Rules → Rule set: OWASP → Version: 3.2 (khuyến nghị)
- 2.4Tab Policy settings → Mode: Detection (bắt đầu để test) → Inspection limit: 128 KB → Review + Create
- 2.5Tab Associated application gateways → + Associate → appgw-lab26 → Save
RG="rg-lab26-appgw"
# Tạo WAF Policy với OWASP CRS 3.2, chế độ Detection
az network application-gateway waf-policy create \
--resource-group $RG \
--name waf-policy-lab27 \
--location southeastasia
# Cập nhật managed rule set: OWASP 3.2
az network application-gateway waf-policy managed-rule rule-set add \
--resource-group $RG \
--policy-name waf-policy-lab27 \
--type OWASP \
--version 3.2
# Đặt mode Detection (log nhưng không block, để baseline trước)
az network application-gateway waf-policy policy-setting update \
--resource-group $RG \
--policy-name waf-policy-lab27 \
--mode Detection \
--state Enabled \
--max-request-body-size-kb 128
# Lấy AppGW resource ID
APPGW_ID=$(az network application-gateway show \
--resource-group $RG --name appgw-lab26 --query id --output tsv)
# Gắn WAF Policy vào AppGW
az network application-gateway update \
--resource-group $RG \
--name appgw-lab26 \
--waf-policy waf-policy-lab27
# Xác nhận WAF Policy đã gắn
az network application-gateway show \
--resource-group $RG --name appgw-lab26 \
--query "firewallPolicy.id" --output tsv
Bật Log Analytics và Diagnostic Settings
WAF Firewall logs phải gửi về Log Analytics để xem. Cần có trước khi test.
RG="rg-lab26-appgw"
# Tạo Log Analytics Workspace (nếu chưa có)
az monitor log-analytics workspace create \
--resource-group $RG \
--workspace-name law-lab27 \
--location southeastasia \
--sku PerGB2018 \
--retention-time 30
LAW_ID=$(az monitor log-analytics workspace show \
--resource-group $RG --workspace-name law-lab27 \
--query id --output tsv)
APPGW_ID=$(az network application-gateway show \
--resource-group $RG --name appgw-lab26 --query id --output tsv)
# Bật WAF Firewall log gửi về Log Analytics
az monitor diagnostic-settings create \
--resource "$APPGW_ID" \
--name diag-appgw-waf \
--workspace "$LAW_ID" \
--logs '[
{"category":"ApplicationGatewayFirewallLog","enabled":true},
{"category":"ApplicationGatewayAccessLog","enabled":true},
{"category":"ApplicationGatewayPerformanceLog","enabled":true}
]' \
--metrics '[{"category":"AllMetrics","enabled":true}]'
echo "Diagnostic settings created. WAF logs will flow to Log Analytics."
Đổi Mode sang Prevention và Test WAF
Đổi sang Prevention mode rồi gửi payload SQL Injection và XSS. WAF phải trả về HTTP 403 (blocked).
- 4.1waf-policy-lab27 → Policy settings → Mode: đổi từ Detection sang Prevention → Save
- 4.2Đợi ~1 phút để policy apply → tiến hành test
RG="rg-lab26-appgw"
# Đổi WAF Policy sang Prevention mode
az network application-gateway waf-policy policy-setting update \
--resource-group $RG \
--policy-name waf-policy-lab27 \
--mode Prevention \
--state Enabled
echo "WAF now in Prevention mode. Testing..."
# Lấy AppGW Public IP
APPGW_IP=$(az network public-ip show \
--resource-group rg-lab26-appgw --name pip-appgw-lab26 \
--query ipAddress --output tsv)
echo "AppGW IP: $APPGW_IP"
# Test 1: Request bình thường — phải trả về HTTP 200
echo "--- Normal request ---"
curl -s -o /dev/null -w "HTTP %{http_code}\n" http://$APPGW_IP/
# Test 2: SQL Injection — WAF phải block (HTTP 403)
echo "--- SQL Injection test ---"
curl -s -o /dev/null -w "HTTP %{http_code}\n" \
"http://$APPGW_IP/?id=1%27%20OR%20%271%27=%271"
# Test 3: XSS payload — WAF phải block (HTTP 403)
echo "--- XSS test ---"
curl -s -o /dev/null -w "HTTP %{http_code}\n" \
"http://$APPGW_IP/?q="
# Test 4: Path traversal — WAF phải block (HTTP 403)
echo "--- Path traversal test ---"
curl -s -o /dev/null -w "HTTP %{http_code}\n" \
"http://$APPGW_IP/../../etc/passwd"
# Test 5: User-Agent injection (HTTP Header attack)
echo "--- Header injection test ---"
curl -s -o /dev/null -w "HTTP %{http_code}\n" \
-H "User-Agent: () { :;}; echo Content-Type: text/html; echo; /bin/cat /etc/passwd" \
http://$APPGW_IP/
Test 1 (normal): HTTP 200 — pass through.
Test 2–5 (attacks): HTTP 403 — WAF blocked. Body chứa "403 Forbidden" từ Azure WAF.
Xem WAF Logs và Thêm Custom Rule
Xem WAF Firewall logs qua KQL. Thêm custom rule block IP cụ thể (custom IP deny list).
// Xem WAF Firewall logs (15 phút gần nhất)
AzureDiagnostics
| where ResourceType == "APPLICATIONGATEWAYS"
| where Category == "ApplicationGatewayFirewallLog"
| where TimeGenerated > ago(15m)
| project TimeGenerated,
Action=action_s,
RuleId=ruleId_s,
RuleGroup=ruleGroup_s,
Message=Message,
ClientIP=clientIp_s,
RequestURI=requestUri_s
| order by TimeGenerated desc
// Thống kê rules triggered nhiều nhất
AzureDiagnostics
| where Category == "ApplicationGatewayFirewallLog"
| where action_s == "Blocked"
| summarize Count=count() by RuleId=ruleId_s, RuleGroup=ruleGroup_s
| order by Count desc
// Xem IPs bị block nhiều nhất
AzureDiagnostics
| where Category == "ApplicationGatewayFirewallLog"
| where action_s == "Blocked"
| summarize BlockCount=count() by ClientIP=clientIp_s
| order by BlockCount desc
| take 10
RG="rg-lab26-appgw"
# Thêm custom rule: block một IP cụ thể (ví dụ block 1.2.3.4)
# Priority thấp hơn = ưu tiên hơn managed rules (priority 1 = first)
az network application-gateway waf-policy custom-rule create \
--resource-group $RG \
--policy-name waf-policy-lab27 \
--name block-bad-ip \
--priority 1 \
--rule-type MatchRule \
--action Block
# Thêm match condition: RemoteAddr equals 1.2.3.4
az network application-gateway waf-policy custom-rule match-condition add \
--resource-group $RG \
--policy-name waf-policy-lab27 \
--rule-name block-bad-ip \
--match-variables RemoteAddr \
--operator IPMatch \
--values "1.2.3.4/32"
# Xem danh sách custom rules
az network application-gateway waf-policy custom-rule list \
--resource-group $RG \
--policy-name waf-policy-lab27 \
--output table
📊 Kết Quả Đầu Ra Lab 27
SKU: WAF_v2, WAF Policy: waf-policy-lab27 (OWASP 3.2)
Rule 942100 (SQLi group) triggered → action: Blocked
Rule 941100 (XSS group) triggered → action: Blocked
ApplicationGatewayFirewallLog có entries với action=Blocked
Custom rule priority 1: block IP 1.2.3.4/32
Firewall egress, DNAT, Policy+ThreatIntel, AppGW, WAF — đủ checklist AZ-500
🧹 Dọn Dẹp Tài Nguyên
Xóa resource group chứa AppGW, WAF Policy, VM backend và Log Analytics.
# Xóa resource group từ Lab 26 (chứa AppGW, WAF, VM backend)
az group delete --name rg-lab26-appgw --yes --no-wait
# Xác nhận không còn resource nào
az group list --query "[?name=='rg-lab26-appgw']" --output table
❓ Câu Hỏi Ôn Tập
1. WAF Detection mode và Prevention mode khác nhau như thế nào? Khi nào chuyển từ Detection sang Prevention?
Gợi ý: Detection = log only, không block. Prevention = log + block. Chuyển sang Prevention sau khi review log Detection 1–2 tuần để loại bỏ false positives.
2. OWASP CRS 3.2 bảo vệ khỏi những loại tấn công nào? Kể ít nhất 5 nhóm rule.
Gợi ý: SQL Injection (942xxx), XSS (941xxx), Remote File Inclusion (931xxx), Local File Inclusion (930xxx), PHP Injection (933xxx), Remote Code Execution (932xxx), Scanner Detection (913xxx), Session Fixation (943xxx).
3. Custom Rule trong WAF có priority 1, Managed Rules có priority mặc định nào? Rule nào xử lý trước?
Gợi ý: Custom Rules priority 1–100 được xử lý trước Managed Rules. Số nhỏ hơn = ưu tiên hơn. Managed Rules mặc định priority không cấu hình được (luôn sau Custom Rules).
4. Nếu WAF block một request hợp lệ (false positive), bạn xử lý như thế nào mà không tắt WAF?
Gợi ý: Dùng Exclusion Rules để bỏ qua specific rule cho specific request attribute (vd: header X-Custom-Token). Hoặc disable rule cụ thể trong Managed Rules. Không nên tắt cả WAF.
5. WAF Policy gắn vào AppGW vs gắn vào từng Listener: sự khác nhau là gì?
Gợi ý: Policy gắn vào AppGW = áp dụng cho tất cả traffic. Policy gắn vào Listener = áp dụng riêng cho listener đó (override policy cấp AppGW). Dùng per-listener policy khi cần WAF khác nhau cho nhiều app trên cùng AppGW.