
NGINX 檔頭設定:Content-Security-Policy 語法與常見錯誤
Content-Security-Policy(內容安全政策,簡稱 CSP)是一個 HTTP 回應標頭,用來告訴瀏覽器「這個頁面只能從哪些來源載入程式、樣式、圖片」,可以降低跨站腳本攻擊(XSS)與惡意外掛置換的風險。這篇整理在 NGINX 設定 CSP 的寫法、語法規則與常見錯誤。整體的安全性標頭設定與導入步驟,見網頁伺服器的安全性設定。
一、NGINX 設定範例
server {
add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://connect.facebook.net https://d.line-scdn.net; style-src 'self' 'unsafe-inline'; img-src 'self' https: data:; frame-src https://www.youtube.com; frame-ancestors 'self'; object-src 'none'; base-uri 'self'" always;
add_header X-Content-Type-Options "nosniff" always;
}
上面的政策意思是:預設只允許自己網站的資源;程式碼另外允許 Facebook 與 LINE 的外掛;圖片允許任何 https 來源與 data 格式;只允許嵌入 YouTube 影片;不允許別人用框架嵌入本站。實際要允許哪些來源,要依網站用到的外部服務調整。
always 參數讓錯誤頁面(例如 404、500)也帶上標頭。另外 NGINX 的 add_header 有「子區塊會覆蓋父區塊」的陷阱,見網頁伺服器的安全性設定第五節。
二、常用的指令
| 指令 | 控制什麼 |
|---|---|
default-src | 預設值,沒有另外指定的類型都套用這一條 |
script-src | JavaScript 程式 |
style-src | CSS 樣式 |
img-src | 圖片 |
font-src | 字型 |
connect-src | 程式發出的連線,例如 AJAX、分析工具回傳資料 |
frame-src | 本站頁面裡可以嵌入哪些網站,例如 YouTube、Google 地圖 |
frame-ancestors | 哪些網站可以用框架嵌入本站,用來防止點擊挾持 |
object-src | Flash 等外掛物件,現在建議設為 'none' |
base-uri | 頁面中 <base> 標籤可以指定的網址 |
三、常用的來源寫法
| 寫法 | 意思 |
|---|---|
'self' | 與目前頁面相同的網域 |
'none' | 完全不允許 |
https://www.example.com | 指定的網域,網域不需要引號 |
https: | 任何 https 來源 |
data: | data 格式的內嵌資源,常見於內嵌的小圖示 |
'unsafe-inline' | 允許寫在頁面裡的程式或樣式,會降低防護效果 |
'unsafe-eval' | 允許 eval 等動態執行程式,會降低防護效果 |
'unsafe-inline'、'unsafe-eval' 會讓 CSP 對 XSS 的防護大打折扣,script-src 盡量不要使用。舊系統或外掛必須用到時,可以先只在 style-src 允許 'unsafe-inline',程式的部分再逐步調整。
四、語法規則與常見錯誤
-
指令後面不加冒號
錯誤:
default-src: 'self'正確:
default-src 'self' -
指令之間以分號區隔
錯誤:
default-src 'self', script-src 'self'正確:
default-src 'self'; script-src 'self' -
多個來源之間只用空白區隔
錯誤:
img-src 'self', web1.nc.com.tw, web2.nc.com.tw正確:
img-src 'self' web1.nc.com.tw web2.nc.com.tw -
https:、data: 這類來源要加冒號
錯誤:
img-src 'self' https data正確:
img-src 'self' https: data: -
'self'、'none'、'unsafe-inline'、'unsafe-eval' 要用單引號括起來
錯誤:
script-src self unsafe-inline正確:
script-src 'self' 'unsafe-inline' -
單引號要用半形的 ',不能用全形或彎引號
從文書軟體或網頁複製設定時,引號常被自動換成 ‘ ’ 這類彎引號,瀏覽器會無法辨識。
-
整段政策在 NGINX 設定中要用雙引號包起來
政策裡已經有單引號,外層用雙引號,NGINX 才不會解析錯誤。
五、已經不建議使用的標頭
- X-XSS-Protection:舊版瀏覽器的 XSS 過濾功能,Chrome 已經移除、Firefox 從未支援,而且這個過濾功能本身曾被利用來製造漏洞。現在建議不設定,或設為
0,改用 CSP 防護 - X-Frame-Options:防止被框架嵌入,CSP 的
frame-ancestors可以取代它。為了相容舊瀏覽器,兩者可以同時設定
六、設定後怎麼確認
- 重新載入 NGINX 前,先用
nginx -t檢查設定檔語法 - 打開網站,按
F12開啟開發者工具,在「Console」查看有沒有資源被 CSP 擋下的訊息 - 在「Network」點選頁面的請求,確認回應標頭裡有 Content-Security-Policy
第一次導入時,建議先用 Content-Security-Policy-Report-Only 只觀察不阻擋,確認沒有誤擋正常功能再正式啟用,做法見網頁伺服器的安全性設定第六節。