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