摘要:示例攻擊如何進(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í)行 標(biāo)簽中所有 JavaScript 代碼。攻擊者就實現(xiàn)了他的攻擊。
惡意 JavaScript 是什么乍一看,在受害者瀏覽器中執(zhí)行 JavaScript 似乎并沒有什么特別的危害。畢竟,JavaScript 運(yùn)行在一個受到嚴(yán)格限制的環(huán)境中,對用戶文件和操作系統(tǒng)只能進(jìn)行非常有限的訪問。事實上,你現(xiàn)在就可以打開瀏覽器的控制臺,執(zhí)行任意的 JavaScript,而不太可能對計算機(jī)造成任何破壞。
但是,當(dāng)你考慮到下面幾點(diǎn)時,就會更清楚惡意 JavaScript 可能造成的危害:
JavaScript 可以訪問用戶的敏感信息,例如 cookies。
JavaScript 可以通過 XMLHTTPRequest 或是其它方式發(fā)送 HTTP 請求,將任意內(nèi)容發(fā)送到任意目標(biāo)。
JavaScript 可以通過 DOM 操作方法,對當(dāng)前頁面進(jìn)行任意篡改。
上面的因素結(jié)合起來就可以造成嚴(yán)重的安全隱患,如下所述。
惡意 JavaScript 有哪些危害在其它用戶瀏覽器中執(zhí)行任意 JavaScript 的能力,使得攻擊者可以進(jìn)行下面幾種攻擊:
盜取 Cookie:攻擊者使用 document.cookie 可以獲取受害者與網(wǎng)站關(guān)聯(lián)的 cookie,將其發(fā)送到自己的服務(wù)器,并利用 cookie 提取敏感信息,例如 session IDs。
鍵盤記錄:攻擊者使用 addEventListener 可以注冊鍵盤事件監(jiān)聽,然后將用戶所有的鍵盤記錄發(fā)送到自己的服務(wù)器,這里面可能會包含敏感信息,例如:密碼或信用卡號。
釣魚:攻擊者使用 DOM 操作可以插入一個偽造的登錄表單,將表單的 action 屬性設(shè)置為自己的服務(wù)器地址,然后欺騙用戶提交敏感信息。
盡管這幾種攻擊方式大不相同,但有個關(guān)鍵點(diǎn)是相同的:由于攻擊者是在網(wǎng)站提供的頁面中注入的代碼,所以惡意 JavaScript 會在網(wǎng)站的上下文中執(zhí)行。這意味著,惡意 JavaScript 與來自網(wǎng)站的其它腳本待遇相同:它可以訪問該網(wǎng)站上受害者的數(shù)據(jù)(例如:cookie)和 URL 地址欄中的主機(jī)名。不論出于何種目的,被注入的腳本會被看成網(wǎng)站合法的一部分,網(wǎng)站可以做的事,它同樣可以做。
這樣的事實凸顯了一個關(guān)鍵點(diǎn):
如果攻擊者可以利用你的網(wǎng)站在其它用戶瀏覽器中執(zhí)行任意 JavaScript,那么你的網(wǎng)站及其用戶的安全都受到了威脅。
為了強(qiáng)調(diào)這一點(diǎn),本教程中的一些例子會略去惡意 JavaScript 的詳細(xì)內(nèi)容,只是表示為 ,這表明,不管實際中執(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)行攻擊:
攻擊者利用網(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ù)器
首先,反射型 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 XSSDOM 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ù)器
在前面存儲型和反射型 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 例子中,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 漏洞。
有一種特殊的 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)行不同的安全處理。
僅憑直覺,似乎只需在網(wǎng)站接收到用戶輸入時,對其進(jìn)行編碼或是校驗就可以防止 XSS。用這種方式,任何惡意代碼插入到頁面中的時候都已經(jīng)失效了,生成 HTML 的腳本就無需關(guān)心安全處理。
問題在于,前面也提到過,用戶輸入可以插入到頁面中很多地方。確定用戶輸入最終會插入到哪一種上下文并不簡單,而且相同的用戶輸入經(jīng)常需要插入到不同的上下文。依賴 inbound 輸入處理來防御 XSS 是一種非常脆弱的方案,很容易出錯。(PHP 廢棄的特性 magic quotes 就是這樣的方案)
反倒是,outbound 輸入處理應(yīng)該作為防御 XSS 的首要陣線,因為它可以考慮到用戶輸入即將插入的特定上下文。換句話說,inbound 校驗可以用來作為第二層保護(hù),后面會再提到。
當(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 解析。
當(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 元素(例如: 和 )但是不允許其它一些(例如:)。
根據(jù)實現(xiàn)方式的不同,主要有兩種典型的校驗方法:
分類策略(Classification strategy):使用黑名單或白名單對用戶輸入進(jìn)行分類。
validation outcome:被確認(rèn)為有惡意的用戶輸入,可以選擇拒絕或是凈化。
直覺上,通過定義一個不允許出現(xiàn)在用戶輸入中的禁止模式(forbidden pattern),來進(jìn)行校驗是合理的。如果字符串匹配了該模式,就被標(biāo)記為非法。例如:允許用戶提交自定義的任意協(xié)議的 URL,除了 javascript: 偽協(xié)議。這種分類策略稱為黑名單。
但是,黑名單有兩大缺點(diǎn):
復(fù)雜:準(zhǔn)確的描述所有可能的惡意字符串的集合通常是一項非常復(fù)雜的任務(wù)。上面例子中,通過簡單地搜索子字符串 "javascript:" 來實現(xiàn)是不行的,因為這會漏掉字符串的其它變種,例如: "Javascript:"(首字母大寫)和 "javascript:"(首字母編碼成了字符引用)
容易失效:即使開發(fā)出了完美的黑名單,一旦瀏覽器增加了允許惡意用戶使用的新特性,黑名單就失效了。例如,在 HTML5 onmousewheel 屬性出現(xiàn)之前開發(fā)的 HTML 驗證黑名單,就不能防御使用該屬性進(jìn)行的 XSS 攻擊。這個缺點(diǎn)在 WEB 開發(fā)中尤其明顯,因為使用到的多種技術(shù)都在不斷地更新中。
由于這些缺點(diǎn),強(qiáng)烈反對使用黑名單作為分類策略。通常,白名單是一種更加安全的方式。
白名單基本上和黑名單是相反的:不是定義禁止模式,而是定義允許模式(allowed pattern),如果字符串不匹配該模式,則標(biāo)記為非法。
對照前面黑名單的例子,允許用戶提交自定義 URL 的白名單只包含 http: 和 https: 協(xié)議,不包含其它。使用這種方式會自動將包含 javascript: 協(xié)議的 URL 標(biāo)記為非法,即使它以 "Javascript:" 或 "javascript:" 形式出現(xiàn)。
和黑名單相比,白名單的兩大優(yōu)點(diǎn)是:
簡單:通常,準(zhǔn)確的描述一個安全的字符串的集合要比定義一個包含所有惡意字符串的集合要簡單很多。尤其是,在一般情況下,用戶輸入只需是瀏覽器功能的有限子集時更是如此。例如,用于描述上面只允許 http: 或 https: 協(xié)議的 URL 的白名單是很簡單的,并且在大多數(shù)情況下完全夠用。
持久性:不像黑名單,當(dāng)有瀏覽器增加新特性時,白名單一般不會失效。例如:一個 HTML 校驗白名單只允許 HTML 元素上出現(xiàn) title 屬性,即使 HTML5 新增了 onmousewheel 屬性,白名單依然有效。
當(dāng)輸入被標(biāo)記為非法,可以采取兩種行為:
拒絕:簡單粗暴的拒絕該輸入,阻止其在網(wǎng)站的任何地方使用
凈化:移除所有非法部分,剩余部分正常用在網(wǎng)站中
兩種方式中,拒絕最容易實現(xiàn)。話雖如此,凈化通常更有用,因為它允許用戶的輸入范圍更廣。例如,如果一個用戶提交信用卡號,凈化過程中通過移除所有非數(shù)字字符來防止代碼注入,同時可以允許用戶在數(shù)字間使用連字符。
如果你決定使用凈化,必須保證凈化過程本身沒有使用黑名單的方式。例如:即使 URL"Javascript:..."被白名單標(biāo)記為非法,只需移除所有的 "Javascript:" 還是可以使其通過凈化流程。因此,測試完備的庫和框架還是應(yīng)該盡可能的使用凈化。
選用哪種方法編碼應(yīng)該作為防御 XSS 的第一陣線,因為編碼的目的就是 neutralize data,保證其不會被解釋為代碼。上面提到過,在某些情況下,需要用校驗來輔助編碼。應(yīng)該在 outbound 處使用編碼和校驗,因為只有當(dāng)輸入展示到頁面中時,你才知道要編碼或校驗的上下文。
作為第二陣線,你應(yīng)該使用 inbound 校驗來凈化或是拒絕那些明顯非法的數(shù)據(jù),例如:使用 javascript: 協(xié)議的鏈接。雖然僅憑這并不能保證絕對安全,但是如果第一陣線由于失誤或是錯誤導(dǎo)致沒有正確進(jìn)行,第二陣線就成了有用的預(yù)防措施。
如果能一貫的落實這兩道防線,你的網(wǎng)站應(yīng)該不會遭受 XSS 攻擊。但是,考慮到開發(fā)和維護(hù)整個網(wǎng)站的復(fù)雜性,要想僅通過對輸入進(jìn)行安全處理就達(dá)到絕對安全是很困難的。作為第三道防線,你應(yīng)該使用馬上就要講到的內(nèi)容安全策略(Content Security Policy)。
Content Security Policy(CSP)僅憑對輸入進(jìn)行安全處理來防御 XSS 的不足之處在于一個安全上的小失誤就可以威脅到整個網(wǎng)站。被稱為內(nèi)容安全策略(CSP)的 WEB 標(biāo)準(zhǔn)可以降低這一風(fēng)險。
CSP 用來限制瀏覽器 viewing your page 保證其只能使用從可信任的源下載的資源。資源可以是腳本、樣式表、圖片或是頁面引用的其它類型文件。也就是說,即使攻擊者成功在網(wǎng)站中注入了惡意代碼,CSP 可以防止其被執(zhí)行。
CSP 可以用來強(qiáng)制實施下面的規(guī)則:
No untrusted sources:外部資源只能從一個明確定義的可信源集合中加載
No inline resources:不執(zhí)行行內(nèi)(inline) JavaScript 和 CSS
No eval:不可以使用 JavaScript 函數(shù) eval
在下面的例子中,攻擊者成功在某個頁面中注入了惡意代碼:
Latest comment:
如果定義了合理的 CSP 策略,瀏覽器就不會加載和執(zhí)行 malicious-script.js,因為 http://attacker/ 不會出現(xiàn)在可信源集合中。在這種情況下,即使網(wǎng)站沒能正確對輸入進(jìn)行安全處理,CSP 策略可以防止漏洞造成任何損害。
即使攻擊者注入的不是外部文件,而是行內(nèi)腳本代碼,合理的 CSP 策略仍可以禁止行內(nèi) JavaScript,從而防止漏洞造成任何傷害。
默認(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 頭部語法如下:
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á)式語法如下:
protocol://host?name:port?number
主機(jī)名可以以 打頭,表示所提供的主機(jī)名的任何子域都被允許。類似的,端口號也可以是 ,表示所有端口都被允許。此外,協(xié)議和端口號可以省略。也可以只指定協(xié)議,從而實現(xiàn)要求所有資源都通過 HTTPS 加載。
除此之外,來源表達(dá)式還可以是下面四個有特殊含義的關(guān)鍵詞之一(包含引號):
"none":不允許該類型資源
"self":允許從提供當(dāng)前頁面的主機(jī)下載資源
"unsafe-inline":允許在頁面中嵌入資源,例如:行內(nèi) 元素, 元素和 javascript: URL。
"unsafe-eval":允許使用 JavaScript eval 函數(shù)
需要注意的是,一旦啟用 CSP,默認(rèn)情況下,行內(nèi)資源和 eval 是自動被禁止的。使用它們的唯一方式就是使用 "unsafe-inline" 和 "unsafe-eval"。
Content?Security?Policy: script?src "self" scripts.example.com; media?src "none"; img?src *; default?src "self" http://*.example.com
在上面的例子當(dāng)中,頁面遵循如下限制:
只能從當(dāng)前頁面所在主機(jī)和 scripts.example.com 加載腳本
不允許加載音頻和視頻文件
可以從任何主機(jī)加載圖片文件
其它類型的資源可以從當(dāng)前頁面所在主機(jī)和 example.com 的任何子域加載
截止到 2013 年 6 月,CSP 處于 W3C candidate recommendation。已經(jīng)有瀏覽器實現(xiàn)了,但是部分功能只特定于某個瀏覽器。特別是,瀏覽器之間使用的 HTTP 頭部是不同的。在使用 CSP 之前,請先查閱對應(yīng)瀏覽器的文檔。
總結(jié) 總結(jié):XSS 概述XSS 是一種代碼注入攻擊,因為沒有安全的處理用戶輸入而導(dǎo)致。
一次成功的 XSS 攻擊可以使攻擊者在受害者瀏覽器中執(zhí)行惡意 JavaScript 代碼。
一次成功的 XSS 攻擊損害了網(wǎng)站及其用戶的安全。
總結(jié):XSS 攻擊
主要存在三種 XSS 攻擊:
存儲型 XSS,惡意輸入來自網(wǎng)站的數(shù)據(jù)庫
反射型 XSS,惡意輸入來自受害者發(fā)起的請求
DOM XSS,漏洞存在于客戶端代碼,而不是服務(wù)端代碼
上面三種 XSS 攻擊雖然實現(xiàn)方式不同,但是如果成功,效果相同。
總結(jié):防御 XSS
防御 XSS 最重要的方法就是對用戶輸入進(jìn)行安全處理:
大多數(shù)時候,對頁面中展示的用戶輸入都要進(jìn)行編碼
在一些場景下,需要用校驗代替或是輔助編碼
進(jìn)行安全處理時,需要考慮到用戶輸入插入點(diǎn)的上下文
為了防御所有類型的 XSS 攻擊,對輸入進(jìn)行的安全處理既要在客戶端進(jìn)行,也要在服務(wù)端進(jìn)行
當(dāng)安全處理失敗時,內(nèi)容安全策略(CSP)提供了額外的防御層
附錄 術(shù)語需要指出的是,用于 XSS 分類的術(shù)語存在一些重疊:DOM XSS 攻擊同時也是存儲型或是反射型;它并不是一個獨(dú)立的攻擊類型。目前沒有廣泛接受的不存在重疊的分類術(shù)語。不考慮術(shù)語,區(qū)分各種攻擊最重要的就是確定惡意輸入來自哪里以及漏洞存在哪里。
轉(zhuǎn)自http://zicai.github.io/
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/11193.html
摘要:層疊樣式表二修訂版這是對作出的官方說明。速查表兩份表來自一份關(guān)于基礎(chǔ)特性,一份關(guān)于布局。核心第一篇一份來自的基礎(chǔ)參考指南簡寫速查表簡寫形式參考書使用層疊樣式表基礎(chǔ)指南,包含使用的好處介紹個方法快速寫成高質(zhì)量的寫出高效的一些提示。 迄今為止,我已經(jīng)收集了100多個精通CSS的資源,它們能讓你更好地掌握CSS技巧,使你的布局設(shè)計脫穎而出。 CSS3 資源 20個學(xué)習(xí)CSS3的有用資源 C...
摘要:網(wǎng)絡(luò)黑白一書所抄襲的文章列表這本書實在是垃圾,一是因為它的互聯(lián)網(wǎng)上的文章拼湊而成的,二是因為拼湊水平太差,連表述都一模一樣,還抄得前言不搭后語,三是因為內(nèi)容全都是大量的科普,不涉及技術(shù)也沒有干貨。 《網(wǎng)絡(luò)黑白》一書所抄襲的文章列表 這本書實在是垃圾,一是因為它的互聯(lián)網(wǎng)上的文章拼湊而成的,二是因為拼湊水平太差,連表述都一模一樣,還抄得前言不搭后語,三是因為內(nèi)容全都是大量的科普,不涉及技術(shù)...
摘要:面試如何防騙一份優(yōu)秀的前端開發(fā)工程師簡歷是怎么樣的作為,有哪些一般人我都告訴他,但是他都不聽的忠告如何面試前端工程師 更多資源請Star:https://github.com/maidishike... 文章轉(zhuǎn)自:https://github.com/jsfront/mo... 3月份前端資源分享 1. Javascript 使用judge.js做信息判斷 javascript...
摘要:本系列教程翻譯自,系列共有九篇,本文譯自第五篇。因此,本系列教程關(guān)鍵的第五章用來討論可能面臨的安全問題以及它們是如何影響到整體的安全性的。一些必要的安全措施包括使用非特權(quán)用戶運(yùn)行容器。本圖中列舉了幾個用于維護(hù)和授權(quán)的安全性。 本系列教程翻譯自 Flux7 Docker Tutorial Series,系列共有九篇,本文譯自第五篇 Part 5: Docker Security。該系列所...
閱讀 2113·2021-11-16 11:45
閱讀 1184·2021-10-22 09:53
閱讀 4002·2021-09-07 10:26
閱讀 1209·2021-09-06 15:00
閱讀 2073·2019-08-28 18:09
閱讀 2795·2019-08-26 14:06
閱讀 3934·2019-08-26 13:48
閱讀 1295·2019-08-26 12:11