前端安全-常見的攻擊以及防禦
一、基礎知識
1、XSS(Cross Site Scripting)跨站指令碼攻擊
(1)原理:頁面渲染的資料中包含可執行的指令碼
(2)攻擊的基本型別:反射型(url引數直接注入)和儲存型(儲存到DB後讀取時注入)
(3)注入點:HTML節點內的內容(text);HTML中DOM元素的屬性;Javascript程式碼;富文字
//HTML節點內容注入 <div><script>alert(1);</script></div> //DOM屬性注入 <img src='/images/1.png' onerror='alert(1);'> //javascript程式碼 <script> var a = '1';alert(1);'' </script> //富文字是html標籤,文字,以及樣式的集合,很容易實現HTML節點內容注入和DOM屬性注入,有被攻擊的風險
2、CSRF(Cross Site Request Forgy)跨站請求偽造
原理:在第三方網站向本網站發起請求(如圖)
(1)使用者在a站前端頁面發起登入(身份認證)請求
(2)a站後端確認身份,登入成功,cookie中存在使用者的身份認證資訊
(3)b站前端頁面向a站後端發起請求,帶著a站的cookie資訊(身份認證資訊),請求成功
綜上,可以清楚的知道,只要使用者訪問了b站的前端頁面,b站就可以在使用者完全不知道的情況下,帶著a站的使用者登入態(cookie)向a站發起請求
3、點選劫持
原理:第三方網站通過iframe內嵌某一個網站,並且將iframe設定為透明不可見,將其覆蓋在其他經過偽裝的DOM上,偽裝的可點選DOM(按鈕等)與實際內嵌網站的可點選DOM位置相同,當用戶點選偽裝的DOM時,實際上點選的是iframe中內嵌的網頁的DOM從而觸發請求操作
特點:使用者自己做了點選操作;使用者毫不知情;
二、如何防禦
1、XSS攻擊防禦
(1)瀏覽器自帶防禦機制,主要應對反射型攻擊(HTML內容或屬性):http響應頭中自動新增x-xss-protection,值為0(關閉),1(開啟),預設開啟
(2)對特定字元做轉義:內容注入替換尖括號( < => < > => > ) 屬性注入替換單引號或雙引號( " => " ' => ' )
(3)CSP(Content Security Policy)內容安全策略:用於指定哪些內容可執行
//我們可以在http響應頭中設定Content-Security-Policy //圖片可以從任何地方載入(注意 "*" 萬用字元) //多媒體檔案僅允許從 media1.com 和 media2.com 載入(不允許從這些站點的子域名) //可執行指令碼僅允許來自於userscripts.example.com Content-Security-Policy: default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com //同時meta中也支援設定Content-Security-Policy <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
2、CSRF攻擊防禦:
CSRF的發生有幾個特點,b站傳送的請求帶著a站的cookie資訊; b站傳送請求不經過a站的前端;http請求頭中的referer為b站。我們可以從這些特點入手,思考防禦的辦法
(1)禁止第三方網站攜帶本網站的cookie資訊:設定same-site屬性,same-site屬性有兩個值,Strict(所有的第三方請求都不能攜帶本網站的cookie)和Lax(連結可以,但是form表單提交和ajax請求不行)
(2)本網站前端頁面新增驗證資訊:使用驗證碼或者新增token驗證
驗證碼:當發起請求時,前端需要輸入本網站頁面的驗證碼資訊,後端對驗證碼進行驗證,驗證碼正確才會進行相關操作(存取資料等)
token驗證:a站前端將token存在當前頁面中(比如表單中的input隱藏域,meta標籤或者任何一個dom的屬性)和cookie中,當請求a站後端的時候,引數中帶上這個token欄位,a站後端將引數中的token和cookie中的token做對比, 相同則驗證通過,不同則請求不合法
不管是驗證碼還是token驗證,原理都是一樣的,在a站前端頁面加入驗證,當第三方網站請求a站後端時,即使能攜帶a站cookie,但是因為沒有經過a站的前端頁面從而拿不到驗證資訊,也會導致請求失敗。
兩種防禦的方法也有區別,驗證碼需要使用者去填寫,從而增加了使用者使用網站的複雜度,而token驗證在使用者無感知的情況下就可以實現,不影響使用者體驗。我個人理解,驗證碼驗證一般使用在需要提高使用者認知的場景,比如,登入多次失敗,修改個人資訊(使用者名稱,密碼,繫結手機號等等),而一些獲取商品列表資訊,搜尋等介面,使用token比較合理。可以看看我們平時使用的這些網站,作參考~
(3)referer驗證:禁止來自第三方的請求
(4)使用post請求:有一個說法是“post請求比get請求更安全”,那這種說法對不對呢?實際上這種說法並不準確,對於CSRF攻擊來講,不管是post還是get都能實現攻擊,區別只是post請求攻擊方需要構造一個form表單才可以發起請求,比get請求(img的src, a標籤的href等等)的攻擊方式複雜了一些,但是並不能有效的阻止攻擊。
3、點選劫持攻擊防禦
(1)Javascript禁止內嵌:當網頁沒有被使用iframe內嵌時,top和window是相等的;當網頁被內嵌時,top和window是不相等的;可以在本網站的頁面中新增如下判斷:
<script> if (top.location != window.location) { //如果不相等,說明使用了iframe,可進行相關的操作 } </script>
但是這種方式並不是萬能的,因為iframe標籤中的屬性sandbox屬性是可以禁用內嵌網頁的指令碼的:
<iframe sandbox='allow-forms' src='...'></iframe>
(2)設定http響應頭 X-Frame-Options:有三個值 DENY(禁止內嵌) SAMEORIGIN(只允許同域名頁面內嵌) ALLOW-FROM(指定可以內嵌的地址)
能在所有的web伺服器端預設好X-Frame-Options欄位值是最理想的狀態。
(3)一些輔助手段,比如新增驗證碼,提高使用者的防範意識
三、總結
本文旨在對平時瞭解到的知識做一些總結和記錄,方便查閱和複習,描述不當之處,歡迎指出。
文中有些部分並未深入展開,比如iframe的sandbox屬性(只適用於內嵌網頁是form提交的情況,如果所有的請求都通過ajax來請求,而js指令碼又被禁用的話,那就沒辦法實現點選劫持了),有一些內容需要你自己動腦思考。
後續可能還會有補充,比如SQL注入部分,總之,今天先這樣