隨著互聯(lián)網(wǎng)技術(shù)和web開發(fā)領(lǐng)域的飛速發(fā)展,當(dāng)下的web安全問題也越來越重要,成為開發(fā)中不可小覷的一個(gè)部分。
本文我將帶著大家從一些常見的安全問題入手,探討如何在開發(fā)過程中盡可能的避免一些可能會出現(xiàn)的安全問題以及一些安全防范的知識點(diǎn)。
日常web開發(fā)項(xiàng)目中可能會遇到哪些安全問題呢?
常見的攻擊方式有xss、csrf、點(diǎn)擊劫持、中間人攻擊.......,那么這些攻擊方式分別是什么,是如何進(jìn)行攻擊,我們又怎么樣來進(jìn)行相對的防御呢?接下來我們一一來進(jìn)行了解與探究。
XSS
XSS簡單點(diǎn)來說就是攻擊者會利用一切可能的方式將可執(zhí)行的代碼注入到網(wǎng)頁中。
XSS可以分為多種類型,但整體上分為兩類:持久型和非持久型。
持久型也就是將攻擊的代碼被服務(wù)端寫入進(jìn)數(shù)據(jù)庫中,這種攻擊危害性很大,因?yàn)槿绻W(wǎng)站訪問量很大的話,就會導(dǎo)致大量正常訪問頁面的用戶都受到攻擊。
比如帶有評論功能的網(wǎng)站,如果我在評論框輸入以下內(nèi)容
如果前后端沒有做好相應(yīng)的防御,這段評論就會被存儲進(jìn)數(shù)據(jù)庫中,這樣每個(gè)打開該頁面的用戶都會被攻擊到。這種便是持久型攻擊的一個(gè)例子。
相比于持久型攻擊,非持久型攻擊的危害就小的多了。一般是通過修改URL參數(shù) 的方式加入攻擊代碼,誘導(dǎo)用戶訪問鏈接從而進(jìn)行攻擊。
舉個(gè)例子,如果頁面需要從 URL 中獲取某些參數(shù)作為內(nèi)容的話,不經(jīng)過過濾就會導(dǎo)致攻擊代碼被執(zhí)行。
<!-- http://www.domain.com?name=<script>alert(1)</script> -->
<div>{{name}}</div>
但是對于這種攻擊方式來說,如果用戶使用 Chrome 這類瀏覽器的話,瀏覽器就能自動幫助用戶防御攻擊。但是我們不能因此就不防御此類攻擊了,因?yàn)槲也荒艽_保用戶都使用了該類瀏覽器。
知道了XSS攻擊者是如何對我們的網(wǎng)站進(jìn)行攻擊的,那么我們該如何去做出相應(yīng)的防御呢?
通常可以通過轉(zhuǎn)義字符和CSP的方式進(jìn)行防御。
轉(zhuǎn)義字符
首先,對于用戶的輸入應(yīng)該是永遠(yuǎn)不信任的。最普遍的做法就是轉(zhuǎn)義輸入輸出的內(nèi)容,對于引號、尖括號、斜杠進(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>')
但是對于顯示富文本來說,顯然不能通過上面的辦法來轉(zhuǎn)義所有字符,因?yàn)檫@樣會把需要的格式也過濾掉。對于這種情況,通常采用白名單過濾的辦法,當(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><script>alert("xss");</script>
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:
1.設(shè)置 HTTP Header 中的 Content-Security-Policy
2.設(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://*
可設(shè)置的更多屬性大家可以通過查閱 MDN的 文檔 去設(shè)置。
另附上知乎上關(guān)于 CSP 的回答。 Content Security Policy (CSP) 是什么?為什么它能抵御 XSS 攻擊?
CSRF
CSRF(Cross-site request forgery),中文名稱:跨站請求偽造,也被稱為:one click attack/session riding,縮寫為:CSRF/XSRF。原理就是攻擊者構(gòu)造出一個(gè)后端請求地址,誘導(dǎo)用戶點(diǎn)擊或者通過某些途徑自動發(fā)起請求。如果用戶是在登錄狀態(tài)下的話,后端就以為是用戶在操作,從而進(jìn)行相應(yīng)的邏輯。
CSRF的攻擊思想如下圖所示:
舉個(gè)例子,假設(shè)網(wǎng)站中有一個(gè)通過 GET 請求提交用戶評論的接口,那么攻擊者就可以在釣魚網(wǎng)站中加入一個(gè)圖片,圖片的地址就是評論接口。
<img src="http://www.domain.com/xxx?comment='attack'"/>
那么你是否會想到使用 POST 方式提交請求是不是就沒有這個(gè)問題了呢?其實(shí)并不是,使用這種方式也不是百分百安全的,攻擊者同樣可以誘導(dǎo)用戶進(jìn)入某個(gè)頁面,在頁面中通過表單提交 POST 請求。
防范CSRF攻擊可以遵循以下幾種規(guī)則:
- GET 請求不對數(shù)據(jù)進(jìn)行修改
- 不讓第三方網(wǎng)站訪問到用戶 Cookie
- 阻止第三方網(wǎng)站請求接口
- 請求時(shí)附帶驗(yàn)證信息,比如驗(yàn)證碼或者 Token
SameSite
可以對 Cookie 設(shè)置 SameSite 屬性。該屬性表示 Cookie 不隨著跨域請求發(fā)送,可以很大程度減少 CSRF 的攻擊,但是該屬性目前并不是所有瀏覽器都兼容。
驗(yàn)證 Referer
對于需要防范 CSRF 的請求,我們可以通過驗(yàn)證 Referer 來判斷該請求是否為第三方網(wǎng)站發(fā)起的。
Token
服務(wù)器下發(fā)一個(gè)隨機(jī) Token,每次發(fā)起請求時(shí)將 Token 攜帶上,服務(wù)器驗(yàn)證 Token 是否有效。
中間人攻擊
中間人攻擊是攻擊方同時(shí)與服務(wù)端和客戶端建立起了連接,并讓對方認(rèn)為連接是安全的,但是實(shí)際上整個(gè)通信過程都被攻擊者控制了。攻擊者不僅能獲得雙方的通信信息,還能修改通信信息。
通常來說不建議使用公共的 Wi-Fi,因?yàn)楹芸赡芫蜁l(fā)生中間人攻擊的情況。如果你在通信的過程中涉及到了某些敏感信息,就完全暴露給攻擊方了。
以上就是整理的一些web安全問題和防御策略,安全是個(gè)極大的問題和方向,需要我們開發(fā)人員不懈的努力共同去解決。如果大家有什么更好的見解,歡迎在評論中一起討論。