8大前端安全問題(上)

原文鏈接:https://mawei.blog/post/frontend-security-vulnerabilities-part1

當(dāng)我們說“前端安全問題”的時候,我們在說什么

安全是個很大的話題,各種安全問題的類型也是種類繁多。如果我們把安全問題按照所發(fā)生的地方來進(jìn)行分類的話,那么所有發(fā)生在后端服務(wù)器、應(yīng)用、服務(wù)當(dāng)中的安全問題就是“后端安全問題”,所有發(fā)生在瀏覽器、單頁面應(yīng)用、Web頁面當(dāng)中的安全問題則算是“前端安全問題”。比如說,SQL注入漏洞發(fā)生在后端應(yīng)用中,是后端安全問題,跨站腳本攻擊(XSS)則是前端安全問題,因為它發(fā)生在用戶的瀏覽器里。

除了從安全問題發(fā)生的地方來分類之外,也可以從另一個維度來判斷這是否是個前端安全問題:針對某個安全問題,團(tuán)隊中的哪個角色最適合來修復(fù)它?是后端開發(fā)還是前端開發(fā)?

總的來說,當(dāng)我們下面在談?wù)摗扒岸税踩珕栴}”的時候,我們說的是發(fā)生瀏覽器、前端應(yīng)用當(dāng)中,或者通常由前端開發(fā)工程師來對其進(jìn)行修復(fù)的安全問題。

8大前端安全問題

按照上面的分類辦法,我們總結(jié)出了8大典型前端安全問題,它們分別是:

  • 老生常談的XSS
  • 警惕iFrame帶來的風(fēng)險
  • 別被點(diǎn)擊劫持了
  • 錯誤的內(nèi)容推斷
  • 防火防盜防豬隊友:不安全的第三方依賴包
  • 用了HTTPS也可能掉坑里
  • 本地存儲數(shù)據(jù)泄露
  • 缺失靜態(tài)資源完整性校驗

由于篇幅所限,本篇文章我們先給各位介紹前4個前端安全問題。

老生常談的XSS

XSS是跨站腳本攻擊(Cross-Site Scripting)的簡稱,它是個老油條了,在OWASP Web Application Top 10 排行榜中長期霸榜,從未掉出過前三名。XSS這類安全問題發(fā)生的本質(zhì)性原因在于,瀏覽器錯誤的將攻擊者提供的用戶輸入數(shù)據(jù)當(dāng)做了JavaScript腳本給執(zhí)行了。

XSS有幾種不同的分類辦法,例如按照惡意輸入的腳本是否在應(yīng)用中存儲,XSS被劃分為“存儲型XSS”和“反射型XSS”,如果按照是否和服務(wù)器有交互,又可以劃分為“Server Side XSS”和“DOM based XSS”。

無論怎么分類,XSS漏洞始終是威脅用戶的一旦安全隱患。攻擊者可以利用XSS漏洞來竊取包括用戶身份信息在內(nèi)的各種敏感信息、修改Web頁面以欺騙用戶,甚至控制受害者瀏覽器,或者和其他漏洞結(jié)合起來形成蠕蟲攻擊,等等。總之,關(guān)于XSS漏洞的利用,只有想不到?jīng)]有做不到。

如何防御

防御XSS最佳的做法就是對數(shù)據(jù)進(jìn)行嚴(yán)格的輸出編碼,使得攻擊者提供的數(shù)據(jù)不再被瀏覽器認(rèn)為是腳本而被誤執(zhí)行。例如 <script>在進(jìn)行HTML編碼后變成了<script>,而這段數(shù)據(jù)就會被瀏覽器認(rèn)為只是一段普通的字符串,而不會被當(dāng)做腳本執(zhí)行了。

編碼也不是件容易的事情,需要根據(jù)輸出數(shù)據(jù)所在的上下文來進(jìn)行相應(yīng)的編碼。例如剛才的例子,由于數(shù)據(jù)將被放置于HTML元素中,因此進(jìn)行的是HTML編碼,而如果數(shù)據(jù)將被放置于URL中,則需要進(jìn)行URL編碼,將其變?yōu)?code>%3Cscript%3E。此外,還有JavaScript編碼、CSS編碼、HTML屬性編碼、JSON編碼等等。好在現(xiàn)如今的前端開發(fā)框架基本上默認(rèn)都提供了前端輸出編碼,這大大減輕了前端開發(fā)小伙伴們的工作負(fù)擔(dān)。

其他的防御措施,例如設(shè)置CSP HTTP Header、輸入驗證、開啟瀏覽器XSS防御等等都是可選項,原因在于這些措施都存在被繞過的可能,并不能完全保證能防御XSS攻擊。不過它們和輸出編碼卻可以共同協(xié)作實施縱深防御策略。

你可以查閱OWASP XSS Prevention Cheat Sheet,里面有關(guān)于XSS及其防御措施的詳細(xì)說明。

警惕iFrame帶來的風(fēng)險

有些時候我們的前端頁面需要用到第三方提供的頁面組件,通常會以iframe的方式引入進(jìn)來。典型的例子是使用iframe在頁面上添加第三方提供的廣告、天氣預(yù)報、社交分享插件等等。

iframe在給我們的頁面帶來更多豐富的內(nèi)容和能力的同時,也帶來了不少的安全隱患。因為iframe中的內(nèi)容是由第三方來提供的,默認(rèn)情況下他們不受我們的控制,他們可以在iframe中運(yùn)行JavaScirpt腳本、Flash插件、彈出對話框等等,這可能會破壞前端用戶體驗。

如果說iframe只是有可能會給用戶體驗帶來影響,看似風(fēng)險不大,那么如果iframe中的域名因為過期而被惡意攻擊者搶注,或者第三方被黑客攻破,iframe中的內(nèi)容別替換掉了,從而利用用戶瀏覽器中的安全漏洞下載安裝木馬、惡意勒索軟件等等,這可就鬧大了。

如何防御

還好HTML5中iframe有了一個叫做sandbox的安全屬性,通過它可以對iframe的行為進(jìn)行各種限制,充分實現(xiàn)“最小權(quán)限“原則。使用sandbox的最簡單的方式就是只在iframe元素中添加上這個關(guān)鍵詞就好,就像下面這樣:

<iframe sandbox src="..."> ... </iframe>

sandbox還忠實的實現(xiàn)了”Secure By Default“原則,也即是說,如果你只是添加上這個屬性而保持屬性值為空,那么瀏覽器將會對iframe實施史上最嚴(yán)厲的調(diào)控限制,基本上來講就是除了允許顯示靜態(tài)資源以外,其他什么都做不了。比如不準(zhǔn)提交表單、不準(zhǔn)彈窗、不準(zhǔn)執(zhí)行腳本等等,連Origin都會被強(qiáng)制重新分配一個唯一的值,換句話講就是iframe中的頁面訪問它自己的服務(wù)器都會被算作跨域請求。

另外,sandbox也提供了豐富的配置參數(shù),我們可以進(jìn)行較為細(xì)粒度的控制。一些典型的參數(shù)如下:

  • allow-forms: 允許iframe中提交form表單
  • allow-popups: 允許iframe中彈出新的窗口或者標(biāo)簽頁(例如,window.open(),showModalDialog(),target=”_blank”等等)
  • allow-scripts: 允許iframe中執(zhí)行JavaScript
  • allow-same-origin: 允許iframe中的網(wǎng)頁開啟同源策略

更多詳細(xì)的資料,可以參考iframe中關(guān)于sandbox的介紹:https://developer.mozilla.org/en/docs/Web/HTML/Element/iframe

別被點(diǎn)擊劫持了

有句話叫做防不勝防,我們在通過iframe使用別人家提供的內(nèi)容的時候,我們自己的頁面也可能正在被不法分子放到他們精心構(gòu)造的iframe或者frame當(dāng)中,進(jìn)行點(diǎn)擊劫持攻擊。

這是一種欺騙性比較強(qiáng),同時也需要用戶高度參與才能完成的一種攻擊。通常的攻擊步驟是這樣的:

  1. 攻擊者精心構(gòu)造一個誘導(dǎo)用戶點(diǎn)擊的內(nèi)容,比如說Web頁面小游戲
  2. 將我們的頁面放入到iframe當(dāng)中
  3. 利用z-index等CSS樣式將這個iframe疊加到小游戲的垂直方向的正上方
  4. 把iframe設(shè)置為100%透明度
  5. 受害者訪問到這個頁面后,肉眼看到的是一個小游戲,如果受到誘導(dǎo)進(jìn)行了點(diǎn)擊的話,實際上點(diǎn)擊到的卻是iframe中的我們的頁面

點(diǎn)擊劫持的危害在于,攻擊利用了受害者的用戶身份,在其不知情的情況下進(jìn)行一些操作。如果只是迫使用戶關(guān)注某個微博賬號的話,看上去仿佛還可以承受,但是如果是刪除某個重要文件記錄,或者竊取敏感信息,那么造成的危害可就難以承受了。

如何防御

有多種防御措施都可以防止頁面遭到點(diǎn)擊劫持攻擊,例如Frame Breaking方案。一個推薦的防御方案是,使用X-Frame-Options: DENY這個HTTP Header來明確的告知瀏覽器,不要把當(dāng)前HTTP響應(yīng)中的內(nèi)容在HTML Frame中顯示出來。

關(guān)于點(diǎn)擊劫持更多的細(xì)節(jié),可以查閱OWASP Clickjacking Defense Cheat Sheet。

錯誤的內(nèi)容推斷

想象一下這樣一個攻擊場景:某網(wǎng)站允許用戶在評論里上傳圖片,攻擊者在上傳圖片的時候,看似提交的是個圖片文件,實則是個含有JavaScript的腳本文件。該文件逃過了文件類型校驗(這涉及到了惡意文件上傳這個常見安全問題,但是由于和前端相關(guān)度不高因此暫不詳細(xì)介紹),在服務(wù)器里存儲了下來。接下來,受害者在訪問這段評論的時候,瀏覽器會去請求這個偽裝成圖片的JavaScript腳本,而此時如果瀏覽器錯誤的推斷了這個響應(yīng)的內(nèi)容類型(MIME types),那么就會把這個圖片文件當(dāng)做JavaScript腳本執(zhí)行,于是攻擊也就成功了。

問題的關(guān)鍵就在于,后端服務(wù)器在返回的響應(yīng)中設(shè)置的Content-Type Header僅僅只是給瀏覽器提供當(dāng)前響應(yīng)內(nèi)容類型的建議,而瀏覽器有可能會自作主張的根據(jù)響應(yīng)中的實際內(nèi)容去推斷內(nèi)容的類型。

在上面的例子中,后端通過Content-Type Header建議瀏覽器按照圖片來渲染這次的HTTP響應(yīng),但是瀏覽器發(fā)現(xiàn)響應(yīng)中其實是JavaScript,于是就擅自做主把這段響應(yīng)當(dāng)做JS腳本來解釋執(zhí)行,安全問題也就產(chǎn)生了。

如何防御

瀏覽器根據(jù)響應(yīng)內(nèi)容來推斷其類型,本來這是個很”智能“的功能,是瀏覽器強(qiáng)大的容錯能力的體現(xiàn),但是卻會帶來安全風(fēng)險。要避免出現(xiàn)這樣的安全問題,辦法就是通過設(shè)置X-Content-Type-Options這個HTTP Header明確禁止瀏覽器去推斷響應(yīng)類型。

同樣是上面的攻擊場景,后端服務(wù)器返回的Content-Type建議瀏覽器按照圖片進(jìn)行內(nèi)容渲染,瀏覽器發(fā)現(xiàn)有X-Content-Type-OptionsHTTP Header的存在,并且其參數(shù)值是nosniff,因此不會再去推斷內(nèi)容類型,而是強(qiáng)制按照圖片進(jìn)行渲染,那么因為實際上這是一段JS腳本而非真實的圖片,因此這段腳本就不會被瀏覽器執(zhí)行。

更多關(guān)于X-Content-Type-Options的細(xì)節(jié)請參考這里。

小結(jié)

本文對前端安全問題進(jìn)行了一次梳理,介紹了其中4個典型的前端安全問題,包括它們發(fā)生的原因以及防御辦法。在下篇文章中,我們將介紹其他的幾個前端安全問題,敬請期待。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容