国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

【譯】Excess-XSS 一份關(guān)于 XSS 的綜合教程

timger / 3534人閱讀

摘要:示例攻擊如何進(jìn)行下圖展示了攻擊者如何進(jìn)行攻擊攻擊者利用網(wǎng)站的表單插入惡意字符串到網(wǎng)站數(shù)據(jù)庫中。恰恰相反,至少有兩種常見的方式,會導(dǎo)致受害者發(fā)起針對自己的反射型攻擊。攻擊者精心構(gòu)造了一個包含惡意字符串的,將其發(fā)送給受害者。

原文地址:http://excess-xss.com/。如有翻譯不當(dāng)之處,歡迎指出 :D

分為四部分:

概述

XSS 攻擊

XSS 防御

總結(jié)

第一部分:概述 XSS 是什么

跨站腳本攻擊(XSS)是一種代碼注入攻擊,攻擊者利用它可以在其它用戶瀏覽器中執(zhí)行惡意 JavaScript。

攻擊者并不是直接面對受害者。而是,為了讓網(wǎng)站替自己傳輸惡意 JavaScript,攻擊者需要利用受害者訪問的網(wǎng)站上的漏洞。對受害者的瀏覽器而言,惡意的 JavaScript 似乎是網(wǎng)站合法的一部分,網(wǎng)站在無意中成為了攻擊者的共犯。

惡意 JavaScript 是如何被注入的

攻擊者在受害者瀏覽器中執(zhí)行惡意 JavaScript 的唯一方式就是將其注入到受害者瀏覽的網(wǎng)頁中。如果網(wǎng)站直接將用戶輸入顯示到頁面中,就可能導(dǎo)致惡意代碼注入,因為攻擊者可以插入惡意字符串,讓受害者瀏覽器誤以為是代碼。

在下面的例子中,一段簡單的服務(wù)端腳本用來在網(wǎng)頁中展示最新的評論:

print ""
print "Latest comment:"
print database.latestComment
print ""

上面的腳本認(rèn)為評論只會包含文本。然而,由于是直接展示用戶輸入,攻擊者可以提交類似這樣的評論 。現(xiàn)在,訪問該頁面的所有用戶就會接收到如下響應(yīng):


Latest comment:

當(dāng)用戶瀏覽器加載了該頁面,就會執(zhí)行 ,這表明,不管實際中執(zhí)行的是什么代碼,只要攻擊者注入的腳本出現(xiàn),問題就存在。

第二部分:XSS 攻擊 XSS 攻擊涉及到的角色

在詳細(xì)介紹 XSS 攻擊如何進(jìn)行之前,需要定義 XSS 中涉及到的角色。通常,一次 XSS 會涉及三個角色:網(wǎng)站受害者攻擊者

網(wǎng)站響應(yīng) HTML 頁面給發(fā)起請求的用戶。在我們的例子中,網(wǎng)站是 http://website/。

網(wǎng)站的數(shù)據(jù)庫用來存儲一些用戶的輸入,并輸出到網(wǎng)站頁面中。

受害者是網(wǎng)站的普通用戶,通過瀏覽器請求頁面。

攻擊者是網(wǎng)站的惡意用戶,準(zhǔn)備利用網(wǎng)站的 XSS 漏洞發(fā)起攻擊

攻擊者的服務(wù)器是由攻擊者控制,唯一的用途是盜取用戶敏感信息。在我們的例子中,位于 http://attacker/

一次攻擊示例

在這個例子當(dāng)中,我們假設(shè)攻擊者的目標(biāo)是通過利用網(wǎng)站 XSS 漏洞盜取受害者的 cookie。這可以通過在受害者瀏覽器中執(zhí)行如下代碼實現(xiàn):

上面的腳本將瀏覽器導(dǎo)航到新的頁面,并觸發(fā)一次 HTTP 請求到攻擊者的服務(wù)器。URL 將受害者的 cookie 作為查詢參數(shù),當(dāng)請求到達(dá)攻擊者服務(wù)器時,攻擊者就可以提取 cookie。一旦攻擊者拿到了 cookie,他就可以冒充受害者,進(jìn)而發(fā)起更深入的攻擊。

從現(xiàn)在起,我們將上面的 HTML 代碼稱為惡意字符串或是惡意腳本。需要注意的是,上面的字符串只有被受害者瀏覽器作為 HTML 解析之后,才會產(chǎn)生危害。

示例攻擊如何進(jìn)行

下圖展示了攻擊者如何進(jìn)行攻擊:

攻擊者利用網(wǎng)站的表單插入惡意字符串到網(wǎng)站數(shù)據(jù)庫中。

受害者從網(wǎng)站中請求頁面。

網(wǎng)站在響應(yīng)中包含了來自數(shù)據(jù)庫的惡意字符串,并返回給受害者。

受害者的瀏覽器執(zhí)行了響應(yīng)中的惡意字符串,將受害者的 cookie 發(fā)送到了攻擊者的服務(wù)器。

XSS 類型

盡管 XSS 攻擊的目標(biāo)都是在受害者瀏覽器中執(zhí)行惡意 JavaScript,還是有幾種完全不同的方式來實現(xiàn)該目標(biāo)的。XSS 攻擊通常可以分為三類:

存儲型 XSS(Persistent XSS),惡意字符串來自網(wǎng)站數(shù)據(jù)庫

反射型 XSS(Reflected XSS),惡意字符串來自受害者的請求

DOM 型 XSS(DOM-based XSS),漏洞位于客戶端代碼而不是服務(wù)端代碼

前面的例子展示了存儲型 XSS 攻擊。接下來介紹另外兩種:反射型 XSS 和 DOM 型 XSS。

反射型 XSS

在反射型 XSS 中,惡意字符串是受害者向網(wǎng)站發(fā)起的請求的一部分。然后,網(wǎng)站將包含惡意字符串的響應(yīng)返回給了受害者。如下圖所示:

攻擊者精心構(gòu)造了一個包含惡意字符串的 URL,將其發(fā)送給受害者

攻擊者欺騙受害者,使其訪問了該 URL

網(wǎng)站在響應(yīng)中包含了來自 URL 的惡意字符串

受害者瀏覽器執(zhí)行了響應(yīng)中的惡意字符串,將自己的 cookie 發(fā)送到了攻擊者的服務(wù)器

如何成功發(fā)起反射型 XSS 攻擊

首先,反射型 XSS 看起來是無害的,因為它需要受害者親自發(fā)起一個包含惡意字符串的請求。而沒有人會自愿攻擊自己,乍看起來是沒辦法發(fā)動攻擊的。

恰恰相反,至少有兩種常見的方式,會導(dǎo)致受害者發(fā)起針對自己的反射型 XSS 攻擊。

如果目標(biāo)用戶是特定的某個人,攻擊者可以發(fā)送惡意 URL 給受害者(例如:使用郵件或是即時消息),并欺騙受害者訪問該 URL。

如果目標(biāo)用戶是一大群人,攻擊者可以發(fā)布指向惡意 URL 的鏈接(例如:在自己的網(wǎng)站或是社交網(wǎng)絡(luò)上),并等待受害者點(diǎn)擊。

這兩種方式類似,并且都可以通過利用短網(wǎng)址服務(wù)來提高成功率,短網(wǎng)址會使得惡意字符串難以分辨。

DOM XSS

DOM XSS 是存儲型 XSS 和 反射型 XSS 的變種。在 DOM XSS 攻擊中,一直到頁面運(yùn)行了 JavaScript,惡意字符串才被實際的解析。
下圖展示了 DOM XSS 攻擊。

攻擊者精心構(gòu)造了一個包含惡意字符串的 URL,將其發(fā)送給受害者。

攻擊者欺騙受害者,使其訪問了該 URL

網(wǎng)站接收到響應(yīng),但是響應(yīng)中并不包含惡意字符串

受害者瀏覽器執(zhí)行響應(yīng)中合法的 JavaScript,導(dǎo)致惡意代碼插入到了頁面中

受害者瀏覽器執(zhí)行了插入到頁面中的惡意代碼,將 cookie 發(fā)送到了攻擊者的服務(wù)器

DOM XSS 的不同之處在哪

在前面存儲型和反射型 XSS 示例中,服務(wù)端把惡意腳本插入到頁面中,然后將其作為響應(yīng)發(fā)送給受害者。當(dāng)受害者瀏覽器接收到響應(yīng)時,會把惡意腳本當(dāng)作是頁面的合法內(nèi)容,在頁面加載過程中與其它腳本一同執(zhí)行。

在 DOM XSS 示例中,惡意腳本并沒有插入到頁面中,在頁面加載過程中,只有合法的 JavaScript 被執(zhí)行。問題在于,合法的 JavaScript 直接將用戶輸入插入到頁面中。因為惡意字符串通過 innerHTML 插入到頁面中,就會作為 HTML 解析,導(dǎo)致惡意腳本執(zhí)行。

兩者的區(qū)別很小但是很重要:

在傳統(tǒng)的 XSS 中,惡意 JavaScript 作為服務(wù)端發(fā)送頁面的一部分,在頁面加載時被執(zhí)行

在 DOM XSS 中,惡意 JavaScript 在頁面加載完成后某個時間點(diǎn)執(zhí)行,是由頁面合法 JavaScript 沒有安全處理用戶輸入造成的。

為什么 DOM XSS 很重要

在上面的 DOM XSS 例子中,JavaScript 并不是必須的;服務(wù)端就可以生成完整的 HTML。如果服務(wù)端代碼不存在漏洞,那么網(wǎng)站就不存在 XSS。

但是,隨著 WEB 應(yīng)用越來越高級,越來越多的 HTML 是在客戶端通過 JavaScript 生成而不是在服務(wù)端生成。任何時候不刷新整個頁面,需要更新內(nèi)容,就必須通過 JavaScript 進(jìn)行。值得注意的是,AJAX 請求后更新頁面就是這樣的例子。

也就是說,XSS 漏洞不僅可以出現(xiàn)在網(wǎng)站服務(wù)端代碼,還可能出現(xiàn)在客戶端 JavaScript 代碼中。結(jié)果就是,即使服務(wù)端代碼完全沒問題,在頁面加載完成后,客戶端代碼還是可能在 DOM 更新中不安全的包含了用戶輸入。一旦發(fā)生,客戶端代碼就存與服務(wù)端無關(guān)的 XSS 漏洞。

對服務(wù)端不可見的 DOM XSS

有一種特殊的 DOM XSS,惡意字符串不會被發(fā)送到網(wǎng)站服務(wù)端:當(dāng)惡意字符串位于 URL 的片段標(biāo)識符中(# 號之后)。瀏覽器不會發(fā)送 URL 的片段標(biāo)識符到服務(wù)端,這樣,服務(wù)端代碼就沒方法獲取它。雖然客戶端代碼可以獲取它,但是如果沒有進(jìn)行安全處理就會出現(xiàn) XSS 漏洞。

并不是只有片段標(biāo)識符會出現(xiàn)這種情況。對服務(wù)端不可見的用戶輸入還包括 HTML5 的新特性,例如:LocalStorage 和 IndexedDB。

第三部分:防御 XSS 防御 XSS 的方法

記住,XSS 攻擊是一種代碼注入:用戶輸入被錯誤的解釋為惡意程序代碼。為了防止這種類型的代碼注入,需要對輸入進(jìn)行安全處理。對 web 開發(fā)者而言,可以采用兩種不同的方式:

編碼,轉(zhuǎn)義用戶輸入,這樣瀏覽器就只會將其解釋為數(shù)據(jù)而不是代碼。

校驗,過濾用戶輸入,這樣瀏覽器就可以將其解釋為沒有惡意命令的代碼。

盡管這兩種方式有著本質(zhì)的區(qū)別,但是它們還是存在共同點(diǎn),在使用過程中,理解這些共同點(diǎn)很重要:

上下文:根據(jù)用戶輸入在頁面中插入位置的不同,需要進(jìn)行不同的安全處理

流入/流出(inbound/outbound):安全處理要么在網(wǎng)站接收輸入時(inbound)進(jìn)行,要么在網(wǎng)站將輸入到插入頁面之前(outbound)進(jìn)行

客戶端/服務(wù)端:安全處理可以在客戶端進(jìn)行,也可以在服務(wù)端進(jìn)行。在某些情況下,需要在客戶端和服務(wù)端同時進(jìn)行安全處理。

在詳細(xì)介紹如何進(jìn)行編碼和校驗之前,我們先來逐個解釋以上三點(diǎn)。

輸入處理的上下文

在網(wǎng)頁中,用戶輸入可能插入的地方有很多。每個地方的上下文不同,要遵循指定規(guī)則才能保證用戶輸入不會打破上下文,被解釋為惡意代碼。下面是常見的上下文:

上下文 示例代碼
HTML element content
userInput
HTML attribute value
URL query value http://example.com/?parameter=userInput
CSS value color: userInput
JavaScript value var name = "userInput";
為什么上下文很重要

如果用戶的輸入在編碼和校驗之前就插入到頁面中,在上面提到的上下文中都可能產(chǎn)生 XSS 漏洞。攻擊者要想注入惡意代碼,他只需插入對應(yīng)上下文的結(jié)束分隔符,緊接著是惡意代碼。

例如,如果某個站點(diǎn)將用戶輸入直接插入到 HTML 屬性中,攻擊者通過以引號作為開頭的輸入就可以注入惡意腳本,如下所示:

Application code
Malicious string ">

只需移除用戶輸入中的所有引號就可以避免上面的 XSS,但這只對該上下文有效。如果相同的輸入插入到其它的上下文,結(jié)束分隔符可能就不同,又可能導(dǎo)致注入。所以說,需要根據(jù)用戶輸入插入點(diǎn)的上下文,進(jìn)行不同的安全處理。

流入/流出(inbound/outbound)的輸入處理

僅憑直覺,似乎只需在網(wǎng)站接收到用戶輸入時,對其進(jìn)行編碼或是校驗就可以防止 XSS。用這種方式,任何惡意代碼插入到頁面中的時候都已經(jīng)失效了,生成 HTML 的腳本就無需關(guān)心安全處理。

問題在于,前面也提到過,用戶輸入可以插入到頁面中很多地方。確定用戶輸入最終會插入到哪一種上下文并不簡單,而且相同的用戶輸入經(jīng)常需要插入到不同的上下文。依賴 inbound 輸入處理來防御 XSS 是一種非常脆弱的方案,很容易出錯。(PHP 廢棄的特性 magic quotes 就是這樣的方案)

反倒是,outbound 輸入處理應(yīng)該作為防御 XSS 的首要陣線,因為它可以考慮到用戶輸入即將插入的特定上下文。換句話說,inbound 校驗可以用來作為第二層保護(hù),后面會再提到。

在哪里進(jìn)行安全處理

當(dāng)前,在大多數(shù) web 應(yīng)用中,客戶端代碼和服務(wù)端代碼都會涉及到處理用戶輸入。為了防御所有類型的 XSS,安全處理也要同時在服務(wù)端和客戶端進(jìn)行。

為了防御傳統(tǒng)的 XSS,安全處理必須在服務(wù)端代碼進(jìn)行。通過服務(wù)器支持的語言實現(xiàn)。

為了防御服務(wù)器接收不到惡意字符串的 DOM XSS,(例如,前面的提到的片段標(biāo)識符攻擊)安全處理必須在客戶端進(jìn)行。通過 JavaScript 實現(xiàn)。

現(xiàn)在我們已經(jīng)解釋過為什么上下文很重要,為什么區(qū)分 inbound 和 outbound 輸入處理很重要,為什么安全處理需要同時在客戶端代碼和服務(wù)端代碼同時進(jìn)行。接下來,將要闡述兩種安全處理(編碼和校驗)是如何進(jìn)行的。

編碼

編碼用來轉(zhuǎn)義用戶輸入,這樣瀏覽器就會將其解釋為數(shù)據(jù)而不是代碼。在 web 開發(fā)中最常見的就是 HTML 轉(zhuǎn)義,它會把字符 <> 分別轉(zhuǎn)換為 <>

下面的偽代碼展示了服務(wù)端代碼如何對用戶輸入進(jìn)行 HTML 轉(zhuǎn)義,然后將其插入到頁面中:

print ""
print "Latest comment: "
print encodeHtml(userInput)
print ""

如果用戶輸入為字符串 ,輸出 HTML 結(jié)果如下:


Latest comment:

由于所有有特殊含義的字符都被轉(zhuǎn)義了,所以瀏覽器不會把用戶輸入當(dāng)作 HTML 解析。

在客戶端和服務(wù)端進(jìn)行編碼

當(dāng)在客戶端進(jìn)行編碼時,使用的是 JavaScript,它包含針對不同上下文對數(shù)據(jù)進(jìn)行編碼的函數(shù)。

當(dāng)在服務(wù)端進(jìn)行編碼時,可用的函數(shù)和服務(wù)端的語言和框架有關(guān)。考慮到服務(wù)端語言和框架多種多樣,該教程不會涉及特定語言或框架的編碼。不管怎樣,熟悉客戶端編碼函數(shù)對編寫服務(wù)端代碼也是很有幫助的。

在客戶端編碼

當(dāng)在客戶端使用 JavaScript 編碼用戶輸入時,有一些內(nèi)置的方法和屬性會自動根據(jù)上下文進(jìn)行編碼:

上下文 方法、屬性
HTML element content node.textContent = userInput
HTML attribute value element.setAttribute(attribute, userInput) or element[attribute] = userInput
URL query value window.encodeURIComponent(userInput)
CSS value element.style.property = userInput

前面提到的最后一種上下文(JavaScript values)并不包含在內(nèi),because JavaScript provides no built-in way of encoding data to be included in JavaScript source code.

編碼的局限性

即使進(jìn)行了編碼,在一些上下文中還是可能輸入惡意字符串。一個值得注意的示例如下,當(dāng)用戶輸入用來提供 URL:

document.querySelector("a").href = userInput

盡管給一個超鏈接元素的 href 屬性賦值,會自動編碼保證其成為屬性值而不是其它,但這并不能阻止攻擊者插入以 "javascript:" 開頭的 URL。當(dāng)點(diǎn)擊鏈接時,URL 中嵌入的 JavaScript 就被執(zhí)行。

當(dāng)你希望用戶可以自定義頁面部分代碼時,編碼這種處理方式就不太合適了。例如:在個人資料頁,用戶可以自定義 HTML。如果對這些 HTML 進(jìn)行編碼,那么個人資料頁只能包含純文本了。

在這種情況下,編碼必須配合校驗進(jìn)行,下面介紹校驗。

校驗

校驗是指過濾用戶輸入,以便移除所有惡意的部分,而無需移除其中所有代碼。在 WEB 開發(fā)中最常見的一種校驗就是允許一些 HTML 元素(例如: )但是不允許其它一些(例如:

如果定義了合理的 CSP 策略,瀏覽器就不會加載和執(zhí)行 malicious-script.js,因為 http://attacker/ 不會出現(xiàn)在可信源集合中。在這種情況下,即使網(wǎng)站沒能正確對輸入進(jìn)行安全處理,CSP 策略可以防止漏洞造成任何損害。

即使攻擊者注入的不是外部文件,而是行內(nèi)腳本代碼,合理的 CSP 策略仍可以禁止行內(nèi) JavaScript,從而防止漏洞造成任何傷害。

如何啟用 CSP

默認(rèn)情況下,瀏覽器不強(qiáng)制使用 CSP。為了給網(wǎng)站開啟 CSP,響應(yīng)中要帶上額外的 HTTP 頭:Content-Security-Policy。如果瀏覽器支持 CSP,那么所有帶有這一 HTTP 頭的頁面都會遵守 CSP。

由于安全策略是通過每一個 HTTP 響應(yīng)來發(fā)送,可以在服務(wù)端對每一頁都設(shè)置安全策略。相同的策略可以通過在每個響應(yīng)中提供相同的 CSP 頭來應(yīng)用到整站上。

Content-Security-Policy 響應(yīng)頭的值是一個字符串,定義了一個或多個安全策略,會應(yīng)用到頁面中。后面會講到它的語法。

注意:本節(jié)示例中,為了表示清楚 HTTP 頭部,使用了換行和縮進(jìn),在實際的 HTTP 頭部中,這是不應(yīng)該出現(xiàn)的。

CSP 語法

CSP 頭部語法如下:

Content?Security?Policy:
    directive source?expression, source?expression, ...;
    directive ...;
    ...

由兩個元素構(gòu)成:

指令:聲明資源類型的字符串,從預(yù)定義列表中取值。

來源表達(dá)式(Source expressions):描述可以用于下載資源的一個或多個服務(wù)器的模式

對每個指令來說,給定的來源表達(dá)式定義了該資源類型可以使用哪些來源下載資源。

指令

在 CSP 頭部中可以使用的指令列表如下:

connect?src

font?src

frame?src

img?src

media?src

object?src

script?src

style?src

除了上面這些,還有一個特別的指令:default-src,它可以用來給所有指令提供一個默認(rèn)值,那些沒有出現(xiàn)在 HTTP 頭部中的指令使用默認(rèn)值。

來源表達(dá)式(source expressions)

來源表達(dá)式語法如下:

protocol://host?name:port?number

主機(jī)名可以以 打頭,表示所提供的主機(jī)名的任何子域都被允許。類似的,端口號也可以是 ,表示所有端口都被允許。此外,協(xié)議和端口號可以省略。也可以只指定協(xié)議,從而實現(xiàn)要求所有資源都通過 HTTPS 加載。

除此之外,來源表達(dá)式還可以是下面四個有特殊含義的關(guān)鍵詞之一(包含引號):

"none":不允許該類型資源

"self":允許從提供當(dāng)前頁面的主機(jī)下載資源

"unsafe-inline":允許在頁面中嵌入資源,例如:行內(nèi)

閱讀需要支付1元查看
<