是個前端都應該了解的web安全知識(附一些較新的防范方法)
前言
對于很多剛開始工作的前端而言,web安全似乎是一個說不清道不明的東西。關于web安全,認真學習總結一下,其實就會發(fā)現(xiàn)它不難。本文通過面試提問的形式來一一進行總結,希望對于各位小伙伴理解web安全有所幫助。
1.前端有哪些攻擊方式?
目前常見的web攻擊方式主要分為:XSS攻擊、CSRF攻擊、點擊劫持。
2.什么是XSS攻擊?XSS攻擊有哪幾種類型?如何防范XSS攻擊?
2.1 什么是XSS攻擊?
XSS(Cross-Site Scripting,跨站腳本攻擊)是一種代碼注入攻擊。攻擊者在目標網站上注入惡意代碼,當被攻擊者登錄網站時就會執(zhí)行這些惡意代碼。這些腳本可以讀取cookie、session tokens或者其他敏感的網站信息,對用戶進行釣魚欺詐,甚至發(fā)起蠕蟲攻擊等。
XSS的本質是:惡意代碼未經過濾,與網站正常的代碼混在一起,而瀏覽器是無法辨別哪些腳本是惡意的,導致惡意腳本被執(zhí)行。由于直接在用戶的終端執(zhí)行,惡意代碼能夠直接獲取用戶的信息,利用這些信息冒充用戶向網站發(fā)起攻擊者定義的請求。
舉個簡單的例子:
click mefunctiondoAttack(){while(true) {? ? ? ? ? ? ? ? alert('u are under attack');? ? ? ? ? ? }? ? ? ? }復制代碼
這里在a標簽里注入一個腳本,當用戶點擊后,瀏覽器會一直彈窗。在真實的網站攻擊中,攻擊者通過注入的這個腳本,它可以隨意干壞事,這樣是非常危險的。因為前端你用JavaScript進行的操作,它也一樣能,想想是不是覺得很恐怖?
2.2 XSS攻擊有哪幾種類型?
根據攻擊的來源,XSS可以分為存儲型(持久型)、反射型(非持久型)、DOM型三種。
反射型XSS
當用戶點擊一個惡意鏈接,或者提交一個表單,或者進入一個惡意網站時,注入腳本進入被攻擊者的網站。Web服務器將注入一個腳本,比如一個錯誤信息、搜索結果等,未進行過濾直接返回到用戶的瀏覽器上。
反射型XSS的攻擊步驟:
攻擊者構造出特殊的url,其中包含惡意代碼。
用戶打開帶有惡意代碼的url時,網站服務端將惡意代碼從url取出,拼接在HTML中返回給用戶。
用戶瀏覽器接收到響應后解析執(zhí)行,混在其中的惡意代碼也被執(zhí)行。
惡意代碼竊取用戶數據并發(fā)送到攻擊者的網站,或者冒充用戶的行為,調用目標網站接口執(zhí)行攻擊者指定的操作。
反射型 XSS 漏洞常見于通過 URL 傳遞參數的功能,如網站搜索、跳轉等。由于需要用戶主動打開惡意的 URL 才能生效,攻擊者往往會結合多種手段誘導用戶點擊。 注意Chrome 和 Safari 能夠檢測到 url 上的xss攻擊,將網頁攔截掉,但是其它瀏覽器不行,如Firefox。 如果不希望被前端拿到cookie,后端可以設置 httpOnly (不過這不是 XSS攻擊 的解決方案,只能降低受損范圍)。
DOM型XSS
DOM 型 XSS 攻擊,實際上就是前端 JavaScript 代碼不夠嚴謹,把不可信的內容插入到了頁面。在使用 .innerHTML、.outerHTML、.appendChild、document.write()等API時要特別小心,不要把不可信的數據作為 HTML 插到頁面上,盡量使用 .innerText、.textContent、.setAttribute() 等。
DOM 型 XSS 的攻擊步驟:
攻擊者構造出特殊數據,其中包含惡意代碼。
用戶瀏覽器執(zhí)行了惡意代碼。
惡意代碼竊取用戶數據并發(fā)送到攻擊者的網站,或者冒充用戶的行為,調用目標網站接口執(zhí)行攻擊者指定的操作。
DOM 型 XSS 攻擊中,取出和執(zhí)行惡意代碼由瀏覽器端完成,屬于前端 JavaScript 自身的安全漏洞。
存儲型XSS
惡意腳本永久存儲在目標服務器上。當瀏覽器請求數據時,腳本從服務器傳回并執(zhí)行,影響范圍比反射型和DOM型XSS更大。存儲型XSS攻擊的原因仍然是沒有做好數據過濾:前端提交數據至服務端時,沒有做好過濾;服務端在接受到數據時,在存儲之前,沒有做過濾;前端從服務端請求到數據,沒有過濾輸出。
存儲型 XSS 的攻擊步驟:
攻擊者將惡意代碼提交到目標網站的數據庫中。
用戶打開目標網站時,網站服務端將惡意代碼從數據庫取出,拼接在 HTML 中返回給瀏覽器。
用戶瀏覽器接收到響應后解析執(zhí)行,混在其中的惡意代碼也被執(zhí)行。
惡意代碼竊取用戶數據并發(fā)送到攻擊者的網站,或者冒充用戶的行為,調用目標網站接口執(zhí)行攻擊者指定的操作。
這種攻擊常見于帶有用戶保存數據的網站功能,如論壇發(fā)帖、商品評論、用戶私信等。
2.3 如何防范XSS攻擊?
2.3.1 防范反射型XSS攻擊
app.get('/welcome',function(req, res){//對查詢參數進行編碼,避免反射型 XSS攻擊res.send(`${encodeURIComponent(req.query.type)}`); });復制代碼
2.3.2 防范DOM型XSS攻擊
防范 DOM 型 XSS 攻擊的核心就是對輸入內容進行轉義(DOM 中的內聯(lián)事件監(jiān)聽器和鏈接跳轉都能把字符串作為代碼運行,需要對其內容進行檢查)。
對于url鏈接(例如圖片的src屬性),那么直接使用 encodeURIComponent 來轉義。
非url,我們可以這樣進行編碼:
functionencodeHtml(str){if(!str)return'';returnstr.replace(/"/g,'"')? ? ? ? ? ? .replace(/'/g,''')? ? ? ? ? ? .replace(/</g,'<')? ? ? ? ? ? .replace(/>/g,'>')? ? ? ? ? ? .replace(/&/g,'&');}復制代碼
2.3.3 防范存儲型XSS攻擊
前端數據傳遞給服務器之前,先轉義/過濾(防范不了抓包修改數據的情況)
服務器接收到數據,在存儲到數據庫之前,進行轉義/過濾
前端接收到服務器傳遞過來的數據,在展示到頁面前,先進行轉義/過濾
2.3.4 CSP方式
CSP的全稱是Content Security Policy,即內容安全策略。
CSP 的主要目標是減少和報告 XSS 攻擊 ,XSS 攻擊利用了瀏覽器對于從服務器所獲取的內容的信任。惡意腳本在受害者的瀏覽器中得以運行,因為瀏覽器信任其內容來源,即使有的時候這些腳本并非來自于它本該來的地方。
CSP通過指定有效域——即瀏覽器認可的可執(zhí)行腳本的有效來源——使服務器管理者有能力減少或消除XSS攻擊所依賴的載體。一個CSP兼容的瀏覽器將會僅執(zhí)行從白名單域獲取到的腳本文件,忽略所有的其他腳本 (包括內聯(lián)腳本和HTML的事件處理屬性)。
作為一種終極防護形式,始終不允許執(zhí)行腳本的站點可以選擇全面禁止腳本執(zhí)行。
如何使用CSP?
你可以使用 Content-Security-Policy HTTP頭部 來指定你的策略,像這樣:
Content-Security-Policy: policy
policy參數是一個包含了各種描述你的CSP策略指令的字符串。
比如一個網站管理者想要所有內容均來自站點的同一個源 (不包括其子域名):
Content-Security-Policy: default-src 'self'
詳細的用法可以參考MDN,內容安全策略( CSP )
3. 什么是CSRF攻擊?如何防范?
3.1 什么是CSRF攻擊?
CSRF(Cross-site request forgery)跨站請求偽造:攻擊者誘導受害者進入第三方網站,在第三方網站中,向被攻擊網站發(fā)送跨站請求。利用受害者在被攻擊網站已經獲取的注冊憑證,繞過后臺的用戶驗證,達到冒充用戶對被攻擊的網站執(zhí)行某項操作的目的。
典型的CSRF攻擊流程:
受害者登錄A站點,并保留了登錄憑證(Cookie)。
攻擊者誘導受害者訪問了站點B。
站點B向站點A發(fā)送了一個請求,瀏覽器會默認攜帶站點A的Cookie信息。
站點A接收到請求后,對請求進行驗證,并確認是受害者的憑證,誤以為是無辜的受害者發(fā)送的請求。
站點A以受害者的名義執(zhí)行了站點B的請求。
攻擊完成,攻擊者在受害者不知情的情況下,冒充受害者完成了攻擊。
3.2 如何防范CSRF攻擊?
3.2.1 主流方式
添加驗證碼(體驗不好)
判斷請求的來源:檢測Referer(并不安全,Referer可以被更改)
使用Token(主流)
CSRF攻擊之所以能夠成功,是因為服務器誤把攻擊者發(fā)送的請求當成了用戶自己的請求。那么我們可以要求所有的用戶請求都攜帶一個CSRF攻擊者無法獲取到的Token。服務器通過校驗請求是否攜帶正確的Token,來把正常的請求和攻擊的請求區(qū)分開。跟驗證碼類似,只是用戶無感知。
服務端給用戶生成一個token,加密后傳遞給用戶
用戶在提交請求時,需要攜帶這個token
服務端驗證token是否正確
3.2.2 啟用cookies的SameSite屬性
SameSite的屬性值有3個:
strict: Cookie只會在第一方上下文中發(fā)送,不會與第三方網站發(fā)起的請求一起發(fā)送。
lex: Cookies允許與頂級一起發(fā)送,并將與第三方網站發(fā)起的GET請求一起發(fā)送。這是瀏覽器中的默認值。
none: Cookie將在所有上下文中發(fā)送,即允許跨域發(fā)送。
注意:以前None是默認值,但最近的瀏覽器版本將Lax作為默認值,以便對某些類型的跨站點請求偽造(csrf)攻擊具有相當強的防御能力。
4. 什么是點擊劫持攻擊?如何防范?
4.1 什么是點擊劫持攻擊?
點擊劫持是指在一個Web頁面中隱藏了一個透明的iframe,用外層假頁面誘導用戶點擊,實際上是在隱藏的frame上觸發(fā)了點擊事件進行一些用戶不知情的操作。
典型的點擊劫持攻擊流程:
攻擊者構建了一個非常有吸引力的網頁
將被攻擊的頁面放置在當前頁面的 iframe 中
使用樣式將 iframe 疊加到非常有吸引力內容的上方
將iframe設置為100%透明
你被誘導點擊了網頁內容,你以為你點擊的是***,而實際上,你成功被攻擊了。
4.2 如何防范點擊劫持?
4.2.1 frame busting
if(top.location !==window.location) {? ? top.location =window.location;}復制代碼
需要注意的是: HTML5中iframe的 sandbox 屬性、IE中iframe的security 屬性等,都可以限制iframe頁面中的JavaScript腳本執(zhí)行,從而可以使得 frame busting 失效。
4.2.2 X-FRAME-OPTIONS
X-FRAME-OPTIONS是微軟提出的一個http頭,專門用來防御利用iframe嵌套的點擊劫持攻擊。并且在IE8、Firefox3.6、Chrome4以上的版本均能很好的支持??梢栽O置為以下值:
DENY: 拒絕任何域加載
SAMEORIGIN: 允許同源域下加載
ALLOW-FROM: 可以定義允許frame加載的頁面地址
5. 總結
以上談到了3種web攻擊方式,分別是XSS攻擊、CSRF攻擊、點擊劫持,并給出了具體的防范方式。當然,只有在實踐中不斷地使用這些技術,才能對web安全有更深刻的認知。