跨站腳本攻擊深入解析之:漏洞利用過程
原創【51CTO.COM 獨家特稿】跨站腳本的名稱源自于這樣一個事實,即一個Web站點(或者人)可以把他們的選擇的代碼越過安全邊界線注射到另一個不同的、有漏洞的Web 站點中。當這些注入的代碼作為目標站點的代碼在受害者的瀏覽器中執行時,攻擊者就能竊取相應的敏感數據,并強迫用戶做一些用戶非本意的事情。
在本文的上篇中,我們詳細介紹了當前Web應用所采取的安全措施,如同源策略、cookie安全模型以及Flash的安全模型;而本文將介紹跨站腳本漏洞利用的過程,并對HTML注入進行深入分析。
一、跨站腳本漏洞利用的過程
現在,您已經熟悉了瀏覽器中的各種安全技術,下面我們開始設法利用XSS規避這些安全技術。XSS的主要目標是通過把攻擊者選擇的JavaScript、VBScript或者其它為瀏覽器所接受的腳本語言注入到(放進)某些Web應用程序之中。只要攻擊者可以將腳本植入有弱點的Web應用程序中的任何地方,瀏覽器就會認為這個腳本是來自該有弱點的Web應用程序,而非非出自攻擊者之手。
這樣的話,該腳本就能夠在這個有弱點的Web應用程序的域中運行了,并能進行下列活動:有權讀取那個有弱點的Web應用程序使用的Cookie;能夠看到該有弱點的Web應用程序提供的頁面的內容,甚至能將它們發送給黑客;改變有弱點的Web應用程序的外觀;回調運行有弱點的Web應用程序的服務器。
大體上,跨站點腳本攻擊可以分為三步進行:
1.HTML注入。我們將介紹把腳本注入到Web應用程序的各種可能的方法。所有HTML注入范例只是注入一個JavaScript彈出式的警告框:a_lert(1)。
2.做壞事。如果您覺得警告框還不夠刺激,我們將討論當受害者點擊了一個被注入了HTML代碼的頁面鏈接時攻擊者能作的各種的惡意事情。
3.誘捕受害者。我們論述如何強制或者誘使受害者執行惡意JavaScript代碼。
一、HTML注入簡介
將HTML和(更為重要的)腳本代碼注入Web應用程序的方法簡直太多了。如果某個Web應用程序的HTTP響應中“照搬”了在HTTP請求中輸入的內容,例如尖括號、圓括號、句號、等號等,那么說明這個Web應用程序和域具有HTML注入漏洞,并且該漏洞十有八九可以用于XSS。
本節將為讀者介紹最常見的HTML注入方法,但是無法包括所有方法,因為這些方法是在太多了。對于大多數小型至中型的網站來說,這些技術很可能仍然奏效。只要有耐心,那么您或許也能夠使用其中的一種技術成功應用于一個大型Web站點。
下面我們將分門別類的介紹各種注入方法。
二、傳統的反射式和存儲式HTML注入
傳統的XSS攻擊是一種反射式的HTML注入攻擊,借此,一個Web應用程序接受在HTTP請求中的用戶輸入。該Web應用程序會返回一個HTTP響應,其主體中將包含原封不動的用戶輸入。如果該服務器的響應跟用戶的原始輸入完全一致,那么這些用戶輸入就會被瀏覽器當作有效的HTML、VBScript或者JavaScript進行解釋。考慮下列的服務器端的PHP代碼:
< html > < body > < ?php if (isset($_GET{'UserInput'})){ $out = '您輸入的內容為: "' . $_GET{'UserInput'} . '".'; } else { $out = '< form method=”GET”>請在此輸入內容: '; $out .= '< input name="UserInput" size="50" >'; $out .= '< input type="submit" >'; $out .= '< /form >'; } print $out; ? > < /body > < /html > |
圖1展示了這段代碼放置到http://publicpages.daxue.edu/~someuser/MyPhp.php上后,客戶端看到的頁面內容。
![]() |
圖1 一個簡單的PHP腳本,用以接收用戶輸入(MyPhp.php) |
當用戶點擊“提交查詢”按鈕時,就會生成下列GET請求:
http://public-pages.daxue.edu/~someuser/MyPhp.php?input=hahaha
這個PHP應用程序看到用戶輸入的“hahaha”后,將響應一個頁面,如圖2所示。
![]() |
圖2 用戶輸入“hahaha”后MyPhp.php回復的響應 |
下面顯示的是圖2中看到的頁面的HTML 源代碼,為醒目起見用戶輸入的內容這里以藍色字體顯示。
您輸入的內容為: "hahaha".
#p#
注意,實際上這里用戶可以輸入任何東西,例如〈 script 〉 a_lert( 1 )〈 / script 〉、〈 body onload = a_lert( 1 ) 〉、〈 img src = x onerror = a_lert( 1 ) 〉 或別的東西來把JavaScript代碼注入到該頁面。如果輸入 的話,將向服務器發送下列GET請求:
http://publicpages.daxue.edu/~someuser/MyPhp.php?input=
如前所述,這個PHP應用程序只是把用戶輸入放到返回的響應頁面中。這時候瀏覽器會把這些用戶輸入的內容當作JavaScript指令,同時認為該腳本來自服務器,這可真是應了那句老話“拿著雞毛當令箭”了,所以瀏覽器就會執行這些JavaScript代碼。圖3展示了用戶看到的樣子。
![]() |
圖3 用戶輸入“ ”后MyPhp.php回復的響應 |
上圖中顯示的頁面的源代碼如下所示,其中用戶輸入用藍色字體表示。
您輸入的內容為: " ".
這是將 注入http://public-pages.daxue.edu/~someuser/MyPhp.php得到的結果。這個例子是一種典型的反射式的HTML注入,因為用戶在HTTP請求中發送JavaScript代碼,同時Web應用程序立即響應(反射回)一個完全相同的JavaScript代碼。只要用戶單擊了下列鏈接,這個腳本就會執行:
http://publicpages.daxue.edu/~someuser/MyPhp.php?input=
從攻擊者的角度來看,利用注入的ML代碼讓惡意的web頁面完成單擊或者指定次數的點擊是非常重要的。假設前面的PHP應用程序只接受POST請求,而不接受GET,如下所示:
< html >
< body >
< ?php
if (isset($_POST{'UserInput'})){
$out = '您輸入的內容為: "' . $_POST{'UserInput'} . '".';
} else {
$out = '< form method="POST" >請在此輸入內容: ';
$out .= '< input name="UserInput" size="50" >';
$out .= '< input type="submit" >';
$out .= '< /form >';
}
print $out;
? >
< /body >
< /html >
在這種情況下,攻擊者無法像上面的GET請求那樣直接通過誘騙受害者點擊一個鏈接來注入HTML代碼;現在,他們必須采取一些額外的步驟。為此,攻擊者可以創建下列HTML頁面:
< html >
< body >
< form name="evilForm" method="POST ction="http://publicpages.
daxue.edu/~someuser/MyPhp.php">
< input type="hidden" name="input" value="〈 script 〉a_lert ( 1 )〈 / script 〉" 〉
< script >
document.evilForm.submit()
< /script >
< /body >
< /html >
document.evilForm.submit()
document.evilForm.submit()
document.evilForm.submit()
當用戶單擊了指向上述HTML頁面的鏈接時,就會對http://public-pages.daxue.edu/~someuser/MyPhp.php進行HTML注入。當然,攻擊者也能利用HTML注入干別的壞事,而不僅僅象征性地調用一個JavaScript的彈出窗口。“第二步:做壞事”部分將解釋攻擊者除了彈出一個窗口外還能做些什么。
存儲式HTML注入跟反射式HTML注入非常相似,唯一區別在于攻擊者將腳本植入Web應用程序后,這些腳本會被Web應用程序存儲到一個可以檢索的地方。例如,對于允許用戶張貼和閱讀消息的網絡論壇,攻擊者可以在張貼消息時注入HTML代碼,然后其它用戶閱讀這則含有腳本的消息時,其中的腳本就會執行。
三、定位存儲式和反射式HTML注入點
為了尋找存儲式和反射式HTML注入點,可以嘗試在所有表單輸入以及GET或者POST請求的所有參數中注入腳本。我們要假設參數/值對中的值都可能有漏洞。甚至嘗試在新生成的參數中注入HTML代碼,如下所示:
〈 script 〉 a_lert ( ' parameter ' )= 不起作用,因為這些測試字符串并不出現在響應的HTML主體區。舉例來說,假如向http://search.engine.com/search?p= 發送的這個請求返回的響應中,其預填充表單字段內是我們的HTML注入字符串,如: