之前介紹過 CSP 1.0 時,有提到目前部分瀏覽器有支援 CSP 2.0
支援度如下圖:
在 CSP level2 新增了部分的 directives 及屬性(如 web worker 針對 外部資源載入的 child-src) ,更多關於 CSP level2 的詳細內容.
這篇僅介紹 CSP level2 針對 inline 程式碼所規範的 hash
與 nonce
,讓 inline 程式碼能較安全且彈性的執行.
我們先來看一個普通的 CSP demo 頁面
header(“Content-Security-Policy: script-src *;”);
print “
CSP demo
<script src=‘https://code.jquery.com/jquery-3.2.1.slim.min.js’>
";
實際執行的畫面:
可以看到設置了 CSP script-src *
,預設還是會擋掉 inline script ,在錯誤的訊息中,透露出可以設定 unsafe-inline, hash 及 nonce 來解決這個問題.
-
unsafe-inline 解法: 若設置 unsafe-inline 就變成允許所有的 inline 程式碼,這也意味著可以注入 inline 程式碼至頁面上面執行,可能會有 XSS 的疑慮,實務上就會變得較不安全. unsafe-inline 的寫法可以參考這篇.
-
hash:利用一串產生的 hash 值,類似簽證.來指定符合此 hash 值的外部資源才可以載入. 支援
SHA-256
SHA-384
SHA-512
演算法所產生的值,經過base64
編碼後結果.
來看看實際使用 php 的例子吧~[code] <?php $script = “alert(‘test1’) ;”; $hash = hash(‘sha256’, $script, true); $hash = base64_encode($hash); header(“Content-Security-Policy: script-src ‘sha256-”.$hash.”’”); print ”
CSP demo
”; ?> [/code]
可以看到上面利用 php 將
alert('test1');
先做 sha256 hash(記得要輸出 binary data,script 中的空白也都要列入計算),再將 hash 值做一次 base64 編碼.將以上結果輸出至 header CSP policy 中. 以上例子執行後會得到alert('test1');
,然而alert('test2');
則會被瀏覽器阻擋載 -
nonce:用法與 hash 類似,但比較簡單,利用一段字串決定是否載入此 inline script 程式碼,來看看以下 php 的例子吧~
[code] <?php $hash = hash(‘sha256’, rand(0, 1000)); header(“Content-Security-Policy: script-src ‘nonce-”.$hash.”’”); print ”
CSP demo
”; ?> [/code]
上面這個例子,每次會產生不同的識別字串(簡單利用隨機值做 hash),讓惡意程式碼不能輕易仿造此
nonce
執行惡意程式碼.
以上介紹針對 hash
與 nonce
這兩個在 CSP level2 所新增對於 inline script 的進階過濾,讓防止 XSS 之餘也能進一步過濾惡意 inline 程式碼.
ps. 若瀏覽器支援 CSP level2,當設置 hash
或 nonce
時會忽略 unsafe-inline
的設置
參考資料:
https://imququ.com/post/content-security-policy-level-2.html