總結
本文將協助你排除 Azure 應用程式閘道 的 Web 應用程式防火牆 (WAF) 問題,當合法請求被封鎖時,你可以允許有效流量同時維持保護。
首先檢視 WAF 概覽 與 WAF 設定 文件,並確保已啟用 WAF 監控 。 這些文章說明了 WAF 的運作方式、規則集的運作方式,以及如何存取 WAF 日誌。
OWASP 規則集設計為出廠時即非常嚴格,並可根據使用 WAF 的應用程式或組織的特定需求進行細微調整。 建立排除、自訂規則,甚至停用可能造成問題或誤判的規則,是完全正常且在許多情況下預期中的。 每個站點及每個 URI 的政策允許這些變更只影響特定站點或 URI。 因此,變更不應該影響到可能沒有遇到相同問題的其他網站。
了解 WAF 日誌
WAF 日誌的目的是顯示每一個被 WAF 匹配或阻擋的請求。 它是所有被評估過、被匹配或被封鎖的請求的帳本。 如果你發現 WAF 阻擋了不該阻擋的請求(誤判),你可以採取幾個步驟。 首先,縮小範圍,找到具體的需求。 查看日誌,找出請求的特定 URI、時間戳或交易 ID。 當你找到相關的日誌條目後,就可以開始對誤報採取行動。
舉例來說,假設您擁有一個合法的網路流量,其中包含您想通過 WAF 的字串 1=1。 如果你嘗試這個請求,WAF 會阻擋包含你 1=1 字串的任何參數或欄位的流量。 此字串通常與 SQL 插入式攻擊相關聯。 您可以瀏覽記錄,查看要求的時間戳記,以及封鎖或符合的規則。
在以下範例中,你可以看到在同一請求中(使用 TransactionId 欄位)會觸發四條規則。 第一項指出之所以相符,是因為使用者在提出請求時使用了數字 IP 位址,而這會因屬於警告而使異常分數增加 3 分。 下一個符合的規則是 942130,這正是你要找的。 你可以在1=1欄位裡看到details.data。 這又讓異常分數再增加三分,因為它同時也是警告。 一般來說,每一條規則中動作為 匹配 ,異常分數都會增加,此時異常分數為六分。 更多資訊請參閱 異常評分模式。
最後兩筆日誌顯示請求被封鎖是因為異常分數夠高。 這些條目的作用方式與其他兩個不同。 他們顯示他們 真的封鎖 了這個請求。 這些規則是強制性的,無法被關閉。 不要把這些規則當作規則,而是WAF內部的核心基礎設施。
{
"resourceId": "/SUBSCRIPTIONS/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1/RESOURCEGROUPS/MYRESOURCEGROUP/PROVIDERS/MICROSOFT.NETWORK/APPLICATIONGATEWAYS/DEMOWAF-V2",
"operationName": "ApplicationGatewayFirewall",
"category": "ApplicationGatewayFirewallLog",
"properties": {
"instanceId": "appgw_3",
"clientIp": "203.0.113.139",
"clientPort": "",
"requestUri": "\/",
"ruleSetType": "OWASP_CRS",
"ruleSetVersion": "3.0.0",
"ruleId": "920350",
"message": "Host header is a numeric IP address",
"action": "Matched",
"site": "Global",
"details": {
"message": "Warning. Pattern match \\\"^[\\\\\\\\d.:]+$\\\" at REQUEST_HEADERS:Host. ",
"data": "40.90.218.160",
"file": "rules\/REQUEST-920-PROTOCOL-ENFORCEMENT.conf\\\"",
"line": "791"
},
"hostname": "vm000003",
"transactionId": "AcAcAcAcAKH@AcAcAcAcAyAt"
}
}
{
"resourceId": "/SUBSCRIPTIONS/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1/RESOURCEGROUPS/MYRESOURCEGROUP/PROVIDERS/MICROSOFT.NETWORK/APPLICATIONGATEWAYS/DEMOWAF-V2",
"operationName": "ApplicationGatewayFirewall",
"category": "ApplicationGatewayFirewallLog",
"properties": {
"instanceId": "appgw_3",
"clientIp": "203.0.113.139",
"clientPort": "",
"requestUri": "\/",
"ruleSetType": "OWASP_CRS",
"ruleSetVersion": "3.0.0",
"ruleId": "942130",
"message": "SQL Injection Attack: SQL Tautology Detected.",
"action": "Matched",
"site": "Global",
"details": {
"message": "Warning. Pattern match \\\"(?i:([\\\\\\\\s'\\\\\\\"`\\\\\\\\(\\\\\\\\)]*?)([\\\\\\\\d\\\\\\\\w]++)([\\\\\\\\s'\\\\\\\"`\\\\\\\\(\\\\\\\\)]*?)(?:(?:=|\\u003c=\\u003e|r?like|sounds\\\\\\\\s+like|regexp)([\\\\\\\\s'\\\\\\\"`\\\\\\\\(\\\\\\\\)]*?)\\\\\\\\2|(?:!=|\\u003c=|\\u003e=|\\u003c\\u003e|\\u003c|\\u003e|\\\\\\\\^|is\\\\\\\\s+not|not\\\\\\\\s+like|not\\\\\\\\s+regexp)([\\\\\\\\s'\\\\\\\"`\\\\\\\\(\\\\\\\\)]*?)(?!\\\\\\\\2)([\\\\\\\\d\\\\\\\\w]+)))\\\" at ARGS:text1. ",
"data": "Matched Data: 1=1 found within ARGS:text1: 1=1",
"file": "rules\/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\\\"",
"line": "554"
},
"hostname": "vm000003",
"transactionId": "AcAcAcAcAKH@AcAcAcAcAyAt"
}
}
{
"resourceId": "/SUBSCRIPTIONS/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1/RESOURCEGROUPS/MYRESOURCEGROUP/PROVIDERS/MICROSOFT.NETWORK/APPLICATIONGATEWAYS/DEMOWAF-V2",
"operationName": "ApplicationGatewayFirewall",
"category": "ApplicationGatewayFirewallLog",
"properties": {
"instanceId": "appgw_3",
"clientIp": "203.0.113.139",
"clientPort": "",
"requestUri": "\/",
"ruleSetType": "",
"ruleSetVersion": "",
"ruleId": "0",
"message": "Mandatory rule. Cannot be disabled. Inbound Anomaly Score Exceeded (Total Score: 8)",
"action": "Blocked",
"site": "Global",
"details": {
"message": "Access denied with code 403 (phase 2). Operator GE matched 5 at TX:anomaly_score. ",
"data": "",
"file": "rules\/REQUEST-949-BLOCKING-EVALUATION.conf\\\"",
"line": "57"
},
"hostname": "vm000003",
"transactionId": "AcAcAcAcAKH@AcAcAcAcAyAt"
}
}
{
"resourceId": "/SUBSCRIPTIONS/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1/RESOURCEGROUPS/MYRESOURCEGROUP/PROVIDERS/MICROSOFT.NETWORK/APPLICATIONGATEWAYS/DEMOWAF-V2",
"operationName": "ApplicationGatewayFirewall",
"category": "ApplicationGatewayFirewallLog",
"properties": {
"instanceId": "appgw_3",
"clientIp": "203.0.113.139",
"clientPort": "",
"requestUri": "\/",
"ruleSetType": "",
"ruleSetVersion": "",
"ruleId": "0",
"message": "Mandatory rule. Cannot be disabled. Inbound Anomaly Score Exceeded (Total Inbound Score: 8 - SQLI=5,XSS=0,RFI=0,LFI=0,RCE=0,PHPI=0,HTTP=0,SESS=0): SQL Injection Attack: SQL Tautology Detected.",
"action": "Blocked",
"site": "Global",
"details": {
"message": "Warning. Operator GE matched 5 at TX:inbound_anomaly_score. ",
"data": "",
"file": "rules\/RESPONSE-980-CORRELATION.conf\\\"",
"line": "73"
},
"hostname": "vm000003",
"transactionId": "AcAcAcAcAKH@AcAcAcAcAyAt"
}
}
修正誤報
有了這些資訊,以及知道規則 942130 與該字串相符 1=1 ,你可以採取幾個步驟來阻止這條規則阻擋你的流量:
使用排除清單。 欲了解更多排除名單資訊,請參閱 WAF排除名單。
關閉該規則。
降低偏執等級 2 的誤判
在 OWASP CRS 3.2 中,SQL 注入規則 942430、 942440、 942450 屬於偏執等級 2(PL2)。 如果 WAF 日誌顯示合法的認證請求符合這些規則之一,請先確認該項貢獻請求欄位,再加排除。 確認請求是否合法,並標明其規則 ID 及已設定的規則集。 關於描述及版本特定的替換,請參見 WAF 規則群組與規則。 不要啟用非活躍規則或更改規則集只是為了模仿這個例子。
- 在 Log Analytics 中,如果您的診斷設定會將防火牆記錄傳送至
AzureDiagnostics資料表,請使用下列查詢。 把資源 ID 和時間範圍替換成你正在調查的閘道和區間。 這些日誌可能包含敏感的請求資料;不要共用欄位值或認證權杖。
執行下列查詢。
AzureDiagnostics
| where TimeGenerated > ago(1h)
| where _ResourceId =~ "<application-gateway-resource-id>"
| where Category == "ApplicationGatewayFirewallLog"
| where ruleId_s in ("942430", "942440", "942450")
| project TimeGenerated, transactionId_g, requestUri_s,
ruleId_s, action_s, details_message_s, details_data_s
| order by TimeGenerated desc
- 找出失敗的請求所對應的交易。 貢獻度規則可採取
Matched動作,而另一條獨立的異常評分規則會封鎖該交易。 若要檢查該交易的所有相符項目,請將規則 ID 篩選條件替換為針對transactionId_g的篩選條件。 不要排除異常得分規則而非貢獻規則。 - 對於已確認的誤判,請針對該特定欄位設定排除項目,且僅包含造成該結果的規則 ID。 每個規則的排除必須使用受支援的 WAF 原則規則集,例如 OWASP CRS 3.2。 用於
Equals欄位選擇器,並保留其他規則與現有政策設定。 請參閱 規則範圍的 CLI 與 PowerShell 程序 ,以及 每條規則排除的範例。 關於規則發現,請參閱 PowerShell 自訂指南 與 CLI 自訂指南。 - 回頭閱讀政策以確認排除內容包含預期的規則集版本、群組、規則 ID、匹配變數和選擇器。 已涵蓋該領域的全域排除仍然適用;增加更窄的排除範圍並不會消除它。 應分別檢視現有的廣泛排除條款,而非清除所有排除事項。
- 重複同樣的合法請求,並檢查它的回應和新的交易紀錄。 確認所選規則是否不再符合排除欄位,若請求仍被封鎖,請調查是否有其他相關規則。 沒有重現的流量且診斷資料收集未正常運作時,僅有空白查詢並不足以判定成功。 驗證在受控的測試環境中,不相關欄位仍維持在受檢查狀態。
不要自動排除所有三個 ID 或所有認證欄位。 在這項針對性變更中,請將WAF維持在預防模式。 如果需要撤銷,請只移除你在審查政策後新增的規則範圍排除條款;保留既有的排除條款。
使用排除清單
為了在處理誤報時做出明智的決策,請熟悉應用程式所使用的技術。 舉例來說,如果你的技術堆疊沒有包含 SQL 伺服器,且你在這些規則中遇到誤報,停用這些規則不一定會削弱你的安全性。
排除項目會將所選的請求屬性排除在檢查之外。 全域排除適用於所有受管理規則,而每規則排除則僅適用於支援規則集中所選規則。 兩者都適用於 WAF 政策所關聯的任何地方,因此在更改政策前請先驗證該政策的應用與路徑。 例如,排除某欄位可能產生風險,當 1=1 對某個應用程式有效,但另一個共享政策的應用程式則無效。 寧願採取狹義排除,也不願排除整個申請。
有時候,特定參數會以不直覺的方式傳入 WAF。 舉例來說,使用 Microsoft Entra ID 認證時會傳遞一個令牌。
__RequestVerificationToken 通常以請求 cookie 的形式傳遞。 然而,在某些情況下,當 cookie 被停用時,這個標記也會以請求屬性或 arg。 如果發生這種情況,你必須確保 __RequestVerificationToken 也被加入排除清單,作為 Request 屬性名稱 。
在這個範例中,你要排除等於 text1 的 Request 屬性名稱。 這個屬性名稱很明顯,因為你可以在防火牆日誌中看到屬性名稱: data: Matched Data: 1=1,可在 ARGS:text1: 1=1 中找到。 屬性是 text1。 你也可以用其他幾種方式找到這個屬性名稱,請參見 尋找請求屬性名稱。
你可以在 Application Gateway 中為 WAF 建立不同範圍層級的排除。 欲了解更多資訊,請參閱Web 應用程式防火牆排除清單。
停用規則
另一種處理誤報的方法,是停用符合 WAF 所判定為惡意之輸入內容的規則。 既然你解析了 WAF 日誌並縮小規則範圍到 942130,你可以在 Azure 入口網站中停用它。 請參考 透過 Azure 入口網站自訂網頁應用防火牆規則。
如果你知道所有包含某個條件且通常會被封鎖的流量都是有效流量,你可以在整個 WAF 中停用該規則。 但如果只有特定使用情境下的有效流量,因為 WAF 是全域設定,禁用該規則就會開啟漏洞。
要使用 Azure PowerShell,請參考透過 PowerShell 自訂網頁應用程式防火牆規則。 要使用 Azure CLI,請參考 Azure CLI 中的自訂網頁應用防火牆規則。
記錄 HAR 檔案
你可以使用瀏覽器或外部工具如 Fiddler 來錄製 HTTP Archive(HAR)檔案。 HAR 檔案包含瀏覽器在載入網頁時所發出的請求與回應資訊。 這些資訊對於排除 WAF 問題非常有用。
小提示
聯絡客服時,最好先準備好 HAR 檔案。 客服團隊可以使用 HAR 檔案來協助診斷問題。
要在 Microsoft Edge 中錄製並儲存 HAR 檔案,請依照以下步驟操作:
按 F12 或 Ctrl+Shift+I 即可開啟 Edge 開發人員工具。 你也可以從工具列選單中的 更多工具>開發人員工具 開啟這些工具。
在 控制台 標籤中,選擇 清除控制台 或按 Ctrl+L。
選取 [網路 ] 索引標籤。
選擇 清除網路日誌 或按 Ctrl+L,如果沒有錄影,再選擇 記錄網路日誌 。
載入由你的 WAF 保護且你想排除故障的網頁。
請選擇 「停止錄製網路日誌」來停止錄影。
選擇 匯出 HAR(消毒)...... 並儲存 HAR 檔案。
尋找請求屬性名稱
使用 Fiddler 檢查個別請求,並判斷網頁中具體的欄位被呼叫。 利用這些資訊,你可以透過排除清單來排除某些欄位。
在這個範例中,你可以看到輸入 1=1 字串的欄位稱為 text1。
這是一個你可以排除的欄位。 若要深入了解排除清單,請參閱 Web 應用程式防火牆排除清單。 此時您可以透過設定以下排除選項來排除該評估:
你也可以查看防火牆日誌,取得資訊,看看需要加入排除清單的是什麼。 要啟用日誌功能,請參閱 應用閘道的後端健康、資源日誌與指標。
查看防火牆日誌,並檢視 PT1H.json 檔案,以了解您想檢查的請求所發生的具體小時。
在這個例子中,你會看到有四條規則使用相同的 TransactionID,且它們都同時發生:
{
"resourceId": "/SUBSCRIPTIONS/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1/RESOURCEGROUPS/MYRESOURCEGROUP/PROVIDERS/MICROSOFT.NETWORK/APPLICATIONGATEWAYS/DEMOWAF-V2",
"operationName": "ApplicationGatewayFirewall",
"category": "ApplicationGatewayFirewallLog",
"properties": {
"instanceId": "appgw_3",
"clientIp": "203.0.113.139",
"clientPort": "",
"requestUri": "\/",
"ruleSetType": "OWASP_CRS",
"ruleSetVersion": "3.0.0",
"ruleId": "920350",
"message": "Host header is a numeric IP address",
"action": "Matched",
"site": "Global",
"details": {
"message": "Warning. Pattern match \\\"^[\\\\\\\\d.:]+$\\\" at REQUEST_HEADERS:Host. ",
"data": "40.90.218.160",
"file": "rules\/REQUEST-920-PROTOCOL-ENFORCEMENT.conf\\\"",
"line": "791"
},
"hostname": "vm000003",
"transactionId": "AcAcAcAcAKH@AcAcAcAcAyAt"
}
}
{
"resourceId": "/SUBSCRIPTIONS/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1/RESOURCEGROUPS/MYRESOURCEGROUP/PROVIDERS/MICROSOFT.NETWORK/APPLICATIONGATEWAYS/DEMOWAF-V2",
"operationName": "ApplicationGatewayFirewall",
"category": "ApplicationGatewayFirewallLog",
"properties": {
"instanceId": "appgw_3",
"clientIp": "203.0.113.139",
"clientPort": "",
"requestUri": "\/",
"ruleSetType": "OWASP_CRS",
"ruleSetVersion": "3.0.0",
"ruleId": "942130",
"message": "SQL Injection Attack: SQL Tautology Detected.",
"action": "Matched",
"site": "Global",
"details": {
"message": "Warning. Pattern match \\\"(?i:([\\\\\\\\s'\\\\\\\"`\\\\\\\\(\\\\\\\\)]*?)([\\\\\\\\d\\\\\\\\w]++)([\\\\\\\\s'\\\\\\\"`\\\\\\\\(\\\\\\\\)]*?)(?:(?:=|\\u003c=\\u003e|r?like|sounds\\\\\\\\s+like|regexp)([\\\\\\\\s'\\\\\\\"`\\\\\\\\(\\\\\\\\)]*?)\\\\\\\\2|(?:!=|\\u003c=|\\u003e=|\\u003c\\u003e|\\u003c|\\u003e|\\\\\\\\^|is\\\\\\\\s+not|not\\\\\\\\s+like|not\\\\\\\\s+regexp)([\\\\\\\\s'\\\\\\\"`\\\\\\\\(\\\\\\\\)]*?)(?!\\\\\\\\2)([\\\\\\\\d\\\\\\\\w]+)))\\\" at ARGS:text1. ",
"data": "Matched Data: 1=1 found within ARGS:text1: 1=1",
"file": "rules\/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\\\"",
"line": "554"
},
"hostname": "vm000003",
"transactionId": "AcAcAcAcAKH@AcAcAcAcAyAt"
}
}
{
"resourceId": "/SUBSCRIPTIONS/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1/RESOURCEGROUPS/MYRESOURCEGROUP/PROVIDERS/MICROSOFT.NETWORK/APPLICATIONGATEWAYS/DEMOWAF-V2",
"operationName": "ApplicationGatewayFirewall",
"category": "ApplicationGatewayFirewallLog",
"properties": {
"instanceId": "appgw_3",
"clientIp": "203.0.113.139",
"clientPort": "",
"requestUri": "\/",
"ruleSetType": "",
"ruleSetVersion": "",
"ruleId": "0",
"message": "Mandatory rule. Cannot be disabled. Inbound Anomaly Score Exceeded (Total Score: 8)",
"action": "Blocked",
"site": "Global",
"details": {
"message": "Access denied with code 403 (phase 2). Operator GE matched 5 at TX:anomaly_score. ",
"data": "",
"file": "rules\/REQUEST-949-BLOCKING-EVALUATION.conf\\\"",
"line": "57"
},
"hostname": "vm000003",
"transactionId": "AcAcAcAcAKH@AcAcAcAcAyAt"
}
}
{
"resourceId": "/SUBSCRIPTIONS/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1/RESOURCEGROUPS/MYRESOURCEGROUP/PROVIDERS/MICROSOFT.NETWORK/APPLICATIONGATEWAYS/DEMOWAF-V2",
"operationName": "ApplicationGatewayFirewall",
"category": "ApplicationGatewayFirewallLog",
"properties": {
"instanceId": "appgw_3",
"clientIp": "203.0.113.139",
"clientPort": "",
"requestUri": "\/",
"ruleSetType": "",
"ruleSetVersion": "",
"ruleId": "0",
"message": "Mandatory rule. Cannot be disabled. Inbound Anomaly Score Exceeded (Total Inbound Score: 8 - SQLI=5,XSS=0,RFI=0,LFI=0,RCE=0,PHPI=0,HTTP=0,SESS=0): SQL Injection Attack: SQL Tautology Detected.",
"action": "Blocked",
"site": "Global",
"details": {
"message": "Warning. Operator GE matched 5 at TX:inbound_anomaly_score. ",
"data": "",
"file": "rules\/RESPONSE-980-CORRELATION.conf\\\"",
"line": "73"
},
"hostname": "vm000003",
"transactionId": "AcAcAcAcAKH@AcAcAcAcAyAt"
}
}
你了解 CRS 規則集的運作方式,以及 CRS 規則集 3.0 支援異常評分系統(參見 Web 應用程式防火牆 Azure 應用程式閘道),你知道底層兩條規則中帶有 action: Blocked 屬性的規則是基於總異常分數的阻擋。 要注意的規則是前兩條。
第一個紀錄會被記錄,因為使用者使用了一個數字 IP 位址來導航到應用程式閘道,這種情況下你可以忽略它。
第二個條目(規則 942130)在細節中可見,因為它符合一個模式 (1=1),欄位名為 text1。 依照前述步驟排除等於 的text1。
尋找請求標題名稱
使用 Fiddler 來查找請求標頭名稱。 在以下截圖中,你可以看到這個 GET 請求的標頭,包括 Content-Type、 User-Agent 以及其他標頭。
你也可以使用Microsoft Edge或Google Chrome的開發者工具來查看請求與回應標頭。 欲了解更多資訊,請參閱 Record HAR 檔案。
尋找請求 cookie 名稱
如果要求包含 Cookie,請選取 [Cookie] 索引標籤,在 Fiddler 中加以檢視。
限制全域參數以消除誤判為真
關閉請求車身檢查
當你將 檢查請求主體 設為關閉時,WAF 就不會檢查你流量中的請求主體。 如果你確定請求實體對你的應用程式沒有惡意,這個設定很有用。
當你關閉這個選項時,只有請求實體會繞過檢查。 標頭和 Cookie 仍會被檢查,除非你透過排除清單功能排除個別 cookie。
關閉最大請求主體大小限制
當你停用最大請求主體限制時,WAF 可以處理大型請求主體,而不會因為超過大小限制而拒絕它們。 如果你經常有大型請求,這個設定很有用。
當你關閉此選項時,請求本體只會被檢查到最大請求本體檢查上限。 如果請求本文中超出最大檢查上限的部分含有惡意內容,WAF 將無法偵測到。
關閉最大檔案大小限制
當你關閉 WAF 的檔案大小限制後,可以上傳大型檔案,而 WAF 不會拒絕這些上傳。 允許上傳大型檔案,後端被淹沒的風險會增加。 如果你知道檔案上傳的最大容量,請設定檔案上傳的大小限制,稍微超過預期最大大小。 將檔案大小限制在應用程式的一般使用情境中,是防止攻擊的另一種方法。 然而,如果你的檔案上傳經常超過可強制執行的最大上傳大小限制,可能需要完全關閉檔案上傳大小限制以避免誤報。
備註
如果你知道你的應用程式不需要超過某個大小的檔案上傳,你可以透過設定限制來限制該大小。
警告
當你將新的管理規則集指派到 WAF 政策時,所有先前來自現有管理規則集的自訂,例如規則狀態、規則動作和規則層級排除,都會重置為新的管理規則集的預設值。 然而,任何自訂規則、政策設定及全域排除在新規則集指派期間仍不受影響。
防火牆指標(僅限 WAF v1)
對於 v1 網頁應用防火牆,入口網站現在提供以下指標:
- Web 應用程式防火牆 被阻擋請求數量 被阻擋的請求數量。
- Web 應用程式防火牆遭封鎖的規則計數 所有符合規則且請求遭封鎖的規則。
- Web 應用程式防火牆規則總分佈 評估期間所有相符的規則。
若要啟用計量,請選取入口網站中的 [計量] 索引標籤,然後選取三個計量之一。