Skip to content

[security] CSP level2  對於 inline 程式碼的 hash 與 nonce 處理方法

Published: at 05:10 AM

之前介紹過 CSP 1.0 時,有提到目前部分瀏覽器有支援 CSP 2.0

支援度如下圖:

在 CSP level2 新增了部分的 directives 及屬性(如 web worker 針對 外部資源載入的 child-src) ,更多關於 CSP level2 的詳細內容

這篇僅介紹 CSP level2 針對 inline 程式碼所規範的 hashnonce,讓 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 來解決這個問題.

  1. unsafe-inline 解法: 若設置 unsafe-inline 就變成允許所有的 inline 程式碼,這也意味著可以注入 inline 程式碼至頁面上面執行,可能會有 XSS 的疑慮,實務上就會變得較不安全. unsafe-inline 的寫法可以參考這篇

  2. 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

    <script> <script>”; ?> [/code]

    可以看到上面利用 php 將 alert('test1'); 先做 sha256 hash(記得要輸出 binary data,script 中的空白也都要列入計算),再將 hash 值做一次 base64 編碼.將以上結果輸出至 header CSP policy 中. 以上例子執行後會得到 alert('test1'); ,然而 alert('test2'); 則會被瀏覽器阻擋載

  3. nonce:用法與 hash 類似,但比較簡單,利用一段字串決定是否載入此 inline script 程式碼,來看看以下 php 的例子吧~

    [code] <?php $hash = hash(‘sha256’, rand(0, 1000)); header(“Content-Security-Policy: script-src ‘nonce-”.$hash.”’”); print ”

    CSP demo

    <script> <script>”; ?> [/code]

    上面這個例子,每次會產生不同的識別字串(簡單利用隨機值做 hash),讓惡意程式碼不能輕易仿造此 nonce 執行惡意程式碼.

以上介紹針對 hashnonce 這兩個在 CSP level2 所新增對於 inline script 的進階過濾,讓防止 XSS 之餘也能進一步過濾惡意 inline 程式碼.

ps. 若瀏覽器支援 CSP level2,當設置 hashnonce 時會忽略 unsafe-inline 的設置

參考資料:

https://imququ.com/post/content-security-policy-level-2.html