內容安全策略(CSP),防禦 XSS 攻擊的好助手
| 2016-10-10 14:58
很久之前,我的個人網站被攻擊了。我不知道它是如何發生的,但它確實發生了。幸運的是,攻擊帶來的破壞是很小的:一小段 JavaScript 被注入到了某些頁面的底部。我更新了 FTP 和其它的口令,清理了一些檔案,事情就這樣結束了。
有一點使我很惱火:在當時,還沒有一種簡便的方案能夠使我知道那裡有問題,更重要的是能夠保護網站的訪客不被這段惱人的程式碼所擾。
現在有一種方案出現了,這種技術在上述兩方面都十分的成功。它就是內容安全策略(CSP)。
什麼是 CSP?
其核心思想十分簡單:網站透過傳送一個 CSP 頭部,來告訴瀏覽器什麼是被授權執行的與什麼是需要被禁止的。
這裡有一個 PHP 的例子:
<?php
header("Content-Security-Policy: <your directives>");
?>
一些指令
你可以定義一些全域性規則或者定義一些涉及某一類資源的規則:
default-src 'self' ;
# self = 同埠,同域名,同協議 => 允許
基礎引數是 default-src
:如果沒有為某一類資源設定指令規則,那麼瀏覽器就會使用這個預設引數值。
script-src 'self' www.google-analytics.com ;
# 來自這些域名的 JS 檔案 => 允許
在這個例子中,我們已經授權了 www.google-analytics.com 這個域名來源的 JavaScript 檔案使用到我們的網站上。我們也新增了 'self'
這個關鍵詞;如果我們透過 script-src
來重新設定其它的規則指令,它將會覆蓋 default-src
規則。
如果沒有指明協議(scheme)或埠,它就會強制選擇與當前頁面相同的協議或埠。這樣做防止了混合內容(LCTT 譯註:混合內容指 HTTPS 頁面中也有非 HTTPS 資源,可參見: https://developer.mozilla.org/zh-CN/docs/Security/MixedContent )。如果頁面是 https://example.com,那麼你將無法載入 http://www.google-analytics.com/file.js 因為它已經被禁止了(協議不匹配)。然而,有一個例外就是協議的提升是被允許的。如果 http://example.com 嘗試載入 https://www.google-analytics.com/file.js,接著協議或埠允許被更改以便協議的提升。
style-src 'self' data: ;
# Data-Uri 嵌入 CSS => 允許
在這個例子中,關鍵詞 data:
授權了在 CSS 檔案中 data 內嵌內容。
在 CSP 1 規範下,你也可以設定如下規則:
img-src
有效的圖片來源connect-src
應用於 XMLHttpRequest(AJAX),WebSocket 或 EventSourcefont-src
有效的字型來源object-src
有效的外掛來源(例如,<object>
,<embed>
,<applet>
)media-src
有效的<audio>
和<video>
來源
CSP 2 規範包含了如下規則:
child-src
有效的 web workers 和 元素來源,如<frame>
和<iframe>
(這個指令用來替代 CSP 1 中廢棄了的frame-src
指令)form-action
可以作為 HTML<form>
的 action 的有效來源frame-ancestors
使用<frame>
,<iframe>
,<object>
,<embed>
或<applet>
內嵌資源的有效來源upgrade-insecure-requests
命令使用者代理來重寫 URL 協議,將 HTTP 改到 HTTPS (為一些需要重寫大量陳舊 URL 的網站提供了方便)。
為了更好的向後相容一些廢棄的屬性,你可以簡單的複製當前指令的內容同時為那個廢棄的指令建立一個相同的副本。例如,你可以複製 child-src
的內容同時在 frame-src
中新增一份相同的副本。
CSP 2 允許你新增路徑到白名單中(CSP 1 只允許域名被新增到白名單中)。因此,相較於將整個 www.foo.com 域新增到白名單,你可以透過新增 www.foo.com/some/folder 這樣的路徑到白名單中來作更多的限制。這個需要瀏覽器中 CSP 2 的支援,但它很明顯更安全。
一個例子
我為 Web 2015 巴黎大會上我的演講 “CSP in Action”製作了一個簡單的例子。
在沒有 CSP 的情況下,頁面展示如下圖所示:
不是十分優美。要是我們啟用瞭如下的 CSP 指令又會怎樣呢?
<?php
header("Content-Security-Policy:
default-src 'self' ;
script-src 'self' www.google-analytics.com stats.g.doubleclick.net ;
style-src 'self' data: ;
img-src 'self' www.google-analytics.com stats.g.doubleclick.net data: ;
frame-src 'self' ;");
?>
瀏覽器將會作什麼呢?它會(非常嚴格的)在 CSP 基礎規則之下應用這些指令,這意味著任何沒有在 CSP 指令中被授權允許的都將會被禁止(“blocked” 指的是不被執行、不被顯示並且不被使用在網站中)。
在 CSP 的預設設定中,內聯指令碼和樣式是不被授權的,意味著每一個 <script>
,onclick
事件屬性或 style
屬性都將會被禁止。你可以使用 style-src 'unsafe-inline' ;
指令來授權使用內聯 CSS。
在一個支援 CSP 的現代瀏覽器中,上述示例看起來如下圖:
發生了什麼?瀏覽器應用了指令並且拒絕了所有沒有被授權的內容。它在瀏覽器除錯終端中傳送了這些通知:
如果你依然不確定 CSP 的價值,請看一下 Aaron Gustafson 文章 “More Proof We Don't Control Our Web Pages”。
當然,你可以使用比我們在示例中提供的更嚴格的指令:
- 設定
default-src
為 'none' - 為每條規則指定你的設定
- 為請求的檔案指定它的絕對路徑
- 等
更多關於 CSP 的資訊
支援
CSP 不是一個需要複雜的配置才能正常工作的每日構建特性。CSP 1 和 2 是候選推薦標準!瀏覽器可以非常完美的支援 CSP 1。
CSP 2 是較新的規範,因此對它的支援會少那麼一點。
現在 CSP 3 還是一個早期草案,因此還沒有被支援,但是你依然可以使用 CSP 1 和 2 來做一些重大的事。
其他需要考慮的因素
CSP 被設計用來降低跨站指令碼攻擊(XSS)的風險,這就是不建議開啟內聯指令碼和 script-src
指令的原因。Firefox 對這個問題做了很好的說明:在瀏覽器中,敲擊 Shift + F2
並且鍵入 security csp
,它就會向你展示指令和對應的建議。這裡有一個在 Twitter 網站中應用的例子:
如果你確實需要使用內聯指令碼和樣式的話,另一種可能就是生成一份雜湊值。例如,我們假定你需要使用如下的內聯指令碼:
<script>alert('Hello, world.');</script>
你應該在 script-src
指令中新增 sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng=
作為有效來源。這個雜湊值用下面的 PHP 指令碼執行獲得的結果:
<?php
echo base64_encode(hash('sha256', "alert('Hello, world.');", true));
?>
我在前文中說過 CSP 被設計用來降低 XSS 風險,我還得加上“……與降低未經請求內容的風險。”伴隨著 CSP 的使用,你必須知道你內容的來源是哪裡與它們在你的前端都作了些什麼(內聯樣式,等)。CSP 同時可以幫助你讓貢獻者、開發人員和其他人員來遵循你內容來源的規則!
現在你的問題就只是,“不錯,這很好,但是我們如何在生產環境中使用它呢?”
如何在現實世界中使用它
想要在第一次使用 CSP 之後就失望透頂的方法就是在生產環境中測試。不要想當然的認為,“這會很簡單。我的程式碼是完美並且相當清晰的。”不要這樣作。我這樣幹過。相信我,這相當的蠢。
正如我之前說明的,CSP 指令由 CSP 頭部來啟用,這中間沒有過渡階段。你恰恰就是其中的薄弱環節。你可能會忘記授權某些東西或者遺忘了你網站中的一小段程式碼。CSP 不會饒恕你的疏忽。然而,CSP 的兩個特性將這個問題變得相當的簡單。
report-uri
還記得 CSP 傳送到終端中的那些通知麼?report-uri
指令可以被用來告訴瀏覽器傳送那些通知到指定的地址。報告以 JSON 格式送出。
report-uri /csp-parser.php ;
因此,我們可以在 csp-parser.php 檔案中處理有瀏覽器送出的資料。這裡有一個由 PHP 實現的最基礎的例子:
$data = file_get_contents('php://input');
if ($data = json_decode($data, true)) {
$data = json_encode(
$data,
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
);
mail(EMAIL, SUBJECT, $data);
}
這個通知將會被轉換成為一封郵件。在開發過程中,你可能不會需要比這更復雜的其它東西。
對於一個生產環境(或者是一個有較多訪問的開發環境),你應該使用一種比郵件更好的收集資訊的方式,因為這種方式在節點上沒有驗證和速率限制,並且 CSP 可能變得亂哄哄的。只需想像一個會產生 100 個 CSP 通知(例如,一個從未授權來源展示圖片的指令碼)並且每天會被瀏覽 100 次的頁面,那你就會每天收到 10000 個通知啊!
例如 report-uri.io 這樣的服務可以用來簡化你的通知管理。你也可以在 GitHub上看一些另外的使用 report-uri
(與資料庫搭配,新增一些最佳化,等)的簡單例子。
report-only
正如我們所見的,最大的問題就是在使用和不使用 CSP 之間沒有中間地帶。然而,一個名為 report-only
的特性會傳送一個稍有不同的頭部:
<?php
header("Content-Security-Policy-Report-Only: <your directives>");
?>
總的來說,這個頭部就是告訴瀏覽器,“表現得似乎所有的 CSP 指令都被應用了,但是不禁止任何東西。只是傳送通知給自己。”這是一種相當棒的測試指令的方式,避免了任何有價值的東西被禁止的風險。
在 report-only
和 report-uri
的幫助下你可以毫無風險的測試 CSP 指令,並且可以實時的監控網站上一切與 CSP 相關的內容。這兩個特性對部署和維護 CSP 來說真是相當的有用!
結論
為什麼 CSP 很酷
CSP 對你的使用者來說是尤其重要的:他們在你的網站上不再需要遭受任何的未經請求的指令碼,內容或 XSS 的威脅了。
對於網站維護者來說 CSP 最重要的優勢就是可感知。如果你對圖片來源設定了嚴格的規則,這時一個指令碼小子嘗試在你的網站上插入一張未授權來源的圖片,那麼這張圖片就會被禁止,並且你會在第一時間收到提醒。
開發者也需要確切的知道他們的前端程式碼都在做些什麼,CSP 可以幫助他們掌控一切。會促使他們去重構他們程式碼中的某些部分(避免行內函數和樣式,等)並且促使他們遵循最佳實踐。
如何讓 CSP 變得更酷
諷刺的是,CSP 在一些瀏覽器中過分的高效了,在和書籤欄小程式一起使用時會產生一些 bug。因此,不要更新你的 CSP 指令來允許書籤欄小程式。我們無法單獨的責備任何一個瀏覽器;它們都有些問題:
- Firefox
- Chrome (Blink)
- WebKit
大多數情況下,這些 bug 都是禁止通知中的誤報。所有的瀏覽器提供者都在努力解決這些問題,因此我們可以期待很快就會被解決。無論怎樣,這都不會成為你使用 CSP 的絆腳石。
via: https://www.smashingmagazine.com/2016/09/content-security-policy-your-future-best-friend/
作者:Nicolas Hoffmann 譯者:wcnnbdk1 校對:wxy
相關文章
- 防禦XSS攻擊的七條原則
- 防禦 XSS 攻擊的七條原則
- WEB攻擊手段及防禦第1篇-XSSWeb
- HTTP 的內容安全策略(CSP)HTTP
- 如何有效防禦XSS攻擊?網路安全學習教程
- WEB攻擊與防禦Web
- CSRF攻擊與防禦
- 淺談DDOS攻擊攻擊與防禦
- Web 安全之內容安全策略 (CSP)Web
- 高防伺服器主要防禦的攻擊伺服器
- CC攻擊的原理是什麼?如何防禦CC攻擊?
- 跨域及相關攻擊&防禦總結(JSONP、CORS、CSRF、XSS)跨域JSONCORS
- React 防注入攻擊 XSS攻擊 (放心大膽的用吧)React
- cc攻擊防禦解決方法
- 網站被攻擊如何防禦網站
- 淺談DDos攻擊與防禦
- 瀏覽器安全策略說之內容安全策略CSP瀏覽器
- JeecgBoot抵禦XSS攻擊實現方案boot
- 前端防禦XSS前端
- WMI 的攻擊,防禦與取證分析技術之防禦篇
- DDOS伺服器防禦的方法有哪些,如何防禦DDOS攻擊伺服器
- XXE攻擊攻擊原理是什麼?如何防禦XXE攻擊?
- DDOS攻擊原理,種類及其防禦
- 伺服器如何防禦CC攻擊伺服器
- 跨域攻擊分析和防禦(中)跨域
- WMI 的攻擊,防禦與取證分析技術之攻擊篇
- CC攻擊的原理是什麼?防禦CC攻擊的方法有哪些?
- 高防伺服器如何防禦網路攻擊伺服器
- Akamai淺談網路攻擊的防禦AI
- Linux下防禦DDOS攻擊的操作梳理Linux
- XXE攻擊是什麼?如何有效防禦XXE攻擊?
- 直播行業如何防禦網路攻擊?行業
- 電商平臺如何防禦網路攻擊?
- CSS keylogger:攻擊與防禦CSS
- DevOps 團隊如何防禦 API 攻擊devAPI
- 生成樹欺騙攻擊與防禦策略
- 淺談 JavaScript DDoS 攻擊原理與防禦JavaScript
- 淺談JavaScript DDoS攻擊原理與防禦JavaScript