直播中
攻擊網(wǎng)站通常都是通過跨站指令代碼(Cross-siteScripting)攻擊網(wǎng)站的后臺漏洞。它和信息隱性代碼攻擊 (SQLInjection)攻擊的目標不同。前者是透過從Web前端輸入信息至網(wǎng)站,導致網(wǎng)站輸出了被惡意控制的網(wǎng)頁內(nèi)容,使得系統(tǒng)安全遭到破壞。而后者則是輸入了足以改變系統(tǒng)所執(zhí)行之SQL語句內(nèi)容的字串,使得系統(tǒng)最終達到攻擊的目的。
但從更一般性的角度來看,這兩種攻擊手法基本上是相通的。他們都是透過系統(tǒng)對于輸入信息的毫無檢核或是檢核不足,利用刻意制造出來的輸入信息,來讓系統(tǒng)產(chǎn)生不在預期內(nèi)的有害行為。
過濾輸入信息有效嗎?
因此,當要防備這類型的攻擊時,大多數(shù)人直覺想到的方式,便是對使用者所提供的輸入信息進行過濾。在面對信息隱性代碼攻擊時,許多人會想到針對輸入信息中,可能會含有的SQL關鍵字串或字元進行過濾,例如,使用者的輸入信息中若含有單引號,那么便可能制造出危險的SQL語句,因此,許多程序設計者便會想到要針對單引號進行escape,來杜絕信息隱性代碼的攻擊。而這種escape或過濾的方法,其實不難規(guī)避,例如,針對單引號,有心人士還是可以利用信息庫服務器支持的特殊寫法,將單引號字元替換成其他的型式,使得escape的程序失效。
同樣的,面對跨站指令代碼攻擊,許多程序設計者首先會想到的,也是針對有可能造成疑慮的使用者信息進行過濾。例如,針對字元、SCRIPT字串進行過濾,倘若使用者的輸入信息中含有可疑的字元或字串時,則進行改寫或禁止使用。這種針對特定的目標進行篩選過濾的方式,可以稱為黑名單式的過濾,因為,程序是先列出不能出現(xiàn)的對象清單,然后進行過濾。
當然,在跨站指令代碼攻擊中,如果想利用黑名單式的過濾方式,當然也是行不通的。因為,單是&#106avascript這個字串,有心人士就可以產(chǎn)生在HTML中等價、但是字串形式不為&#106avascript的寫法。例如,使用#x的十六進位字元表示方式,來表示&#106avascript這個字串中的每一個字元。由于改寫形式太多了,這使得想要利用黑名單的方式,幾乎是不可能的事。
因此,無論何種攻擊,想要有更嚴密的防備,在信息的過濾上,都應該采取白名單式的過濾。而這正和黑名單相反,它不是列出不被允許的對象,而是列出可被接受的對象。
以正向表列的方式管制
在面對信息隱性代碼攻擊時,我們建議針對每個欄位都明確定義出它該有的形式,例如日期欄位就只能出現(xiàn)數(shù)字和斜線字元,而ID欄位,僅能出現(xiàn)英文字母及底線字元等等。如此一來,想要透過信息植入有害的組成,就不是那么容易可以辦到了。
對于同樣需要對輸入信息進行檢核的跨站指令代碼攻擊來說,要做到輸入信息的過濾,最好的策略也是基于白名單來過濾。例如,允許使用者輸入HTML語法的地方,若僅允許輸入圖片,則可開放形式的輸入,其余則否。這么一來,想要規(guī)避過濾的規(guī)則,難度就比較高了。
當然,采取較嚴格的白名單政策,程序在撰寫難度上比較高,此外,允許使用者信息輸入的形式也就更為受限,但這是為了安全必須付出的代價。
將網(wǎng)頁內(nèi)容編代碼,提升防御力
除了針對輸入信息進行白名單式的過濾之外,針對輸出的頁面內(nèi)容進行編代碼,也是實務上能派上用場的技巧。輸入信息的過濾是針對可疑的信息進行防范,而針對輸入進行編代碼,則是讓可能造成危害的信息變成無害。
慶幸的是,有許多程序語言都推出了為了防范跨站指令代碼攻擊的程序庫,協(xié)助程序設計者針對HTML輸出內(nèi)容進行編代碼。例如PHP的 htmlentities()或是htmlspecialchars()、ASP的Server.HTMLEncode()、ASP.NET的 Server.HtmlEncode()等等。讓專門的程序庫來處理輸入內(nèi)容的編代碼,也可以減少程序設計者自行開發(fā)的額外成本,同時也能提供更為完善的防備考慮。而像微軟,更提供了一個名為MicrosoftAnti-CrossSiteScriptingLibrary的程序庫,提供了各種HTML、 &#106avascript、URL、XML、VBScript的過濾及編代碼機制。如此一來。便可以透過這一套程序庫,將來自于使用者輸入的字串,或是以使用者輸入字串為基礎的輸出字串進行轉(zhuǎn)換,成為單純的文字,而不含可于瀏覽器上執(zhí)行script程序,因此能夠降低遭受到攻擊的風險。
徹底分析程序代碼可能的弱點
在撰寫程序時,如果能夠留意輸入信息的輸出,以及輸出頁面內(nèi)容的編代碼,相信可以增加不少防范的強度。但是,針對既有的程序代碼,倘若存在跨站指令代碼攻擊的漏洞,又該如何察覺并進行防范呢?基本上,你可以采取一個系統(tǒng)性的分析方法。
若想要審視你的程序代碼是否具有跨站指令代碼攻擊的問題,根據(jù)《WritingSecureCode》一書中的建議,首先,你必須要列舉出你的網(wǎng)站程序中所有接收自使用者端送出信息的地方。所謂使用者端的信息,包括了你的網(wǎng)站程序所讀取表格中的每個欄位、來自于網(wǎng)址中的查詢字串、cookies 的值、HTTP的標頭等等。因為,不要忘了,所有來自于使用者的信息“都是邪惡的”。
找到了每個接收使用者端信息的地方后,便可以逐一追蹤每筆信息在應用程序中的流向,檢驗所接收到的信息,最終是否會反映到輸出的頁面結果中。這中間,你可能直接把接收來的信息稍微加工后,就當做輸出結果送出去了也有可能,先把所接收到的信息儲存在信息庫或檔案中,于日后才做為輸出結果送出。
倘若,你所找出來的信息最終會成為輸出頁面的一部份,那么,你就應該檢查這份信息是否足夠“乾凈”,也就是說,你是否有針對這份信息進行足夠的過濾或在輸出時加上了編代碼的動作。倘若沒有,那么,這份信息就有可能成為跨站指令代碼攻擊被發(fā)動的點。也就是說,你應該針對這份信息的輸入及輸出,進行相對應的處理。透過以上的步驟,有助于你審視既有的程序代碼的問題。
除此之外,檢查你的&#106avascript程序中,動用到innerHTML以及document.write()的地方,是否有安全疑慮,也會有幫助。另外,在&#106avascript程序中使用eval(),同樣有可能造成安全問題。eval()函數(shù)允許在瀏覽器上直接將傳入該函數(shù)的參數(shù)做為 JavaScritp算式或是可執(zhí)行的語句,動態(tài)的評估算式之值或是加以執(zhí)行。倘若,eval()所接收的參數(shù)之值,是來自于使用者輸入的部份信息,那么可以造成的危機就大了,因為這意謂著,使用者有機會控制透過eval()所執(zhí)行的&#106avascript語句,系統(tǒng)安全形同門戶洞開。這也就是近來,為什么許多守則都建議不要使用eval()的原因,因為太容易形成安全性的漏洞了。
跨站指令代碼攻擊的確是十分難以防守的攻擊形式,但不小心,就有可能造成頗大的傷害。遺憾的是,還是有不少Web應用程序設計者并沒有小心的提防,希望可以透過這里,帶給你基本的認知。關于跨站指令代碼攻擊其中還充滿許多高深的探討和技巧,不在本文范圍之內(nèi),建議有興趣者自行鉆研之。