前端面試題-安全防范

這一篇文章我們將來學(xué)習(xí)安全防范這一塊的知識(shí)點(diǎn)??偟膩碚f安全是很復(fù)雜的一個(gè)領(lǐng)域,不可能通過一篇文章就學(xué)習(xí)完。在這里,我們主要學(xué)習(xí)常見的一些安全問題及如何防范的內(nèi)容。在當(dāng)下,其實(shí)安全問題對(duì)前端開發(fā)已經(jīng)越來越重要,已經(jīng)逐漸成為前端開發(fā)必備的技能了。


前端面試題

1. XSS

涉及面試題:什么是 XSS 攻擊?如何防范 XSS 攻擊?什么是 CSP?

XSS 簡單點(diǎn)來說,就是攻擊者想盡一切辦法將可以執(zhí)行的代碼注入到網(wǎng)頁中。

1.1 類型

XSS 可以分為多種類型,但是總體上我認(rèn)為分為兩類:持久型和非持久型。

持久型

持久型也就是攻擊的代碼被服務(wù)端寫入進(jìn)數(shù)據(jù)庫中,這種攻擊危害性很大,因?yàn)槿绻W(wǎng)站訪問量很大的話,就會(huì)導(dǎo)致大量正常訪問頁面的用戶都受到攻擊。
舉個(gè)栗子,對(duì)于評(píng)論功能來說,就得防范持久型 XSS 攻擊,因?yàn)槲铱梢栽谠u(píng)論中輸入以下內(nèi)容


評(píng)論

這種情況如果前后端沒有做好防御的話,這段評(píng)論就會(huì)被存儲(chǔ)到數(shù)據(jù)庫中,這樣每個(gè)打開該頁面的用戶都會(huì)被攻擊到。

非持久型

非持久型相比于前者危害就小的多了,一般通過修改 URL 參數(shù)的方式加入攻擊代碼,誘導(dǎo)用戶訪問鏈接從而進(jìn)行攻擊。
再舉個(gè)栗子,如果頁面需要從 URL 中獲取某些參數(shù)作為內(nèi)容的話,不經(jīng)過過濾就會(huì)導(dǎo)致攻擊代碼被執(zhí)行。

<!-- http://www.domain.com?name=<script>alert(1)</script> -->
<div>{{name}}</div> 

但是對(duì)于這種攻擊方式來說,如果用戶使用 Chrome 這類瀏覽器的話,瀏覽器就能自動(dòng)幫助用戶防御攻擊。但是我們不能因此就不防御此類攻擊了,因?yàn)槲也荒艽_保用戶都使用了該類瀏覽器。


該網(wǎng)頁無法訪問

1.2 防御對(duì)策

對(duì)于 XSS 攻擊來說,通常有兩種方式可以用來防御。

轉(zhuǎn)義字符

首先,對(duì)于用戶的輸入應(yīng)該是永遠(yuǎn)不信任的。最普遍的做法就是轉(zhuǎn)義輸入輸出的內(nèi)容,對(duì)于引號(hào)、尖括號(hào)、斜杠進(jìn)行轉(zhuǎn)義

function escape(str) {
   str = str.replace(/&/g, '&');
   str = str.replace(/</g, '<');
   str = str.replace(/>/g, '>');
   str = str.replace(/"/g, '&quto;');
   str = str.replace(/'/g, ''');
   str = str.replace(/`/g, '`');
   str = str.replace(///g, '/');
   return str;
}

通過轉(zhuǎn)義可以將攻擊代碼 <script>alert(1)</script> 變成

// -> <script>alert(1)</script>
escape('<script>alert(1)</script>')

但是對(duì)于顯示富文本來說,顯然不能通過上面的辦法來轉(zhuǎn)義所有字符,因?yàn)檫@樣會(huì)把需要的格式也過濾掉。對(duì)于這種情況,通常采用白名單過濾的辦法,當(dāng)然也可以通過黑名單過濾,但是考慮到需要過濾的標(biāo)簽和標(biāo)簽屬性實(shí)在太多,更加推薦使用白名單的方式。

const xss = require('xss');
let html = xss('<h1 id="title">XSS Demo</h1><script>alert("XSS");</script>');
// -><h1>XSS Demo</h1>$lt;script&gt;alert("XSS");&lt;/script&gt;
console.log(html);

以上示例使用了 js-xss 來實(shí)現(xiàn),可以看到在輸出中保留了 h1 標(biāo)簽且過濾了 script 標(biāo)簽。

CSP

CSP 本質(zhì)上就是建立白名單,開發(fā)者明確告訴瀏覽器哪些外部資源可以加載和執(zhí)行。我們只需要配置規(guī)則,如何攔截是由瀏覽器自己實(shí)現(xiàn)的。我們可以通過這種方式來盡量減少 XSS 攻擊。
通??梢酝ㄟ^兩種方式來開啟 CSP:

  • 設(shè)置 HTTP Header 中的 Content-Security-Policy
  • 設(shè)置 meta 標(biāo)簽的方式 <meta http-equiv="Content-Security-Policy">

這里以設(shè)置 HTTP Header 來舉例

  • 只允許加載本站資源
Content-Security-Policy: default-src ‘self’
  • 只允許加載 HTTPS 協(xié)議圖片
Content-Security-Policy: img-src https://*
  • 允許加載任何來源框架
Content-Security-Policy: child-src 'none'

當(dāng)然可以設(shè)置的屬性遠(yuǎn)不止這些,你可以通過查閱 文檔 的方式來學(xué)習(xí),這里就不過多贅述其他的屬性了。
對(duì)于這種方式來說,只要開發(fā)者配置了正確的規(guī)則,那么即使網(wǎng)站存在漏洞,攻擊者也不能執(zhí)行它的攻擊代碼,并且 CSP 的兼容性也不錯(cuò)。


CSP兼容性

2. CSRF

涉及面試題:什么是 CSRF 攻擊?如何防范 CSRF 攻擊?

CSRF 中文名為跨站請(qǐng)求偽造。原理就是攻擊者構(gòu)造出一個(gè)后端請(qǐng)求地址,誘導(dǎo)用戶點(diǎn)擊或者通過某些途徑自動(dòng)發(fā)起請(qǐng)求。如果用戶是在登錄狀態(tài)下的話,后端就以為是用戶在操作,從而進(jìn)行相應(yīng)的邏輯。
舉個(gè)栗子,假設(shè)網(wǎng)站中有一個(gè)通過 GET 請(qǐng)求提交用戶評(píng)論的接口,那么攻擊者就可以在釣魚網(wǎng)站中加入一個(gè)圖片,圖片的地址就是評(píng)論接口。

<img src="http://www.domain.com/xxx?comment='attack'"/>

那么你是否會(huì)想到使用 POST 方式提交請(qǐng)求是不是就沒有這個(gè)問題了呢?其實(shí)并不是,使用這種方式也不是百分百安全的,攻擊者同樣可以誘導(dǎo)用戶進(jìn)入某個(gè)頁面,在頁面中通過表單提交 POST 請(qǐng)求。

2.1 如何防御

防范 CSRF 攻擊可以遵循以下幾種規(guī)則:

  • Get 請(qǐng)求不對(duì)數(shù)據(jù)進(jìn)行修改
  • 不讓第三方網(wǎng)站訪問到用戶 Cookie
  • 阻止第三方網(wǎng)站請(qǐng)求接口
  • 請(qǐng)求時(shí)附帶驗(yàn)證信息,比如驗(yàn)證碼或者 Token

SameSite

可以對(duì) Cookie 設(shè)置 SameSite 屬性。該屬性表示 Cookie 不隨著跨域請(qǐng)求發(fā)送,可以很大程度減少 CSRF 的攻擊,但是該屬性目前并不是所有瀏覽器都兼容。

驗(yàn)證 Referer

對(duì)于需要防范 CSRF 的請(qǐng)求,我們可以通過驗(yàn)證 Referer 來判斷該請(qǐng)求是否為第三方網(wǎng)站發(fā)起的。

Token

服務(wù)器下發(fā)一個(gè)隨機(jī) Token,每次發(fā)起請(qǐng)求時(shí)將 Token 攜帶上,服務(wù)器驗(yàn)證 Token 是否有效。

3. 點(diǎn)擊劫持

涉及面試題:什么是點(diǎn)擊劫持?如何防范點(diǎn)擊劫持?

點(diǎn)擊劫持是一種視覺欺騙的攻擊手段。攻擊者將需要攻擊的網(wǎng)站通過 iframe 嵌套的方式嵌入自己的網(wǎng)頁中,并將 iframe 設(shè)置為透明,在頁面中透出一個(gè)按鈕誘導(dǎo)用戶點(diǎn)擊。


點(diǎn)擊劫持

3.1 防御策略

對(duì)于這種攻擊方式,推薦防御的方法有兩種。

X-FRAME-OPTIONS

X-FRAME-OPTIONS 是一個(gè) HTTP 響應(yīng)頭,在現(xiàn)代瀏覽器有一個(gè)很好的支持。這個(gè) HTTP 響應(yīng)頭 就是為了防御用 iframe 嵌套的點(diǎn)擊劫持攻擊。
該響應(yīng)頭有三個(gè)值可選,分別是

  • DENY,表示頁面不允許通過 iframe 的方式展示
  • SAMEORIGIN,表示頁面可以在相同域名下通過 iframe 的方式展示
  • ALLOW-FROM,表示頁面可以在指定來源的 iframe 中展示

JS 防御

對(duì)于某些遠(yuǎn)古瀏覽器來說,并不能支持上面的這種方式,那我們只有通過 JS 的方式來防御點(diǎn)擊劫持了。

<head>
   <style id="click-jack">
     html {
       display: none !important;
     }
   </style>
</head>
<body>
   <script>
     if (self == top) {
       var style = document.getElementById('click-jack');
       document.body.removeChild(style);
     } else {
       top.location = self.location;
     }
   </script>
</body>

以上代碼的作用就是當(dāng)通過 iframe 的方式加載頁面時(shí),攻擊者的網(wǎng)頁直接不顯示所有內(nèi)容了。

4. 中間人攻擊

涉及面試題:什么是中間人攻擊?如何防范中間人攻擊?

中間人攻擊是攻擊方同時(shí)與服務(wù)端和客戶端建立起了連接,并讓對(duì)方認(rèn)為連接是安全的,但是實(shí)際上整個(gè)通信過程都被攻擊者控制了。攻擊者不僅能獲得雙方的通信信息,還能修改通信信息。

通常來說不建議使用公共的 Wi-Fi,因?yàn)楹芸赡芫蜁?huì)發(fā)生中間人攻擊的情況。如果你在通信的過程中涉及到了某些敏感信息,就完全暴露給攻擊方了。

當(dāng)然防御中間人攻擊其實(shí)并不難,只需要增加一個(gè)安全通道來傳輸信息。HTTPS 就可以用來防御中間人攻擊,但是并不是說使用了 HTTPS 就可以高枕無憂了,因?yàn)槿绻銢]有完全關(guān)閉 HTTP 訪問的話,攻擊方可以通過某些方式將 HTTPS 降級(jí)為 HTTP 從而實(shí)現(xiàn)中間人攻擊。

5. 小結(jié)

以上就是我們平時(shí)開發(fā)過程中一些常見的前端安全方面的知識(shí)以及我們應(yīng)該如何防御這些攻擊。但是安全的領(lǐng)域相當(dāng)大,這些內(nèi)容只是滄海一粟,如果大家對(duì)于安全有興趣的話,可以去網(wǎng)上多進(jìn)行拓展學(xué)習(xí),深入原理。

關(guān)注公眾號(hào)【grain先森】,回復(fù)關(guān)鍵詞 【18福利】,獲取為你準(zhǔn)備的年終福利,更多關(guān)鍵詞玩法期待你的探索~

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

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