大家好,我是沐華。最近面了一些前端,發現每次問到安全相關的問題,一些面試者只能説上來 XSS、CSRF、中間人攻擊,就沒了,於是寫了這篇文章,總結了前端安全相關的點,給大家查缺補漏
瀏覽器
XSS
XSS 攻擊是一種代碼注入攻擊,通過惡意注入腳本在瀏覽器運行,然後盜取用户信息。本質上其實是因為網站沒有過濾惡意代碼,與正常代碼混在一起之後,瀏覽器沒有辦法分辨哪些是可信的,然後導致惡意代碼也被執行
結果是可能會導致:頁面數據或用户信息被竊取、偽造登錄窗口或在頁面生成浮窗廣告、監聽鍵盤事件竊取賬號密碼、流量被支持到其他網站等
XSS 攻擊有三種類型:
- 存儲型:通過輸入框把惡意代碼提交到網站數據庫中,然後比如在顯示評論的頁面就會從數據獲取,並直接執行
- 反射型:和存儲型不同的是不會儲存在服務器裏。比如打開包含帶惡意腳本的鏈接,當打開後會向服務器請求後,服務器會獲取URL中的數據然後拼接在HTML上返回,然後執行
- 基於DOM型:是通過一些劫持手段,在頁面資源傳輸過程中劫持並修改頁面的數據,插入惡意代碼
防範:比如對輸入框內容進行過濾和用轉義符進行轉碼、添加白名單、關閉 Cookie 訪問權限、使用驗證碼防止腳本偽裝成用户執行操作等
CSRF
CSRF 就是跨站請求偽造攻擊,主要就是利用用户的登錄狀態發起跨站請求
比如郵箱裏的亂七八糟的鏈接,打開鏈接的時候郵箱肯定是處於登錄狀態,然後黑客就可以用這個登錄狀態,偽造帶有正確 Cookie 的 http 請求,直接繞過後台的登錄驗證,然後冒充用户執行一些操作,本質是利用 Cookie 在同源請求中攜帶發送給服務器的特點,來實現冒充用户
發起 CSRF 攻擊有幾個必要條件:
- 目標網站一定要有
CSRF漏洞 - 用户登錄過目標網站,並且瀏覽器保存了登錄狀態
- 需要用户主動打開第三方站點
CSRF 攻擊也有三種類型:
- 自動發GET類型:比如
img或iframe標籤等,當用户打開這個網站時會自動發起帶Cookie的資源請求 - 自動發POST類型:比如整一個隱藏的
表單,在用户進入頁面的時候自動提交表單 - 誘導鏈接型:就是誘導用户主動點擊鏈接,比如
a標籤
防範:比如 Token 驗證、雙重 Cookie、通過 origin/referer 驗證請求來源等
CSP
CSP 就是白名單,作用是可以禁止加載外域的代碼,禁止外域的提交,只允許本域下的請求表單提交之類的,簡單説就是告訴瀏覽器哪些資源可以加載執行,讓那些真的插入進入的惡意代碼也不會被執行;或者允許向哪些第三方站點提交數據,因為攻擊者竊取信息的根本還是向外域提交
開啓 CSP 的方式有兩種
1. meta
<meta http-equiv="content-security-policy" content="policy">
<meta http-equiv="content-security-policy-report-only" content="policy">
2. http request header
如果不支持 Content-Security-Policy,可以用 X-XSS-Proterction 代替
# 所加載的內容必須來自同源站點
Content-Security-Policy: default-src "self"
# 添加可信域名
Content-Security-Policy: *.baidu.com
# 和上面同理
Content-Security-Policy-Report-Only: policy
HSTS
HSTS 是 HTTP 嚴格傳輸安全協議,作用是強制客户端使用 https 與服務器建立連接,以避免因為 http 而被中間人攻擊
HSTS 設置須添加在請求頭中,如下
Strict-Transport-Security: max-age=12345;includeSubDomains;
參數:
- max-age: 指定該設置過期的時間,單位毫秒
- includeSubDomains: 可選參數,表示所有子域名也必須通過
https訪問 - preload: 可選參數,可以設置一個使用
https的域名列表
設置 HSTS 後,再使用 http 訪問時,只要 max-age 沒有過期,客户端內部會進行跳轉,會出現 307 Redirect Internel 狀態碼,變成 https 後,再訪問請求的資源服務器
X-Frame-Options
X-Frame-Options 是用於控制當前頁面是否可以被嵌入到 iframe 中,以防盜鏈及點擊劫持攻擊
X-Frame-Options 設置須添加在請求頭中,如下
X-Frame-Options: DENY
參數:
- DENY: 不允許,同域名嵌套也不行
- SAMEORIGIN: 允許同域名嵌套
- ALLOW_FORM url: 可以指定允許嵌套訪問的來源
設置 X-Frame-Options 後,可以確保我們的網站沒有被嵌入到別人的站點裏去(以防內容被惡意嵌套,並且在表面加一個透明層,誘導用户點擊),從而避免點擊劫持攻擊及惡意盜鏈
SRI
SRI 指子資源完整性,該方案的作用是確保我們站點的資源文件永遠不會被改變,如果被改變,瀏覽器會拒絕執行
比如我們打包的時候有一個 xxx.js 文件,被 index.html 引用,並上傳 CDN,用户在訪問的時候,會去請求 xxx.js,而這個文件可能被劫持篡改,或者由於網絡等原因,接收到的文件不完整,怎麼辦?
而設置了 SRI 就可以確保當請求的文件被篡改或不完整的時候就拒絕執行該文件,設置如下:
<link href="https://xxx/x.css" intergrity="sha1/asdhfkjasdf">
<script src="https://xxx/x.js" intergrity="sha1/asdhfkjasdf"></script>
標籤上的 intergrity 屬性值的格式是:哈希算法/base64後的哈希值
原理:
打包的時候會根據文件內容生成 hash,並且把 hash 作為 intergrity 屬性注入到標籤上,客户端接收到文件後,根據文件內容生成 hash 與 intergrity 上的進行對比是否一致,如果不一致就會認為是不安全的,拒絕執行
Referrer-Policy
Referrer-Policy 是一種 HTTP 安全方案,用於控制 referer 攜帶策略,用於監管哪些訪問來源信息會在 referer 中發送
注意 referer 實際上是單詞 referrer 的錯誤拼寫。而 Referrer-Policy 這個首部並沒有延續這個錯誤拼寫
開啓 Referrer-Policy 的方式有兩種
1. meta
<meta name="referrer" content="same-origin">
2. http general
Referrer-Policy: same-origin
參數:
- no-referrer:不發送
referer - no-referrer-when-downgrade:默認值,同安全級別發送
referrer並且是完整url,不同安全級別則不發送 - origin:只發送協議、域名、端口,不發送完整
url,比如https://juejin.cn/index.html,會變成https//juejin.cn/ - origin-when-cross-origin:同源才發送完整
url,不同源只發送協議、域名、端口 - same-origin:同源才發送
referer,並且是完整的url - strict-origin:同安全級別和
origin是一樣的,比如https請求https,如https請求http是不同安全級別了,就不發送 - strict-origin-when-cross-origin:同源發送完整
url,同安全級別才發送協議、域名、端口,不同源或不同安全級別不發送referer - unsafe-url:這是最不安全的策略,不管同不同源都發送完整
url
HTTPS
由於 http 是明文傳輸,是不安全的,所以在 http 傳輸過程中信息可能被竊取、偽造、篡改,這種攻擊方式被稱為中間人攻擊
避免中間人攻擊的方法就是用 https,在應用層與傳輸層之間添加一個安全層 TLS,但也不是就絕對安全了
安全層會通過加密算法和公鑰私鑰加密傳遞的數據,好處是即使被劫持,中間人沒有私鑰就拿不到加密生成的隨機數,就無法生成最終密鑰
但問題是:假如一開始就被 DNS 劫持,或者説域名劫持攻擊,拿到的公鑰就是中間人的,中間人解密拿到數據後,再請求實際服務器,拿到服務器公鑰,再把信息發給服務器,這樣不知不覺間信息還是會被竊取
所以,還需要搭配數字證書,來幫我們驗證服務器身份。可 https 還有一個安全問題就是偽造證書的存在,比如
- 比如
CA機構沒有正確校驗申請者的身份而無意簽發了一些錯誤的證書 - 比如
CA機構在利益的驅使下,發放的證書 - 比如冒充或偽造某個域名的擁有者,申請到一張證書,畢竟域名擁有者是無法知曉哪些
CA機構給他簽發了證書,也不知道是否有人冒充他的身份申請了證書的 - ...
而 CA 證書公鑰可信度是靠操作系統裏面預置的 CA 證書公鑰列表來保證的,就像白名單,用户一般也不知道 CA 證書公鑰的真假,那如果有黑客有能力把自己的公鑰放到用户系統的 CA 證書公鑰列表裏,那也可以偽造數字證書放到用户的電腦上,而用户卻無法感知就信任了這個證書,然後你懂的
為了解決證書問題,有一個解決方案,就是證書透明度(CT),能夠審計、監控證書的簽發和使用,一旦發現偽造的證書,可以快速聯繫到 CA 機構,吊銷該證書
使用證書透明度服務就是添加請求頭 Expect-CT 用來告訴瀏覽器期望使用證書透明度服務的,這能更有效的避免中間人攻擊等
但誰也不能説這就有 100% 的絕對安全了,只是現行架構下的這些解決方案,已經大大增加了中間人的攻擊成本,一般都是可以放心的
Node(服務端)
本地文件操作
指由於本地文件操作相關或路徑拼接導致的文件資源泄露,所帶來的安全問題
- 比如提供了一個靜態服務,通過請求的參數 url 來給客户端返回想要資源,而用户手動修改 url 上的路徑卻可以訪問到
- 比如暴露了一個服務或接口也可以操作文件的話,如果對它的校驗不是那麼安全的,就會有攻擊者能訪問到我們的文件,比如 ssh 文件、密碼之類的
預防:express-static、koa-static、resolve-path,都可以解決這個
WebShell
WebShell 是指一種惡意腳本,或者腳本木馬
原理:
利用文件上傳漏洞、SQL注入漏洞等等,把惡意文件放到服務器中,作為後門,然後通過服務器開放的端口+後門獲取服務器的操作權限,比如竊取用户數據、修改權限、文件管理 修改甚至刪除 web 頁面、數據庫管理等等
常見的 WebShell 編寫語言是 jsp、asp、php
攻擊方式:
- 上傳漏洞。網站上有上傳文件的功能,過濾又不嚴,就可以直接把
jsp、asp、php文件直接上傳到服務器 - 上傳文件類型。項目上有添加上傳類型或重命名文件功能的,比如把
WebShell文件重命名成.jpg之類的允許上傳的文件,上傳完成後,再重命名改回如.jsp這樣類型的文件 - 隱藏到合法文件。比如把
php代碼放到jpg文件裏,再使用@運算符防止發生錯誤,或者刪除空格換行等,導致代碼比較混亂,再使用編碼或者加密來隱藏惡意函數等 - 隱藏到日誌。修改發送數據包的頭部,添加
WebShell。 web 服務器一般會保存訪問記錄到Web日誌,如果找到web日誌,且放到可執行目錄下,可能獲得 shell - .....
ReDos
ReDos 就是正則表達式攻擊,利用正則表達式攻擊或者利用開發者正則寫的不規範,而瘋狂佔用服務器資源,造成服務器宕機
正則表達式匹配規則是:會先匹配第一種要能性,每當一次匹配不成功,就會嘗試回溯到上一個字符,看看能不能有其他組合來匹配到這個字符串,比如,匹配 aaa 會向下面這樣匹配
aaa
aa + a
a + aa
a + a + a
再看下圖三條正則表達式執行時間,第一條 0.198ms,第二條 26.445ms,第三條沒有結果,因為跑不完,會一直瘋狂佔用資源
時序攻擊
時序攻擊由於條件非常嚴荷,所以瞭解一下即可,哪怕只能説出時序攻擊這四個字,但知道有這麼回事就比不知道的強
比如攻擊者嘗試 arr = [1,2]、arr = [1,3],發現響應時間幾乎一致,則可以認為第一個數字不是 1,再嘗試 arr = [2,1],依此類推,不斷碰撞嘗試,直到最後碰撞出來真實的 arr
像是對比兩個數組是否相同,下面代碼看似沒什麼問題,業務效果完全能達到,但是在絕對安全層面上是不安全的
當然業務代碼中沒必要這麼嚴苛,因為比如上述代碼上如果還有其他 if else 判斷,就完全沒辦法碰撞出來了
爬蟲
爬蟲就是一種按照一定規則自動抓取資源的程序或者腳本,搜索引擎可以用爬蟲抓取網頁、圖片、視頻、音頻等
對於有一些沒有防範的系統,通過爬蟲,甚至可以把人家會員才能看或者付費下載的資源直接給爬下來,假設網站上有一個 10MB 的文件,使用爬蟲抓取上千上萬次,就會導致網站產生大量出站流量,很可能還會使服務器癱瘓無法訪問了
防範其實主要就是服務端安全校驗的問題,比如設置 robots.txt 文件、比如對請求中的 User Agent 識別和限制,説到底防爬蟲主要是防範這幾個點:ip、origin、referer、request headers
如果沒有併發的去請求去爬蟲的時候,它不會針對 ip 做校驗,只會判斷後面幾個,而如果沒有後幾點就會認為你是不安全的系統,就給爺爬
結語
如果本文對你有一點點幫助,點個贊支持一下吧,你的每一個【贊】都是我創作的最大動力 ^_^
更多前端文章,或者加入前端交流羣,歡迎關注公眾號【沐華説技術】,大家一起共同交流和進步呀