繁體中文

開發者工具 · URL 編碼器和解碼器

雙 URL 編碼:%2520 如何發生以及如何偵測和撤銷它

· 工作原理

url 編碼 JavaScript 開發人員工作流程 偵錯

URL 參數顯示 %2520 逐漸解碼為 %20,然後解碼為空格
原始 ToolAcre 向量圖

%2520 表示空格被編碼兩次。這篇文章解釋了導致它的管道錯誤、如何識別簽名以及多少次解碼是安全的。

雙 URL 編碼:當 %2520 表示一個空格經過兩個編碼器

以「my%20file.pdf」而不是「my file.pdf」形式到達的檔案名稱表示雙重編碼:空格被編碼為 %20,然後百分號本身被編碼為 %25,在最終 URL 中產生 %2520。系統的每一層(例如客戶端程式碼、Web 框架或反向代理)可能會編碼一次。當兩個單獨的層編碼時,單一字元會被破壞。

雙編碼表面最常出現在複雜的重定向鍊和模板系統。開發人員可能會在框架內產生編碼的 URL,該框架本身預設對所有輸出進行編碼。反向代理或內容交付網路可能會對已從後端系統編碼到達的 URL 進行重新編碼。包含已編碼值的參數在嵌套到另一個 URL 結構之前會再次編碼。

為什麼 %25 是關鍵 - 百分號本身被編碼,因此 %20 變成 %2520 並 %C3%A9 變成 %25C3%25A9

雙重編碼的明顯標誌是 %25 ,它出現在您通常期望在 URL 或資料中看到單一百分號的位置。在正常編碼的 URL 中,除非發送文字“%25”,否則您永遠不會看到 %25。如果編碼為 %20 的空格再次編碼,它將變成 %2520。

像 é 這樣的重音字元通常編碼為 %C3%A9,當由兩個不同的系統按順序編碼兩次時,變為 %25C3%25A9。在資料流經多個服務的生產環境中,學習識別 URL 列、日誌和錯誤訊息中的 %25 模式可以節省無數時間令人沮喪的偵錯工作。

引入雙重編碼的地方 - 客戶端程式碼加框架、重定向、代理和模板助手

雙重編碼會破壞可讀性以及伺服器端系統正確解析 URL 的能力。正確編碼後,名為「my file.pdf」的檔案將變為「my%20file.pdf」。如果編碼的字串被重新編碼(可能透過某種形式),它將變成「my%2520file.pdf」。

當伺服器收到此訊息並對其進行解碼一次時,它將「my%20file.pdf」視為文字檔案名,而不是將其識別為「my file.pdf」。任何期望僅接收單一解碼通道的應用程式都將收到損壞的結果。更糟糕的是,開發人員解碼兩次以修復僅編碼一次的值的問題實際上會透過額外的解碼過程破壞合法資料。

工作範例:一次解碼一個雙重編碼的 URL — 每一次顯示什麼內容以及何時停止

客戶端 JavaScript 程式碼和伺服器端框架預設值是生產系統中意外雙重編碼的最常見來源。 JavaScript 應用程式可能會對某個值使用encodeURIComponent,然後將其直接傳遞到預設對所有字串輸出進行編碼的框架,從而對百分號進行第二次編碼。用於清理 URL 的反向代理層可能會對已從後端應用程式預先編碼的參數進行重新編碼。

透過連接使用者提供的輸入與框架輔助函數建構的重定向 URL 可以同時在兩個步驟中進行編碼。工作範例:使用者透過 HTML 表單提交“test&value”,瀏覽器將其編碼為“test%26value”。該框架看到文字百分比文字並對其進行編碼,產生“test%2526value”。一次解碼給出“test%26value”,仍然是錯誤的。

當故意使用雙重編碼時 — 一個 URL 包含在另一個 URL 的查詢參數中

故意雙重編碼在一個特定情況下是有效的:當一個 URL 必須在另一個 URL 的查詢參數內傳輸時。 OAuth 流和登入返回連結有時需要將一個完整的 URL 嵌套在另一個 URL 中。內部 URL 必須先進行完全百分比編碼,然後必須將整個編碼字串再次編碼為外部 URL 的參數值。

這種雙重編碼是經過深思熟慮的,並在這些情況下是絕對必要的。外部參數解析器解碼一次,產生仍然編碼的內部 URL。然後內部系統再次解碼,恢復原始 URL。關鍵是理解意圖並在程式碼註釋中清楚地記錄下來,以供未來的維護人員使用。

常見錯誤 - 解碼直到沒有任何變化,這會破壞合法包含 %25 的值

典型且危险的錯誤是重複解碼,直到没有任何變化,這將破坏實際資料中合法包含百分号的值。像“discount%2525”這樣的參數(表示編碼為參數值的文字“%25”,然後再次編碼以進行傳輸)在設計上是完全正確的。解碼一次會產生“discount%25”,這仍然是正确的。第二次解碼會得到“discount%”,這是錯誤的並會丢失信息。

開發人員可能會认為“%25”是一個錯誤並重複解碼,丢失百分号。相反,解碼次數與您的架構要求的次數完全相同:一次用于参數,两次嵌套。計算層數以了解正確的解碼操作。

這不包括什么 - HTML 實體編碼分層在 URL 之上,由 HTML 實體轉义器處理

常見錯誤包括使用encodeURIComponent 對整個 URL 進行編碼,然後期望斜槓和冒號充當結構分隔符,但在編碼後卻不能這樣做。另一個常見錯誤是混合不同的編碼標準:某些代碼使用 RFC 3986 的百分比編碼,而其他代碼使用帶有代表空格的加號的形式編碼。像“my+file”這樣的值確實變得不明確——它可能意味著“我的檔案”,也可能意味著帶有加號的文字文字“my+file”。

如果百分比編碼先觸及“my+file”,則它變成“my%2Bfile”。如果接下來進行形式解碼,期望加號作為空格,那麼它仍然是錯誤的。跨層的一致性至關重要。每個系統必須使用相同的編碼標准,或者必須明确記錄每一層。

重點:每層只編碼一次 — URL 編碼器和解碼器如何讓您一次解碼一次並查看每個中間結果

一旦成功識別生產系統中發生的雙重編碼,修復完全取決於管道中重複發生的位置。如果客戶端代碼和框架都在編碼,请從其中之一完全刪除編碼。如果参數经過多個後端服務,请跟踪每個服務的完整路径,並找到哪個服務在不應该編碼的情况下进行編碼。

透過將範例資料傳遞到完整的端對端管道來徹底測試修復,並驗證資料完全未變更地到達目的地。清楚記錄每個邊界處的編碼假設:「此端點傳回百分比編碼的參數」或「此中間件需要原始 UTF-8 並對其應用編碼」。包括未來開發人員在該檔案中預期的解碼次數。