一、XSS攻擊
1、概念
? Cross-Site Scripting(跨站腳本攻擊)簡稱 XSS,是一種代碼注入攻擊。攻擊者通過在目標(biāo)網(wǎng)站上注入惡意腳本,使之在用戶的瀏覽器上運(yùn)行。利用這些惡意腳本,攻擊者可獲取用戶的敏感信息如 Cookie、SessionID 等,進(jìn)而危害數(shù)據(jù)安全。
為了和 CSS 區(qū)分,這里把攻擊的第一個字母改成了 X,于是叫做 XSS。
XSS 的本質(zhì)是:惡意代碼未經(jīng)過濾,與網(wǎng)站正常的代碼混在一起;瀏覽器無法分辨哪些腳本是可信的,導(dǎo)致惡意腳本被執(zhí)行。
而由于直接在用戶的終端執(zhí)行,惡意代碼能夠直接獲取用戶的信息,或者利用這些信息冒充用戶向網(wǎng)站發(fā)起攻擊者定義的請求。
在部分情況下,由于輸入的限制,注入的惡意腳本比較短。但可以通過引入外部的腳本,并由瀏覽器執(zhí)行,來完成比較復(fù)雜的攻擊策略。
2、不可信內(nèi)容來源
? 不僅僅是業(yè)務(wù)上的“用戶的 UGC 內(nèi)容”可以進(jìn)行注入,包括 URL 上的參數(shù)等都可以是攻擊的來源。在處理輸入時(shí),以下內(nèi)容都不可信:
- 來自用戶的 UGC 信息 (用戶生成內(nèi)容,即用戶原創(chuàng)內(nèi)容。)
- 來自第三方的鏈接
- URL 參數(shù)
- POST 參數(shù)
- Referer (可能來自不可信的來源,header的一部分,用來獲取該網(wǎng)頁是從哪個頁面鏈接過來的)
- Cookie (可能來自其他子域注入)
3、XSS分類
根據(jù)攻擊的來源,XSS 攻擊可分為存儲型、反射型和 DOM 型三種。
| 類型 | 存儲區(qū)* | 插入點(diǎn)* |
|---|---|---|
| 存儲型 XSS | 后端數(shù)據(jù)庫 | HTML |
| 反射型 XSS | URL | HTML |
| DOM 型 XSS | 后端數(shù)據(jù)庫/前端存儲/URL | 前端 JavaScript |
- 存儲區(qū):惡意代碼存放的位置。
- 插入點(diǎn):由誰取得惡意代碼,并插入到網(wǎng)頁上。
(1)存儲型 XSS
存儲型 XSS 的攻擊步驟:
- 攻擊者將惡意代碼提交到目標(biāo)網(wǎng)站的數(shù)據(jù)庫中。
- 用戶打開目標(biāo)網(wǎng)站時(shí),網(wǎng)站服務(wù)端將惡意代碼從數(shù)據(jù)庫取出,拼接在 HTML 中返回給瀏覽器。
- 用戶瀏覽器接收到響應(yīng)后解析執(zhí)行,混在其中的惡意代碼也被執(zhí)行。
- 惡意代碼竊取用戶數(shù)據(jù)并發(fā)送到攻擊者的網(wǎng)站,或者冒充用戶的行為,調(diào)用目標(biāo)網(wǎng)站接口執(zhí)行攻擊者指定的操作。
這種攻擊常見于帶有用戶保存數(shù)據(jù)的網(wǎng)站功能,如論壇發(fā)帖、商品評論、用戶私信等。
(2)反射型 XSS
反射型 XSS 的攻擊步驟:
- 攻擊者構(gòu)造出特殊的 URL,其中包含惡意代碼。
- 用戶打開帶有惡意代碼的 URL 時(shí),網(wǎng)站服務(wù)端將惡意代碼從 URL 中取出,拼接在 HTML 中返回給瀏覽器。
- 用戶瀏覽器接收到響應(yīng)后解析執(zhí)行,混在其中的惡意代碼也被執(zhí)行。
- 惡意代碼竊取用戶數(shù)據(jù)并發(fā)送到攻擊者的網(wǎng)站,或者冒充用戶的行為,調(diào)用目標(biāo)網(wǎng)站接口執(zhí)行攻擊者指定的操作。
反射型 XSS 跟存儲型 XSS 的區(qū)別是:存儲型 XSS 的惡意代碼存在數(shù)據(jù)庫里,反射型 XSS 的惡意代碼存在 URL 里。
反射型 XSS 漏洞常見于通過 URL 傳遞參數(shù)的功能,如網(wǎng)站搜索、跳轉(zhuǎn)等。
由于需要用戶主動打開惡意的 URL 才能生效,攻擊者往往會結(jié)合多種手段誘導(dǎo)用戶點(diǎn)擊。
POST 的內(nèi)容也可以觸發(fā)反射型 XSS,只不過其觸發(fā)條件比較苛刻(需要構(gòu)造表單提交頁面,并引導(dǎo)用戶點(diǎn)擊),所以非常少見。
(3)DOM 型 XSS
DOM 型 XSS 的攻擊步驟:
- 攻擊者構(gòu)造出特殊的 URL,其中包含惡意代碼。
- 用戶打開帶有惡意代碼的 URL。
- 用戶瀏覽器接收到響應(yīng)后解析執(zhí)行,前端 JavaScript 取出 URL 中的惡意代碼并執(zhí)行。
- 惡意代碼竊取用戶數(shù)據(jù)并發(fā)送到攻擊者的網(wǎng)站,或者冒充用戶的行為,調(diào)用目標(biāo)網(wǎng)站接口執(zhí)行攻擊者指定的操作。
DOM 型 XSS 跟前兩種 XSS 的區(qū)別:DOM 型 XSS 攻擊中,取出和執(zhí)行惡意代碼由瀏覽器端完成,屬于前端 JavaScript 自身的安全漏洞,而其他兩種 XSS 都屬于服務(wù)端的安全漏洞。
4、XSS攻擊的預(yù)防
XSS 攻擊有兩大要素:
- 攻擊者提交惡意代碼。
- 瀏覽器執(zhí)行惡意代碼。
(1)、輸入過濾
? 在用戶提交時(shí),由前端過濾輸入,然后提交到后端。這樣做并不能保證安全,一旦攻擊者繞過前端過濾,直接構(gòu)造請求,就可以提交惡意代碼了。
? 后端在寫入數(shù)據(jù)庫前,對輸入進(jìn)行過濾,然后把“安全的”內(nèi)容,返回給前端。也有問題如果是通過ajax獲取數(shù)據(jù)展示,保存的時(shí)候有需要轉(zhuǎn)譯的字符,客戶端顯示就會亂碼。
當(dāng)然,對于明確的輸入類型,例如數(shù)字、URL、電話號碼、郵件地址等等內(nèi)容,進(jìn)行輸入過濾還是必要的。
既然輸入過濾并非完全可靠,我們就要通過“防止瀏覽器執(zhí)行惡意代碼”來防范 XSS。這部分分為兩類:
- 防止 HTML 中出現(xiàn)注入。
- 防止 JavaScript 執(zhí)行時(shí),執(zhí)行惡意代碼。
(2)、預(yù)防存儲型和反射型 XSS 攻擊
存儲型和反射型 XSS 都是在服務(wù)端取出惡意代碼后,插入到響應(yīng) HTML 里的,攻擊者刻意編寫的“數(shù)據(jù)”被內(nèi)嵌到“代碼”中,被瀏覽器所執(zhí)行。
預(yù)防這兩種漏洞,有兩種常見做法:
- 改成純前端渲染,把代碼和數(shù)據(jù)分隔開。
- 對 HTML 做充分轉(zhuǎn)義。
(3)、預(yù)防 DOM 型 XSS 攻擊
DOM 型 XSS 攻擊,實(shí)際上就是網(wǎng)站前端 JavaScript 代碼本身不夠嚴(yán)謹(jǐn),把不可信的數(shù)據(jù)當(dāng)作代碼執(zhí)行了。
在使用 .innerHTML、.outerHTML、document.write() 時(shí)要特別小心,不要把不可信的數(shù)據(jù)作為 HTML 插到頁面上,而應(yīng)盡量使用 .textContent、.setAttribute() 等。
如果用 Vue/React 技術(shù)棧,并且不使用 v-html/dangerouslySetInnerHTML 功能,就在前端 render 階段避免 innerHTML、outerHTML 的 XSS 隱患。
DOM 中的內(nèi)聯(lián)事件監(jiān)聽器,如 location、onclick、onerror、onload、onmouseover 等,`` 標(biāo)簽的 href 屬性,JavaScript 的 eval()、setTimeout()、setInterval() 等,都能把字符串作為代碼運(yùn)行。如果不可信的數(shù)據(jù)拼接到字符串中傳遞給這些 API,很容易產(chǎn)生安全隱患,請務(wù)必避免。
二、CSRF攻擊
1、概念
Cross-site request forgery, 跨站請求偽造。是指黑客引誘用戶打開黑客的網(wǎng)站,在黑客的網(wǎng)站中,利用用戶的登錄狀態(tài)發(fā)起跨站請求。
攻擊者盜用了你的身份,以你的名義向第三方網(wǎng)站發(fā)送惡意請求。 CRSF能做的事情包括利用你的身份發(fā)郵件、發(fā)短信、進(jìn)行交易轉(zhuǎn)賬等,甚至盜取你的賬號。
2、防止CSRF
黑客發(fā)起CSRF攻擊的條件
- 目標(biāo)網(wǎng)站一定要有CSRF漏洞,黑客破解了服務(wù)器的接口
- 用戶登錄過目標(biāo)網(wǎng)站,并且瀏覽器保存目標(biāo)網(wǎng)站的登錄狀態(tài)
- 用戶在同一瀏覽器下以某種方式打開了黑客的網(wǎng)站或者是攻擊的鏈接
CSRF攻擊與XSS攻擊不同,CSRF攻擊不會往頁面內(nèi)注入惡意腳本,因此黑客是無法通過CSRF攻擊來獲取用戶頁面數(shù)據(jù)的,所以主要由服務(wù)器來做預(yù)防。
主要有以下幾種方式:
(1)、充分利用好cookie的SameSite屬性
SameSite選項(xiàng)通常由Strict、Lax和None三個值
- Strict最為嚴(yán)格,如果cookie設(shè)置了Strict,那么瀏覽器會完全禁止第三方Cookie。
- Lax相對寬松一點(diǎn),在跨站點(diǎn)的情況下,從第三方站點(diǎn)的鏈接打開和從第三方站點(diǎn)提交Get的表單都會攜帶cookie.但是如果在第三方站點(diǎn)中使用Post方法或者通過img、iframe等標(biāo)簽加載的URL,都不會攜帶Cookie。
- None, 任何情況下都會發(fā)送Cookie。
但是現(xiàn)在大部分的網(wǎng)站靜態(tài)資源都放在單獨(dú)的域名下,所以通過設(shè)置Cookie的SameSite為Strict、Lax是不能正常運(yùn)行的,所以這個方法只適用靜態(tài)資源跟服務(wù)器接口在同一個站點(diǎn)下的網(wǎng)站。
(2)、驗(yàn)證請求的來源站點(diǎn)
在服務(wù)器端驗(yàn)證請求的來源站點(diǎn)。因?yàn)镃SRF攻擊大多數(shù)都是來自第三方站點(diǎn)。
通過http請求頭中的Referer和Origin屬性
- referer屬性
記錄了該http請求的來源地址,但有些場景不適合將來源URL暴露給服務(wù)器,所以可以設(shè)置不用上傳,并且referer屬性是可以修改的,所以在服務(wù)器端校驗(yàn)referer屬性并沒有那么可靠
- origin屬性
通過XMLHttpRequest、Fetch發(fā)起的跨站請求或者Post方法發(fā)送請求時(shí),都會帶上origin,所以服務(wù)器可以優(yōu)先判斷Origin屬性,再根據(jù)實(shí)際情況判斷是否使用referer判斷。
(3)、CSRF Token
除了上面兩個方法之外,還可以使用CSRF Token來驗(yàn)證。
- 在瀏覽器向服務(wù)器發(fā)起請求時(shí),服務(wù)器生成一個CSRF Token(字符串)發(fā)送給瀏覽器,然后將該字符串放入頁面中
- 瀏覽器請求時(shí)(如表單提交)需要帶上這個CSRF Token。服務(wù)器收到請求后,驗(yàn)證CSRF是否合法,如果不合法拒絕即可。