Web Bot Auth 驗證
此技能為現有服務加入已簽章代理程式流量的驗證。困難的部分不在密碼學,而在於那些讓簽章看起來比實際更無意義的微小細節:未簽署的元件、重複使用的 nonce、會觸發 fetch 的標頭、與客戶端簽署不同的 URL 重建方式。這裡的參考程式碼與測試已將這些細節編碼。你的工作是將它們整合到使用者的技術棧中,且不削弱安全性。
規範狀態:目標為 draft-meunier-web-bot-auth-architecture-05(IETF 網際網路草案,非標準)並接受許多已部署代理程式仍會傳送的舊版 quoted-string Signature-Agent。告知使用者這是草案,可能會有變更。
工作流程
-
找到請求進入點。 辨識框架以及請求進入的位置(中介軟體、邊緣處理器、反向代理鉤子)。注意服務是否位於代理或 CDN 後方,因為這決定了如何重建 URL(請參閱
references/adapters.md)。 -
與使用者確定政策決策。 閱讀
references/policy-decisions.md,並詢問對話中尚未確定的任何事項:允許哪些運算子、是否要求請求綁定與 nonce、nonce 儲存方式,以及每種結果應採取的行動。不要默默選擇嚴格的設定:嚴格的預設值會拒絕大多數現今已部署的代理程式。也不要默默選擇寬鬆的設定:說明它們留下了哪些漏洞。 -
加入驗證器。
- Python:將
scripts/web_bot_auth.py不變地複製到專案中(保留其授權標頭),將cryptography加入相依性,並撰寫一個建構Request的小型轉接器。 - 其他語言:移植
scripts/web_bot_auth.py,使用該語言已建立的 Ed25519 函式庫(絕不自行實作)以及維護中的 RFC 8941 結構化欄位解析器(如果有的話)。移植尚未完成,直到每個assets/test-vectors.json中的案例都通過為止。
- Python:將
-
謹慎撰寫轉接器。 這是大多數整合出問題的地方。
Request必須攜帶發送時的方法、客戶端要求的絕對 URL、每個標頭出現的順序,以及解析或解壓縮前的原始 body 位元組。請參閱references/adapters.md中各框架的注意事項。 -
選擇 nonce 儲存。 僅限單一程序使用記憶體內儲存。任何具有兩個以上工作者或節點的系統都需要一個共享、強一致性的儲存。請參閱
references/nonce-stores.md。 -
將結果對應至行動。 除非使用者另有決定,否則使用下方的表格。
-
端到端測試整合。 透過真實框架(其測試客戶端)撰寫測試,使用
sign_request產生已簽署的請求:一個有效請求、一個竄改 body 的請求、一個重播請求,以及一個過期請求。如果已複製檔案,也執行scripts/test_web_bot_auth.py。 -
建議僅記錄的部署。 在強制執行任何動作之前,先記錄每個請求的
outcome、reason、operator、keyid、binds_request和replay_protected一段時間。
結果
| 結果 | 意義 | 預設動作 |
|---|---|---|
unsigned | 無 web-bot-auth 簽章 | 現有機器人處理 / 風險評分 |
verified | 有效簽章,允許清單中的運算子 | 以該代理程式的身份接受;仍套用個別使用者驗證與速率限制 |
signed_untrusted | 有效簽章,已知但不在允許清單中的運算子 | 視為未簽署,可選擇性地給予較低風險 |
unknown_operator | 格式正確,但無可用金鑰 | 視為未簽署;可選擇性地排程背景目錄擷取 |
invalid | 存在但錯誤 | 封鎖。合法的客戶端不會發送損毀的簽章 |
expired | 超出時間視窗 | 封鎖 |
replay | Nonce 已使用過 | 封鎖 |
Result.hostile 對最後三項為真。對於 verified,也檢查兩個旗標。如果 binds_request 為 false,則簽章不涵蓋方法、路徑、查詢與 body。如果 replay_protected 為 false,則表示沒有 nonce 或儲存不可用。合理的預設是對安全方法(GET、HEAD)接受任一旗標為 false 的已驗證請求。
容易違反的規則
這些規則存在是因為每個背後都有具體的攻擊。如果使用者的限制似乎需要違反其中一條,請解釋風險並讓他們決定。
- 絕對不要為不在允許清單中的運算子內聯擷取金鑰目錄。
Signature-Agent是攻擊者可控制的,因此擷取它指定的任何內容屬於 SSRF,並且會讓任何攻擊者癱瘓你的請求路徑。在背景工作中使用safe_fetch_directory擷取未知的運算子,或根本不擷取。 - 每當
Content-Digest被涵蓋時,請驗證它是否與 body 相符。 簽署標頭而無人檢查它是否與接收到的位元組相符是沒有意義的。 - 僅在簽章驗證成功後才記錄 nonce。 否則任何人都可以填滿儲存,或預先消耗合法代理程式的 nonce。
- 跨實例使用共享、原子的 nonce 儲存。 每個程序的快取會讓重播落在不同的工作者上。
- 以
created而非僅expires來限制新鮮度。 代理程式可能簽署具有長效期的簽章;無論如何,Policy.max_age會保持重播視窗與 nonce 快取較小。 - 重建客戶端實際請求的 URL。 在代理後方,僅使用來自你信任的代理的轉發協定與主機。如果出錯,有效簽章將無法驗證,或偽造的
Host標頭將被信任。 - 已驗證的簽章識別運算子,而非使用者。 在其後保留正常的驗證、個別使用者的授權與速率限制。絕對不要讓簽章代表使用者對敏感動作的同意。
- 不要對已驗證的代理程式套用人類行為檢查。 它們本質上就是自動化。
檔案
scripts/web_bot_auth.py:驗證器、金鑰解析器、nonce 儲存與sign_request。單一檔案;僅依賴cryptography。scripts/test_web_bot_auth.py:攻擊案例測試加上 RFC 9421 附錄 B.2.6 的符合性向量。從scripts/目錄使用python -m unittest -v test_web_bot_auth執行。scripts/generate_vectors.py:重新產生assets/test-vectors.json。assets/test-vectors.json:適用於移植的語言中立向量(僅測試金鑰)。references/policy-decisions.md:需要與使用者一起做出的選擇及其權衡。請在步驟 2 中閱讀。references/adapters.md:如何在常見框架及代理後方正確建構Request。請在步驟 4 中閱讀。references/nonce-stores.md:哪些儲存是安全的以及如何調整其大小。請在步驟 5 中閱讀。