繁體中文

開發者工具 · SHA 雜湊計算器

子資源完整性:瀏覽器如何使用 SHA-384 檢查腳本

· 背景

sha-256 base64 瀏覽器 API 安全

顯示演演算法前綴、連字符和 Base64 摘要的完整性屬性
原始 ToolAcre 向量圖

完整性屬性允許瀏覽器拒絕位元組已變更的 CDN 腳本。這篇文章解釋了屬性的格式、為什麼 base64 中的 SHA-384 是常見的選擇,以及 SRI 無法防範的內容。

可以為任何事物提供服務的 CDN — SRI 的設計目的是為了應對供應鏈風險

網頁上的腳本標記可以攜帶完整性屬性:`<script src="https://cdn.example.com/lib.js" integrity="sha384-..."></script>`。完整性值是腳本位元組的加密摘要。當瀏覽器下載腳本時,它會計算接收到的位元組的摘要並與完整性屬性進行比較。如果它們匹配,則載入腳本。如果它們不匹配,瀏覽器將拒絕加載它並在控制台中報告失敗。這可以防止受損的 CDN 提供修改後的程式碼,或防止網路攻擊者攔截和更改回應。

子資源完整性 (SRI) 是適用於腳本和樣式表的 W3C 規格。這是瀏覽器可以對跨來源資源的內容做出的唯一加密保證:位元組必須與摘要匹配,否則資源將被拒絕。這並不能證明誰創建了該資源,只是證明自計算摘要以來該資源沒有改變。對於從信譽良好的 CDN 透過 HTTPS 提供的資源,摘要提供了一種保護措施,防止 CDN 受到損害或專門向您提供過時的快取內容。

完整性屬性 — 演演算法前綴、連字符、base64 摘要和對多個雜湊的支持

完整性屬性具有特定的格式:演算法名稱、連字符、base64 格式的摘要。範例:`integrity="sha384-JZDdQnrrAMe+sxxpn47in+PwhkxrCrt4SNvt+xWqV3zPJUkeFF0Qq/wNtuvNqPP5"`。演算法名稱可以是 SHA-256、SHA-384 或 SHA-512。 Base64是編碼,不是十六進位;這是 SRI 規範有意選擇的。 Base64 比十六進位更緊湊(對於相同的摘要,大約短 33%),這在嵌入 HTML 屬性時很重要。連字符將演算法名稱與摘要分開。可以列出多個完整性值,以空格分隔:如果其中任何一個匹配,則資源被接受。

為什麼選擇 SHA-384? SRI 規範允許 SHA-256、SHA-384 和 SHA-512。 SHA-384 成為社區預設值,因為它提供了大小/安全性平衡。 SHA-256 較小(32 位元組,base64 中的 44 個字元),但 SHA-384 更寬(48 位元組,base64 中的 64 個字元),並且與 SHA-256 相比,並沒有顯著增加屬性大小。 SHA-512 可用,但很少使用,因為其較大的摘要對於此用例似乎沒有必要。 SHA-384 的選擇是歷史性和實用性的,而不是高級安全屬性的反映(所有這三種方法在加密方面都具有很強的安全性)。

SHA-384並產生所需的base64材料;社群偏好不是從該工具推斷出來的

SRI中的Base64編碼是標準base64,而不是base64url。標准 base64 使用 + 和 / 字符,它们在没有百分比編碼的 HTML 属性中有效,尽管它们在 URL 和表單資料中具有特殊含义。 SRI 格式是為 HTML 屬性而不是 URL 設計的,因此標準的 base64 是合適的。如果您手動構建完整性值,則計算 SHA-384 摘要(字節序列),然後將這些字節編碼為標准 base64,然後在前面添加 `sha384-` 並粘贴到完整性属性中。

瀏覽器反向執行相同的步驟:從完整性屬性中提取 base64,解碼為位元組以恢復摘要,計算下載的腳本位元組的 SHA-384 並比較兩個摘要值。它們必須完全匹配;摘要中的單位數差異會導致拒絕。不存在模糊匹配或部分信用:完整性是二元的。

跨來源 SRI 行為需要除此雜湊計算器之外的瀏覽器文件

SRI 要求跨域回應使用 CORS。如果您從不同的來源載入腳本,伺服器必須使用 `Access-Control-Allow-Origin: *` 或包含您的特定來源標頭來回應。如果沒有 CORS 標頭,瀏覽器就無法檢查 SRI,因為如果沒有 CORS,瀏覽器就無法確認回應正文是否與伺服器打算傳送的內容相符。 CORS 標頭是伺服器的聲明,表示此回應可以安全檢查; SRI 用於檢查位元組是否正確。它們共同構成了供應鏈承諾:伺服器允許您驗證內容,您也可以這樣做。

如果跨來源腳本缺少 CORS 標頭並具有完整性屬性,則瀏覽器將下載它(如果網站的 CSP 允許來自該來源的腳本),但不會驗證完整性。該腳本將被加載,就好像完整性屬性不存在一樣。這並不是 SRI 的失敗;而是 SRI 的失敗。這是一個安全邊界:您無法驗證您無法讀取的回應。

不符時會發生什麼 - 瀏覽器阻止資源並在控制台中報告

當瀏覽器偵測到完整性不符時,它會拒絕執行腳本並在瀏覽器控制台中記錄一條訊息。該訊息通常會命名 URL、預期哈希值和計算出的哈希值。失敗是原子性的:資源要么按原樣加載,要么被完全拒絕。沒有部分載入或回退。如果網站依賴該腳本並被拒絕,則該網站可能會崩潰。這是故意的:提供錯誤的程式碼比不提供程式碼更糟糕,而且無聲的故障使攻擊無限期地持續下去。

測試 SRI 設定非常簡單:開啟瀏覽器控制台,載入頁面並尋找有關完整性不符的訊息。如果您發現不匹配,請將控制台中顯示的計算出的雜湊值與完整性屬性中的雜湊值進行比較。如果它們不匹配,請重新計算:腳本可能已更新,您需要新的摘要。

工作範例 — 計算腳本摘要並將其格式化為完整性值,包括 base64 步驟

手動計算 SRI 摘要只需要腳本位元組和雜湊工具。下載脚本,將其粘贴到 ToolAcre SHA 哈希計算器中,選擇 SHA-384,複制 Base64 輸出(不是十六进制),在前面加上 `sha384-` 並粘贴到完整性属性中。如果腳本很大,請使用curl或wget將其保存到檔案然後讀取檔案比貼上更快。對于內聯脚本(在 HTML 中的 `<script>` 標記中而不是來自 URL),SRI 不适用;根據定义,內聯脚本始終是可信的。 SRI 用於外部資源。

一個有效的範例:假設您想要使用 SRI 從 CDN 載入 jQuery。找到脚本 URL,下載它(或使用curl 獲取它),將字節粘贴到計算器中或在命令行上使用 `sha384sum`,獲取 SHA-384 摘要為 base64,並將格式設置為 `sha384-[base64-digest]`。貼上到腳本標記的完整性屬性中。載入頁面並驗證沒有出現控制台錯誤。

這不包括什麼 - 有意更改的腳本,以及像 ToolAcre 這樣根本不加載外部腳本的網站,因此沒有什麼可固定的

SRI 不能防禦所有供應鏈攻擊。它可以防止在計算摘要後位元組發生更改,但不能防止從受損代碼開始計算摘要。如果在計算摘要之前 CDN 遭到破壞,SRI 將無法提供協助。摘要的可信度取決於計算它的來源。為了獲得最大程度的保證,請從原始來源(例如,庫的 GitHub 版本)計算摘要,並在從 CDN 載入時使用這些摘要。摘要在發布過程中成為維護者的承諾。

SRI 也無法在您計算摘要時防止網路受損,或開發機器受損。它僅防止在建立摘要和瀏覽器載入腳本之間對腳本進行更改。為了持續保證,除了 SRI 之外,某些部署還使用版本簽名:版本由維護者的金鑰進行簽名,您驗證簽名,根據已驗證的位元組計算摘要並在 SRI 中使用它。

本文並未從雜湊來源斷言 ToolAcre 的站點範圍外部腳本庫存

ToolAcre SHA 雜湊計算器直接以標準 base64 發出摘要(作為 `toBase64()` 函數的 `base64` 輸出)。若要轉換為 SRI 格式,請在前面新增演算法名稱和連字號:`sha256-`、`sha384-` 或 `sha512-`。計算器不會自動套用該前綴,因為雜湊出現在許多上下文(git、Docker、npm、URL)中,其中演算法名稱是單獨的或編碼不同的。邊界很明確:計算器會對您貼上的 UTF-8 文字進行雜湊處理,而不是對檔案或二進位金鑰進行雜湊處理。它輸出十六進制和base64。您可以根據您的上下文選擇使用哪一個。對於 SRI,規格要求使用 base64。對於 git 和其他工具來說,十六進制是常規的。對於 npm 和 Go,使用 base64。編碼選擇由您決定;摘要位元組是相同的。

SRI 仍然是瀏覽器可以在沒有集中權限的情況下在客戶端執行的少數加密檢查之一。使用 ToolAcre 的 SHA 計算器等值得信賴的工具進行計算,並根據載入的資源驗證它們是強化網站抵禦某些供應鏈攻擊的一種可行方法。保護效果取決於摘要;每次更新外部資源後重新計算,並測試瀏覽器載入腳本而不拒絕它。