前端安全:XSS攻擊/CSRF攻擊

XSS攻擊

什么是 XSS

Cross-Site Scripting (跨站腳本攻擊)簡稱XSS拔妥,是一種代碼注入攻擊薪者。攻擊者通過在目標(biāo)網(wǎng)站上注入惡意腳本斯棒,使之在用戶的瀏覽器上運(yùn)行许帐。利用這些惡意腳本劳坑,攻擊者可獲取用戶的敏感信息如 Cookie投蝉、SessionID 等窍株,進(jìn)而危害數(shù)據(jù)安全这揣。
所以,網(wǎng)頁上哪些部分會引起XSS攻擊?簡單來說,任何可以輸入的地方都有可能引起,包括URL

XSS 常見的注入方法:

  • HTML 中內(nèi)嵌的文本中穗酥,惡意內(nèi)容以script標(biāo)簽形成注入。
  • 在內(nèi)聯(lián)的 JavaScript中框仔,拼接的數(shù)據(jù)突破了原本的限制(字符串舀武,變量,方法名等)离斩。
  • 在標(biāo)簽屬性中银舱,惡意內(nèi)容包含引號,從而突破屬性值的限制跛梗,注入其他屬性或者標(biāo)簽寻馏。
  • 在標(biāo)簽的hrefsrc 等屬性中核偿,包含 javascript: (偽協(xié)議)等可執(zhí)行代碼诚欠。
  • onloadonerror漾岳、onclick 等事件中轰绵,注入不受控制代碼。
  • style 屬性和標(biāo)簽中尼荆,包含類似 background-image:url("javascript:..."); 的代碼(新版本瀏覽器已經(jīng)可以防范)藏澳。
  • style 屬性和標(biāo)簽中,包含類似 expression(...) 的 CSS 表達(dá)式代碼(新版本瀏覽器已經(jīng)可以防范)耀找。

XSS 攻擊的分類

根據(jù)攻擊的來源翔悠,XSS 攻擊可分為存儲型反射型DOM三種野芒。

存儲型 XSS

存儲型 XSS 的攻擊步驟:

  1. 攻擊者將惡意代碼提交到目標(biāo)網(wǎng)站的數(shù)據(jù)庫中蓄愁。
  2. 用戶打開目標(biāo)網(wǎng)站時,網(wǎng)站服務(wù)端將惡意代碼從數(shù)據(jù)庫取出狞悲,拼接在HTML 中返回給瀏覽器撮抓。
  3. 用戶瀏覽器接收到響應(yīng)后解析執(zhí)行,混在其中的惡意代碼也被執(zhí)行摇锋。
  4. 惡意代碼竊取用戶數(shù)據(jù)并發(fā)送到攻擊者的網(wǎng)站丹拯,或者冒充用戶的行為,調(diào)用目標(biāo)網(wǎng)站接口執(zhí)行攻擊者指定的操作荸恕。
  • 存儲型XSS (又被稱為持久性XSS)攻擊常見于帶有用戶保存數(shù)據(jù)的網(wǎng)站功能乖酬,如論壇發(fā)帖、商品評論融求、用戶私信等咬像。
  • 它是最危險的一種跨站腳本,相比反射型XSS和DOM型XSS具有更高的隱蔽性,所以危害更大县昂,因?yàn)?strong>它不需要用戶手動觸發(fā)肮柜。任何允許用戶存儲數(shù)據(jù)的web程序都可能存在存儲型XSS漏洞,當(dāng)攻擊者提交一段XSS代碼后倒彰,被服務(wù)器端接收并存儲审洞,當(dāng)所有瀏覽者訪問某個頁面時都會被XSS

反射型 XSS

反射型 XSS 的攻擊步驟:

  1. 攻擊者構(gòu)造出特殊的 URL待讳,其中包含惡意代碼预明。
  2. 用戶打開帶有惡意代碼的URL時,網(wǎng)站服務(wù)端將惡意代碼從URL 中取出耙箍,拼接在 HTML 中返回給瀏覽器撰糠。
  3. 用戶瀏覽器接收到響應(yīng)后解析執(zhí)行,混在其中的惡意代碼也被執(zhí)行辩昆。
  4. 惡意代碼竊取用戶數(shù)據(jù)并發(fā)送到攻擊者的網(wǎng)站阅酪,或者冒充用戶的行為,調(diào)用目標(biāo)網(wǎng)站接口執(zhí)行攻擊者指定的操作汁针。

反射型 XSS 跟存儲型 XSS 的區(qū)別是:存儲型 XSS 的惡意代碼存在數(shù)據(jù)庫里术辐,反射型XSS的惡意代碼存在 URL 里。

  • 反射型XSS (也被稱為非持久性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)擊)幢哨,所以非常少見。

DOM 型 XSS

DOMXSS 的攻擊步驟:

  1. 攻擊者構(gòu)造出特殊的URL嫂便,其中包含惡意代碼捞镰。
  2. 用戶打開帶有惡意代碼的 URL
  3. 用戶瀏覽器接收到響應(yīng)后解析執(zhí)行毙替,前端JavaScript取出URL 中的惡意代碼并執(zhí)行岸售。
  4. 惡意代碼竊取用戶數(shù)據(jù)并發(fā)送到攻擊者的網(wǎng)站,或者冒充用戶的行為厂画,調(diào)用目標(biāo)網(wǎng)站接口執(zhí)行攻擊者指定的操作凸丸。

DOMXSS 跟前兩種 XSS的區(qū)別:DOMXSS攻擊中,取出和執(zhí)行惡意代碼由瀏覽器端完成木羹,屬于前端 JavaScript 自身的安全漏洞甲雅,而其他兩種 XSS 都屬于服務(wù)端的安全漏洞。

注意:

DOM通常代表在html坑填、xhtmlxml中的對象抛人,使用DOM可以允許程序和腳本動態(tài)的訪問和更新文檔的內(nèi)容、結(jié)構(gòu)和樣式脐瑰。它不需要服務(wù)器解析響應(yīng)的直接參與妖枚,觸發(fā)XSS 靠的是瀏覽器端的DOM解析,所以防范DOMXSS完全就是前端的責(zé)任,必須注意!!!苍在。

對比:

類型 存儲區(qū) 插入點(diǎn)
存儲型 XSS 后端數(shù)據(jù)庫 HTML
反射型 XSS URL HTML
DOM 型 XSS 后端數(shù)據(jù)庫/前端存儲/URL 前端 JavaScript

防御XSS

只要有輸入數(shù)據(jù)的地方绝页,就可能存在XSS 危險。

常用防范方法

  • httpOnly: 在 cookie 中設(shè)置 HttpOnly 屬性后寂恬,js腳本將無法讀取到 cookie 信息续誉。

  • 輸入過濾: 一般是用于對于輸入格式的檢查,例如:郵箱初肉,電話號碼酷鸦,用戶名,密碼……等牙咏,按照規(guī)定的格式輸入臼隔。不僅僅是前端負(fù)責(zé),后端也要做相同的過濾檢查妄壶。因?yàn)楣粽咄耆梢岳@過正常的輸入流程摔握,直接利用相關(guān)接口向服務(wù)器發(fā)送設(shè)置。

  • 轉(zhuǎn)義 HTML: 如果拼接 HTML 是必要的丁寄,就需要對于引號氨淌,尖括號,斜杠進(jìn)行轉(zhuǎn)義,但這還不是很完善.想對 HTML 模板各處插入點(diǎn)進(jìn)行充分的轉(zhuǎn)義,就需要采用合適的轉(zhuǎn)義庫.(可以看下這個,還是中文的)

function escape(str) {
  str = str.replace(/&/g, '&')
  str = str.replace(/</g, '&lt;')
  str = str.replace(/>/g, '&gt;')
  str = str.replace(/"/g, '&quto;')
  str = str.replace(/'/g, '&#39;')
  str = str.replace(/`/g, '&#96;')
  str = str.replace(/\//g, '&#x2F;')
  return str
}
  • 白名單: 對于顯示富文本來說伊磺,不能通過上面的辦法來轉(zhuǎn)義所有字符宁舰,因?yàn)檫@樣會把需要的格式也過濾掉。這種情況通常采用白名單過濾的辦法奢浑,當(dāng)然也可以通過黑名單過濾蛮艰,但是考慮到需要過濾的標(biāo)簽和標(biāo)簽屬性實(shí)在太多,更加推薦使用白名單的方式雀彼。

預(yù)防存儲型和反射型 XSS 攻擊

存儲型和反射型XSS 都是在服務(wù)端取出惡意代碼后壤蚜,插入到響應(yīng)HTML 里的,攻擊者刻意編寫的“數(shù)據(jù)”被內(nèi)嵌到“代碼”中徊哑,被瀏覽器所執(zhí)行袜刷。

預(yù)防這兩種漏洞,有兩種常見做法:

  • 改成純前端渲染莺丑,把代碼和數(shù)據(jù)分隔開著蟹。
  • HTML做充分轉(zhuǎn)義墩蔓。

HTML轉(zhuǎn)義前面已經(jīng)說過,這里僅僅談?wù)劶兦岸虽秩?/p>

純前端渲染的過程:

  1. 瀏覽器先加載一個靜態(tài)HTML,此HTML 中不包含任何跟業(yè)務(wù)相關(guān)的數(shù)據(jù)萧豆。
  2. 然后瀏覽器執(zhí)行 HTML 中的 JavaScript奸披。
  3. JavaScript 通過 Ajax 加載業(yè)務(wù)數(shù)據(jù),調(diào)用 DOM API 更新到頁面上涮雷。
  • 在純前端渲染中阵面,我們會明確的告訴瀏覽器:下面要設(shè)置的內(nèi)容是文本(.innerText),還是屬性(.setAttribute)洪鸭,還是樣式(.style)等等样刷。瀏覽器不會被輕易的被欺騙,執(zhí)行預(yù)期外的代碼了览爵。
  • 但純前端渲染還需注意避免DOMXSS 漏洞(例如 onload 事件和 href中的javascript:xxx 等置鼻,請參考下文”預(yù)防 DOM 型 XSS 攻擊“部分)
  • 在很多內(nèi)部蜓竹、管理系統(tǒng)中沃疮,采用純前端渲染是非常合適的。但對于性能要求高梅肤,或有 SEO 需求的頁面司蔬,我們?nèi)匀灰鎸ζ唇?code>HTML 的問題,這時就需要對HTML進(jìn)行充分的轉(zhuǎn)義。

預(yù)防 DOM 型 XSS 攻擊

DOMXSS 攻擊姨蝴,實(shí)際上就是網(wǎng)站前端JavaScript代碼本身不夠嚴(yán)謹(jǐn)俊啼,把不可信的數(shù)據(jù)當(dāng)作代碼執(zhí)行了。

  • 在使用 .innerHTML左医、.outerHTML授帕、document.write() 時要特別小心,不要把不可信的數(shù)據(jù)作為HTML插到頁面上浮梢,而應(yīng)盡量使用 .textContent跛十、.setAttribute() 等。
  • 如果用 Vue/React 技術(shù)棧秕硝,并且不使用 v-html/dangerouslySetInnerHTML 功能芥映,就在前端render 階段避免 innerHTMLouterHTMLXSS 隱患远豺。
  • DOM 中的內(nèi)聯(lián)事件監(jiān)聽器奈偏,如 locationonclick躯护、onerror惊来、onloadonmouseover 等棺滞,<a> 標(biāo)簽的 href 屬性裁蚁,JavaScripteval()矢渊、setTimeout()setInterval() 等枉证,都能把字符串作為代碼運(yùn)行矮男。如果不可信的數(shù)據(jù)拼接到字符串中傳遞給這些 API,很容易產(chǎn)生安全隱患刽严,請務(wù)必避免昂灵。
<!-- 內(nèi)聯(lián)事件監(jiān)聽器中包含惡意代碼 -->
<img onclick="UNTRUSTED" onerror="UNTRUSTED" src="data:image/png,">

<!-- 鏈接內(nèi)包含惡意代碼 -->
<a href="UNTRUSTED">1</a>

<script>
// setTimeout()/setInterval() 中調(diào)用惡意代碼
setTimeout("UNTRUSTED")
setInterval("UNTRUSTED")

// location 調(diào)用惡意代碼
location.href = 'UNTRUSTED'

// eval() 中調(diào)用惡意代碼
eval("UNTRUSTED")
</script>

CSRF 跨站點(diǎn)請求偽造

什么是 CSRF

跨站請求偽造(英語:Cross-site request forgery)避凝,也被稱為 one-click attack 或者 session riding舞萄,通常縮寫為 CSRF或者XSRF管削, 是一種挾制用戶在當(dāng)前已登錄的 Web應(yīng)用程序上執(zhí)行非本意的操作的攻擊方法倒脓。如:攻擊者誘導(dǎo)受害者進(jìn)入第三方網(wǎng)站,在第三方網(wǎng)站中含思,向被攻擊網(wǎng)站發(fā)送跨站請求崎弃。利用受害者在被攻擊網(wǎng)站已經(jīng)獲取的注冊憑證,繞過后臺的用戶驗(yàn)證含潘,達(dá)到冒充用戶對被攻擊的網(wǎng)站執(zhí)行某項(xiàng)操作的目的饲做。

CSRF攻擊流程

下圖引自這位大佬的淺談CSRF攻擊方式,感謝!

簡而言之:網(wǎng)站過分相信用戶

從上圖可以看出,要完成一次CSRF攻擊遏弱,受害者必須依次完成兩個步驟:

  • 1.登錄受信任網(wǎng)站A盆均,并在本地生成Cookie。
  • 2.在不登出A的情況下漱逸,訪問危險網(wǎng)站B泪姨。

看到這里,你也許會說:“如果我不滿足以上兩個條件中的一個饰抒,我就不會受到CSRF的攻擊”肮砾。是的,確實(shí)如此袋坑,但你不能保證以下情況不會發(fā)生:

  • 1.你不能保證你登錄了一個網(wǎng)站后仗处,不再打開一個tab頁面并訪問另外的網(wǎng)站。
  • 2.你不能保證你關(guān)閉瀏覽器了后枣宫,你本地的Cookie立刻過期疆柔,你上次的會話已經(jīng)結(jié)束。(事實(shí)上镶柱,關(guān)閉瀏覽器不能結(jié)束一個會話旷档,但大多數(shù)人都會錯誤的認(rèn)為關(guān)閉瀏覽器就等于退出登錄/結(jié)束會話了......)
  • 3.上圖中所謂的攻擊網(wǎng)站,可能是一個存在其他漏洞的可信任的經(jīng)常被人訪問的網(wǎng)站歇拆。

常見的CSRF攻擊類型

GET類型的CSRF

GET類型的CSRF利用非常簡單鞋屈,只需要一個HTTP請求

一般會這樣利用:

 <img src="http://bank.example/withdraw?amount=10000&for=hacker" > 

在受害者訪問含有這個img的頁面后范咨,瀏覽器會自動向http://bank.example/withdraw?account=xiaoming&amount=10000&for=hacker發(fā)出一次HTTP請求。bank.example就會收到包含受害者登錄信息的一次跨域請求厂庇。

POST類型的CSRF

這種類型的CSRF利用起來通常使用的是一個自動提交的表單渠啊,如:

<form action="http://bank.example/withdraw" method=POST>
  <input type="hidden" name="account" value="xiaoming" />
  <input type="hidden" name="amount" value="10000" />
  <input type="hidden" name="for" value="hacker" />
</form>
<script> 
document.forms[0].submit(); 
</script> 
  • 訪問該頁面后,表單會自動提交权旷,相當(dāng)于模擬用戶完成了一次POST操作替蛉。
  • POST類型的攻擊通常比GET要求更加嚴(yán)格一點(diǎn),但仍并不復(fù)雜拄氯。任何個人網(wǎng)站躲查、博客,被黑客上傳頁面的網(wǎng)站都有可能是發(fā)起攻擊的來源译柏,后端接口不能將安全寄托在僅允許POST上面镣煮。

鏈接類型的CSRF

鏈接類型的CSRF并不常見,比起其他兩種用戶打開頁面就中招的情況鄙麦,這種需要用戶點(diǎn)擊鏈接才會觸發(fā)典唇。這種類型通常是在論壇中發(fā)布的圖片中嵌入惡意鏈接,或者以廣告的形式誘導(dǎo)用戶中招胯府,攻擊者通常會以比較夸張的詞語誘騙用戶點(diǎn)擊

例如:

<a  taget="_blank">
  重磅消息=橄巍!
<a/>

CSRF的特點(diǎn)

  • 攻擊一般發(fā)起在第三方網(wǎng)站骂因,而不是被攻擊的網(wǎng)站炎咖。被攻擊的網(wǎng)站無法防止攻擊發(fā)生。
  • 攻擊利用受害者在被攻擊網(wǎng)站的登錄憑證侣签,冒充受害者提交操作塘装;而不是直接竊取數(shù)據(jù)。
  • 整個過程攻擊者并不能獲取到受害者的登錄憑證影所,僅僅是“冒用”蹦肴。
  • 跨站請求可以用各種方式:圖片URL、超鏈接猴娩、CORS阴幌、Form提交等等。部分請求方式可以直接嵌入在第三方論壇卷中、文章中矛双,難以進(jìn)行追蹤。

CSRF通常是跨域的蟆豫,因?yàn)橥庥蛲ǔ8菀妆还粽哒瓶匾楹觥5侨绻居蛳掠腥菀妆焕玫墓δ埽热缈梢园l(fā)圖和鏈接的論壇和評論區(qū)十减,攻擊可以直接在本域下進(jìn)行栈幸,而且這種攻擊更加危險愤估。

CSRF與 XSS 區(qū)別

  • 通常來說 CSRF 是由 XSS 實(shí)現(xiàn)的,CSRF 時常也被稱為 XSRF(CSRF 實(shí)現(xiàn)的方式還可以是直接通過命令行發(fā)起請求等)速址。
  • 本質(zhì)上講玩焰,XSS 是代碼注入問題,CSRFHTTP 問題芍锚。XSS 是內(nèi)容沒有過濾導(dǎo)致瀏覽器將攻擊者的輸入當(dāng)代碼執(zhí)行昔园。CSRF 則是因?yàn)闉g覽器在發(fā)送 HTTP 請求時候自動帶上 cookie,而一般網(wǎng)站的 session都存在cookie里面(Token驗(yàn)證可以避免)并炮。

防御

  • 驗(yàn)證碼默刚;強(qiáng)制用戶必須與應(yīng)用進(jìn)行交互,才能完成最終請求渣触。此種方式能很好的遏制 csrf羡棵,但是用戶體驗(yàn)比較差壹若。

  • Referer check嗅钻;請求來源限制,此種方法成本最低店展,但是并不能保證 100% 有效养篓,因?yàn)榉?wù)器并不是什么時候都能取到Referer,而且低版本的瀏覽器存在偽造 Referer的風(fēng)險赂蕴。

  • token柳弄; token 驗(yàn)證的 CSRF 防御機(jī)制是公認(rèn)最合適的方案。(具體可以查看本系列前端鑒權(quán)中對token有詳細(xì)描述)若網(wǎng)站同時存在 XSS 漏洞的時候概说,這個方法也是空談碧注。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市糖赔,隨后出現(xiàn)的幾起案子萍丐,更是在濱河造成了極大的恐慌,老刑警劉巖放典,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逝变,死亡現(xiàn)場離奇詭異,居然都是意外死亡奋构,警方通過查閱死者的電腦和手機(jī)壳影,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弥臼,“玉大人宴咧,你說我怎么就攤上這事【睹澹” “怎么了掺栅?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵箱吕,是天一觀的道長。 經(jīng)常有香客問我柿冲,道長茬高,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任假抄,我火速辦了婚禮怎栽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘宿饱。我一直安慰自己熏瞄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布谬以。 她就那樣靜靜地躺著强饮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪为黎。 梳的紋絲不亂的頭發(fā)上邮丰,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天,我揣著相機(jī)與錄音铭乾,去河邊找鬼剪廉。 笑死,一個胖子當(dāng)著我的面吹牛炕檩,可吹牛的內(nèi)容都是我干的斗蒋。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼笛质,長吁一口氣:“原來是場噩夢啊……” “哼泉沾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起妇押,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤跷究,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后舆吮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體揭朝,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年色冀,在試婚紗的時候發(fā)現(xiàn)自己被綠了潭袱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡锋恬,死狀恐怖屯换,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤彤悔,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布嘉抓,位于F島的核電站,受9級特大地震影響晕窑,放射性物質(zhì)發(fā)生泄漏抑片。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一杨赤、第九天 我趴在偏房一處隱蔽的房頂上張望敞斋。 院中可真熱鬧,春花似錦疾牲、人聲如沸植捎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽焰枢。三九已至,卻和暖如春舌剂,著一層夾襖步出監(jiān)牢的瞬間济锄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工架诞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拟淮,地道東北人干茉。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓谴忧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親角虫。 傳聞我的和親對象是個殘疾皇子沾谓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容