
為什麼連寫個看起來無害的 CSS 都會被瀏覽器當成恐怖份子。
瀏覽器的大內總管:CSP 到底在嚴格什麼?
各位前端與後端苦力們,有沒有遇過這種慘劇?
當你興高采烈地在網站加上這行內容安全政策(CSP):
Content-Security-Policy: default-src 'self';
本以為從此高枕無憂,結果下一秒打開網頁,發現自己寫的行內腳本(inline-script)全部陣亡:
<script>console.log('連我都不能跑是怎樣');</script>
好啦,大家都知道 JavaScript 權限大、壞人最愛用,所以瀏覽器預設不讓它亂跑很合理。為了安撫大內總管,我們還得乖乖去算雜湊值(Hash)或是塞個 nonce 安全憑證,像是這樣:
Content-Security-Policy: default-src 'self'; script-src 'sha256-xxx...';
但是,最讓人傻眼的是,連單純想幫網頁化妝的行內樣式(inline-style)也被一起關進大牢了:
<style>h1 { color: yellow; }</style>
CSS 到底做錯了什麼?它只是個孩子啊!
警匪片現場:當 CSS 變成滲透工具
資安世界有三大神聖支柱:機密性、完整性、可用性。而隨便亂加的 CSS,其實正在默默破壞這一切。
疑犯一號:DOM 元素私生子(破壞完整性)
你可能會想:「這網頁是我寫的,裡面的 CSS 當然也是我寫的啊!」
事情可沒那麼簡單。在 JavaScript 的世界裡,壞人可以用各種神奇手法動態產生元素:
JavaScript
let style = document.createElement('style');
style.innerText = 'h1 { color: blue; }';
document.body.appendChild(style);
這段程式碼一旦被惡意注入,它就能神不知鬼不覺地改掉你的網頁外觀。這就是為什麼瀏覽器乾脆一不做二不休,預設把所有沒登記過的行內樣式全部封鎖。
疑犯二號:假藉美化名義的間諜(破壞機密性)
CSS 裡面有兩個看起來很無辜、但實際上超常被當作間諜的語法: @import 和 url() 。
當你用了背景圖片:
background-image: url(https://example.com/spy.jpg);
瀏覽器看到這行,就會自動發出一個請求去下載圖片。這時候,壞人就可以利用這個機制搞鬼:
- 偷看你的行蹤(Beacon 技術): 只要把圖片網址加上個人專屬的編碼,當你一打開網頁,壞人的伺服器收到圖片請求,就知道「喔!某某某在幾點幾分看了這個頁面!」
- Cookie 順風車: 如果網站沒設定好,這個請求甚至會順便把你的 Cookie 跨站送出去,直接把你的登入狀態雙手奉上。
所以,想要在有 CSP 的防護下安全地秀出圖片,你還必須跟總管報備圖片的白色名單:
Content-Security-Policy: default-src 'self'; style-src 'sha256-...'; img-src http://信任的圖片來源;
結論
在這個壞人招數層出不窮的時代,網頁開發者真的不能只活在「CSS 只是用來排版」的粉紅泡泡裡。多了解一點 CSP 的龜毛規則,雖然設定時會寫到抓狂,但至少能保住大家的飯碗,不讓網站變成駭客的免費遊樂園!
