淺談 Content Security Policy (CSP)

Content Security Policy 是一個讓網站更安全的機制,透過設定 CSP HTTP Response Header,可以告知瀏覽器哪些資源(JavaScript、CSS 等等)可以使用,哪先不行,如果你的網站還沒有使用 CSP,會讓使用者暴露在高危險中,趕緊為你的網站加上 CSP 吧

CSP 主要可以分成 directivepolicydirective 代表資源,如 script-src 代表 JavaScript,img-src 代表圖片;而 policy 代表規則,如 'self' 代表可以從相同來源載入,'none' 代表禁止載入此資源

因此,透過正確設定 CSP,可以確保網頁只使用我們所允許的資源,任何不在規則中的都會直接禁止,藉此來提供網頁的安全性

你可以在 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#Directives 查看所有可以使用的 directive

本篇著重在 policy,但僅會介紹通用的規則,各 directive 可能會有獨自可以設定的 policy,可到 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy 查看

以下為各 policy 的介紹

'none'

不允許該資源從任何地方載入

'self'

允許該資源在相同來源下載入,比如網站網址是 https://blog.bepsvpt.me,那麼該資源可以從此來源載入,以下以 script-src 為範例:

  • ✓ – https://blog.bepsvpt.me/app.js
  • ✓ – https://blog.bepsvpt.me/assets/vendor.js
  • ✗ – http://blog.bepsvpt.me/app.js (schema 不同)
  • ✗ – https://blog.bepsvpt.me:777/app.js (port 不同)
  • ✗ – https://bepsvpt.me/app.js(域名不同)
  • ✗ – https://cdn.blog.bepsvpt.me/app.js(域名不同)

<host-source>

允許從該來源載入相關資源,可以設定多組,以下為範例

style-src blog.bepsvpt.me cdn.bepsvpt.me

  • ✓ – http://blog.bepsvpt.me/app.css
  • ✓ – https://blog.bepsvpt.me/app.css
  • ✓ – https://cdn.bepsvpt.me/assets/vendor.css
  • ✗ – https://blog.bepsvpt.me:777/app.css (port 不同)
  • ✗ – https://bepsvpt.me/app.css(域名不在允許來源內)

style-src https://blog.bepsvpt.me/assets/ https://cdn.bepsvpt.me/vendor.css

  • ✓ – https://blog.bepsvpt.me/assets/app.css
  • ✓ – https://cdn.bepsvpt.me/vendor.css
  • ✗ – https://blog.bepsvpt.me/app.css (路徑不匹配,必須在 assets 底下)
  • ✗ – http://blog.bepsvpt.me/assets/app.css (schema 不同)
  • ✗ – https://blog.bepsvpt.me:777/assets/app.css (port 不同)
  • ✗ – https://bepsvpt.me/assets/app.css(域名不同)
  • ✗ – https://cdn.bepsvpt.me/app.csshttps://cdn.bepsvpt.me 只能載入 /vendor.css

從此規則看到,<host-source> 可以極大程度確保資源載入來源,因此如有載入第三方資源,務必設置好此規則

<scheme-source>

允許指定 schema 之資源載入,如 img-src https: data: 代表只要網址是 https 協定的圖片,皆可載入,亦可載入 data:xxx inline 型的圖片

'unsafe-inline'不推薦

此為 JavaScript 和 CSS 專屬之 policy,允許 <script><style> 以及 <a onclick="callback">link</a> 等形式之 JavaScript 或 CSS

如果 script-srcstyle-src 未設置 'unsafe-inline',則下方程式碼瀏覽器皆不會執行

  • <script>alert('Hello, World!')</script>
  • <a onclick="alert('Hello, World!')" />
  • <style>h1, h2 { font-size: 5rem; }</style>
  • <a style="text-decoration: none;">link</a>

可以看到,如果設置了 'unsafe-inline',會大幅降低安全性,因此 script-src 不推薦設置 'unsafe-inline'

'unsafe-eval極不推薦

此為 JavaScript 專屬之 policy,允許使用 evalFunction,除非你知道在做什麼,否則極不推薦設置此 policy

以上為 policy 之介紹,如欲深入了解,可到 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy 查看

了解 CSP 後,你可以透過 https://www.cspisawesome.com/content_security_policies 此網站來產生 CSP,並可以在 https://github.com/github/secure_headers#similar-libraries 此 repo 查看各語言是否有現成可以使用的套件

如是使用 PHP 或 Laravel,歡迎使用我開發的套件 https://github.com/bepsvpt/secure-headers