子資源完整性
子資源完整性 (SRI) 是一項安全功能,它允許瀏覽器驗證它們獲取的資源(例如,從 CDN)在交付過程中未被意外篡改。它的工作原理是允許您提供一個加密雜湊,獲取的資源必須與之匹配。
注意: 對於從與嵌入它的文件不同源提供的資源的子資源完整性驗證,瀏覽器還會使用 跨域資源共享 (CORS) 來額外檢查該資源,以確保提供該資源的源允許它與請求的源共享。
子資源完整性如何提供幫助
網站有時會選擇依賴第三方(例如 內容分發網路 (CDN))來託管其部分資源,而不是完全自行託管所有資源。例如,從 https://example.com 提供的文件可能包含來自另一個位置的資源。
<script src="https://not-example.com/script.js"></script>
這存在風險,即如果攻擊者控制了第三方主機,攻擊者就可以在其檔案中注入任意惡意內容(或完全替換檔案),從而也可以潛在地攻擊從它那裡獲取檔案的網站。
子資源完整性使您能夠透過確保您的 Web 應用程式或 Web 文件獲取的檔案在沒有攻擊者注入任何額外內容的情況下交付,並且這些檔案沒有任何其他更改,來減輕此類攻擊的某些風險。
使用子資源完整性
您透過在 <script> 元素或帶有 rel="stylesheet"、rel="preload" 或 rel="modulepreload" 的 <link> 元素的 integrity 屬性值中,指定一個 base64 編碼的加密雜湊,來使用子資源完整性功能,告訴瀏覽器獲取該資源(檔案)。
integrity 值至少包含一個字串,每個字串都包含一個指示特定雜湊演算法的字首(目前允許的字首是 sha256、sha384 和 sha512),後跟一個連字元,最後是實際的 base64 編碼雜湊。
注意: integrity 值可能包含多個由空格分隔的雜湊。如果資源匹配其中一個雜湊,它就會被載入。
帶有 base64 編碼 sha384 雜湊的 integrity 字串示例
sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC
因此,oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC 是“雜湊”部分,字首 sha384 表明這是一個 sha384 雜湊。
注意: 嚴格來說,integrity 值的“雜湊”部分是應用特定雜湊函式到某個輸入(例如,指令碼或樣式表文件)形成的**加密摘要**。但通常使用“雜湊”的簡寫來表示加密摘要,因此本文件中也這樣使用。
生成 SRI 雜湊的工具
SRI 雜湊生成器
SRI Hash Generator 是一個線上工具,可用於生成 SRI 雜湊。
使用 OpenSSL
您可以使用 OpenSSL 從命令列生成 SRI 雜湊,命令如下:
cat FILENAME.js | openssl dgst -sha384 -binary | openssl base64 -A
在 Windows 環境中,您可以使用以下程式碼建立一個生成 SRI 雜湊的工具:
@echo off
set bits=384
openssl dgst -sha%bits% -binary %1% | openssl base64 -A > tmp
set /p a= < tmp
del tmp
echo sha%bits%-%a%
pause
使用該程式碼:
- 將該程式碼儲存在 Windows 的 SendTo 資料夾中,檔名為
sri-hash.bat(例如,C:\Users\USER\AppData\Roaming\Microsoft\Windows\SendTo)。 - 在檔案資源管理器中右鍵單擊一個檔案,選擇“傳送到…”(Send to…),然後選擇
sri-hash。您將在命令框中看到完整性值。 - 選中完整性值,然後右鍵單擊進行復制到剪貼簿。
- 按任意鍵關閉命令框。
注意: 如果您的系統未安裝 OpenSSL,請訪問 OpenSSL 專案網站瞭解下載和安裝資訊。OpenSSL 專案本身不託管 OpenSSL 的二進位制分發版,但維護著一個非正式的第三方分發版列表:https://github.com/openssl/openssl/wiki/Binaries。
使用 shasum
您可以使用 shasum 從命令列生成 SRI 雜湊,命令如下:
shasum -b -a 384 FILENAME.js | awk '{ print $1 }' | xxd -r -p | base64
- 透過管道傳遞
xxd的步驟會將shasum的十六進位制輸出轉換為二進位制。 - 透過管道傳遞
awk的步驟是必需的,因為shasum會將雜湊後的檔名包含在其輸出中傳遞給xxd。如果檔名碰巧包含有效的十六進位制字元,這可能會導致災難性的後果——因為xxd也會對其進行解碼並傳遞給base64。
跨域資源共享與子資源完整性
對於從與嵌入它的文件不同源提供的資源的子資源完整性驗證,瀏覽器還會使用 跨域資源共享 (CORS) 來額外檢查該資源,以確保提供該資源的源允許它與請求的源共享。因此,該資源必須以允許與請求的源共享的 Access-Control-Allow-Origin 頭部提供;例如:
Access-Control-Allow-Origin: *
瀏覽器如何處理子資源完整性
瀏覽器透過執行以下操作來處理 SRI:
-
當瀏覽器遇到帶有
integrity屬性的<script>或<link>元素時,在執行指令碼或應用<link>元素指定的任何樣式表之前,瀏覽器必須首先將指令碼或樣式表與integrity值中提供的預期雜湊進行比較。對於從與嵌入它的文件不同源提供的資源的子資源完整性驗證,瀏覽器還會使用 跨域資源共享 (CORS) 來額外檢查該資源,以確保提供該資源的源允許它與請求的源共享。
-
如果指令碼或樣式表與其關聯的
integrity值不匹配,瀏覽器必須拒絕執行指令碼或應用樣式表,而應返回一個網路錯誤,表明獲取該指令碼或樣式表失敗。
完整性策略
Integrity-Policy 和 Integrity-Policy-Report-Only HTTP 頭部允許文件強制執行有關載入的指令碼和樣式表子資源的完整性元資料要求的策略。
當指定 Integrity-Policy 頭部時,瀏覽器會阻止發出 no-cors 模式或沒有 integrity 屬性的請求,並且如果指定了有效的報告端點,還會報告違規行為。當指定 Integrity-Policy-Report-Only 頭部時,瀏覽器允許違規策略的請求,但會將違規行為報告給報告端點(如果指定了有效的報告端點)。
開發者通常會在其完整性策略的實現過程中,首先使用 Integrity-Policy-Report-Only 作為第一步部署,以確保其文件中載入的所有指令碼和樣式表都具有相應的完整性元資料。一旦他們看到沒有收到違規報告,他們就知道可以使用 Integrity-Policy 頭部啟用阻止功能,而不會冒使用者介面中斷的風險。
頭值被定義為具有以下鍵的結構化欄位字典
blocked-destinations-
定義了一組要阻止的 請求目標。唯一允許的值是
script和style。 sources可選-
定義了一組完整性源。預設且目前唯一支援的值是
inline。因此,將sources=(inline)新增到頭部與省略sources的效果類似。 endpoints可選-
定義了一組 報告端點。報告端點需要在
Reporting-Endpoints頭部中定義。
在完整性策略阻止請求的情況下,會建立一個型別為 integrity-violation 的 Reporting API 違規報告,其主體型別為 IntegrityViolationReportBody,其中包含有關文件 URL 和被阻止資源等資訊。
典型的報告可能如下所示:
{
"type": "integrity-violation",
"url": "https://example.com",
"body": {
"documentURL": "https://example.com",
"blockedURL": "https://example.com/main.js",
"destination": "script",
"reportOnly": false
}
}
示例
在以下示例中,假設 oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC 已被確認為特定指令碼 example-framework.js 的預期 SHA-384 雜湊(摘要),並且該指令碼在 https://example.com/example-framework.js 託管有副本。
使用 <script> 元素的子資源完整性
您可以使用以下 <script> 元素告知瀏覽器,在執行 https://example.com/example-framework.js 指令碼之前,瀏覽器必須先將指令碼與預期雜湊進行比較,並驗證匹配。
<script
src="https://example.com/example-framework.js"
crossorigin="anonymous"></script>
注意:有關 crossorigin 屬性用途的更多詳細資訊,請參閱 CORS 設定屬性。
使用 Integrity-Policy 頭部執行完整性
您可以將 Integrity-Policy 頭部新增到您的文件中,以確保它載入的外部資源(在此例中是指令碼)具有完整性(並且不是以 no-cors 模式載入)
Integrity-Policy: blocked-destinations=(script), endpoints=(integrity-endpoint, some-other-integrity-endpoint)
如果您不確定所有外部指令碼是否都具有完整性元資料,您可以啟用該功能的報告模式版本,並開始接收違規報告。您可以使用 Integrity-Policy-Report-Only 頭部來做到這一點。
Integrity-Policy-Report-Only: blocked-destinations=(script), endpoints=(integrity-endpoint, some-other-integrity-endpoint)
規範
| 規範 |
|---|
| HTML # attr-link-integrity |
| HTML # attr-script-integrity |
| 子資源完整性 # the-integrity-attribute |
瀏覽器相容性
html.elements.link.integrity
載入中…
html.elements.script.integrity
載入中…