8大前端安全問(wèn)題(上)

當(dāng)我們說(shuō)“前端安全問(wèn)題”的時(shí)候踩萎,我們?cè)谡f(shuō)什么

“安全”是個(gè)很大的話題棋蚌,各種安全問(wèn)題的類型也是種類繁多岛抄。如果我們把安全問(wèn)題按照所發(fā)生的區(qū)域來(lái)進(jìn)行分類的話绅络,那么所有發(fā)生在后端服務(wù)器月培、應(yīng)用、服務(wù)當(dāng)中的安全問(wèn)題就是“后端安全問(wèn)題”恩急,所有發(fā)生在瀏覽器杉畜、單頁(yè)面應(yīng)用、Web頁(yè)面當(dāng)中的安全問(wèn)題則算是“前端安全問(wèn)題”衷恭。比如說(shuō)此叠,SQL注入漏洞發(fā)生在后端應(yīng)用中,是后端安全問(wèn)題随珠,跨站腳本攻擊(XSS)則是前端安全問(wèn)題灭袁,因?yàn)樗l(fā)生在用戶的瀏覽器里猬错。

除了從安全問(wèn)題發(fā)生的區(qū)域來(lái)分類之外,也可以從另一個(gè)維度來(lái)判斷:針對(duì)某個(gè)安全問(wèn)題茸歧,團(tuán)隊(duì)中的哪個(gè)角色最適合來(lái)修復(fù)它倦炒?是后端開(kāi)發(fā)還是前端開(kāi)發(fā)?

總的來(lái)說(shuō)软瞎,當(dāng)我們下面在談?wù)摗扒岸税踩珕?wèn)題”的時(shí)候逢唤,我們說(shuō)的是發(fā)生在瀏覽器、前端應(yīng)用當(dāng)中铜涉,或者通常由前端開(kāi)發(fā)工程師來(lái)對(duì)其進(jìn)行修復(fù)的安全問(wèn)題智玻。

8大前端安全問(wèn)題

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

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

由于篇幅所限吊奢,本篇文章先給各位介紹前4個(gè)前端安全問(wèn)題。

老生常談的XSS

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

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

無(wú)論怎么分類,XSS漏洞始終是威脅用戶的一個(gè)安全隱患闷愤。攻擊者可以利用XSS漏洞來(lái)竊取包括用戶身份信息在內(nèi)的各種敏感信息整葡、修改Web頁(yè)面以欺騙用戶,甚至控制受害者瀏覽器讥脐,或者和其他漏洞結(jié)合起來(lái)形成蠕蟲(chóng)攻擊遭居,等等⊙總之俱萍,關(guān)于XSS漏洞的利用,只有想不到?jīng)]有做不到告丢。

如何防御

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

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

其他的防御措施熏纯,例如設(shè)置CSP HTTP Header同诫、輸入驗(yàn)證、開(kāi)啟瀏覽器XSS防御等等都是可選項(xiàng)樟澜,原因在于這些措施都存在被繞過(guò)的可能误窖,并不能完全保證能防御XSS攻擊。不過(guò)它們和輸出編碼卻可以共同協(xié)作實(shí)施縱深防御策略秩贰。

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

警惕iframe帶來(lái)的風(fēng)險(xiǎn)

有些時(shí)候我們的前端頁(yè)面需要用到第三方提供的頁(yè)面組件萍膛,通常會(huì)以iframe的方式引入吭服。典型的例子是使用iframe在頁(yè)面上添加第三方提供的廣告、天氣預(yù)報(bào)蝗罗、社交分享插件等等艇棕。

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

如果說(shuō)iframe只是有可能會(huì)給用戶體驗(yàn)帶來(lái)影響闺骚,看似風(fēng)險(xiǎn)不大彩扔,那么如果iframe中的域名因?yàn)檫^(guò)期而被惡意攻擊者搶注,或者第三方被黑客攻破僻爽,iframe中的內(nèi)容被替換掉了虫碉,從而利用用戶瀏覽器中的安全漏洞下載安裝木馬、惡意勒索軟件等等胸梆,這問(wèn)題可就大了敦捧。

如何防御

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

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

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

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

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

更多詳細(xì)的資料卵凑,可以參考iframe中關(guān)于sandbox的介紹庆聘。

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

有個(gè)詞叫做防不勝防,我們?cè)谕ㄟ^(guò)iframe使用別人提供的內(nèi)容時(shí)勺卢,我們自己的頁(yè)面也可能正在被不法分子放到他們精心構(gòu)造的iframe或者frame當(dāng)中伙判,進(jìn)行點(diǎn)擊劫持攻擊。

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

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

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

如何防御

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

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

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

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

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

在上面的例子中畅哑,后端通過(guò)Content-Type Header建議瀏覽器按照?qǐng)D片來(lái)渲染這次的HTTP響應(yīng),但是瀏覽器發(fā)現(xiàn)響應(yīng)中其實(shí)是JavaScript水由,于是就擅自做主把這段響應(yīng)當(dāng)做JS腳本來(lái)解釋執(zhí)行荠呐,安全問(wèn)題也就產(chǎn)生了赛蔫。

如何防御

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

同樣是上面的攻擊場(chǎng)景,后端服務(wù)器返回的Content-Type建議瀏覽器按照?qǐng)D片進(jìn)行內(nèi)容渲染钞钙,瀏覽器發(fā)現(xiàn)有X-Content-Type-OptionsHTTP Header的存在鳄橘,并且其參數(shù)值是nosniff,因此不會(huì)再去推斷內(nèi)容類型芒炼,而是強(qiáng)制按照?qǐng)D片進(jìn)行渲染瘫怜,那么因?yàn)閷?shí)際上這是一段JS腳本而非真實(shí)的圖片,因此這段腳本就會(huì)被瀏覽器當(dāng)作是一個(gè)已經(jīng)損壞或者格式不正確的圖片來(lái)處理本刽,而不是當(dāng)作JS腳本來(lái)處理鲸湃,從而最終防止了安全問(wèn)題的發(fā)生。

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

小結(jié)

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

文/ThoughtWorks馬偉

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末晒衩,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子墙歪,更是在濱河造成了極大的恐慌听系,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虹菲,死亡現(xiàn)場(chǎng)離奇詭異靠胜,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)毕源,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門浪漠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人霎褐,你說(shuō)我怎么就攤上這事址愿。” “怎么了冻璃?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵响谓,是天一觀的道長(zhǎng)损合。 經(jīng)常有香客問(wèn)我,道長(zhǎng)娘纷,這世上最難降的妖魔是什么嫁审? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮赖晶,結(jié)果婚禮上律适,老公的妹妹穿的比我還像新娘。我一直安慰自己遏插,他們只是感情好捂贿,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著胳嘲,像睡著了一般厂僧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胎围,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音德召,去河邊找鬼白魂。 笑死,一個(gè)胖子當(dāng)著我的面吹牛上岗,可吹牛的內(nèi)容都是我干的福荸。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼肴掷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼敬锐!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起呆瞻,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤台夺,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后痴脾,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體颤介,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年赞赖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了滚朵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡前域,死狀恐怖辕近,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情匿垄,我是刑警寧澤移宅,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布归粉,位于F島的核電站,受9級(jí)特大地震影響吞杭,放射性物質(zhì)發(fā)生泄漏盏浇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一芽狗、第九天 我趴在偏房一處隱蔽的房頂上張望绢掰。 院中可真熱鬧,春花似錦童擎、人聲如沸滴劲。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)班挖。三九已至,卻和暖如春芯砸,著一層夾襖步出監(jiān)牢的瞬間萧芙,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工假丧, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留双揪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓包帚,卻偏偏與公主長(zhǎng)得像渔期,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子渴邦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容