世界第一個XSS攻擊蠕蟲的原理
Kamkar近日在Github上發布了一款軟件并附上指導教程,教你如何修改無人機設置,使之認證失效并對其進行攻擊。該Perl軟件名為SkyJack,運行在 Raspberry Pi上并使用其它開源軟件來劫持飛行器。
這一新聞讓我對此人非常敬佩,翻譯了他關于如何在MySpace上實現第一個XSS工具蠕蟲代碼的說明,翻譯的過程也是對XSS攻擊的一次學習過程和對黑客精神的震撼。
1)Myspace 屏蔽了很多標志符。事實上,他們只允許<a>,<img>類,和<div>類,或許還有其他一些(例如,<embed>類)。他們不允許<script>類,<boday>類,onClinks,onAnythings,帶javascript的<href>類。但是某些瀏覽器(IE,部分Safari和其他)允許CSS標識符中帶有javascript.即便如此,我們也需要javascript能夠正常運行。例如:
2)我們不能對Div 標識符使用引號,因為我們已經使用了單引號和雙引號。這讓JS的編程非常困難。為了讓JS運行,我們使用表達式來保存JS代碼和通過函數名來運行。例如,
3)真棒,現在我們可以執行帶單引號的Javascript代碼了。但是,MySpace網站禁止了關鍵字”javascript”.為了實現目的,某些瀏覽器認可“java\nscript”(就是java<NEWLINE>script 為”javascript”.例如,
4)很好,當我們讓單引號其效果后,我們有時還需要雙引號。我們將引號轉義,例如,“foo\”bar”. Myspace 打擊我一下,他們禁止了所有轉義,無論是雙引號還是單引號。但是,我們依然可以在javascript 中將10進制翻譯成ASCII來生成引號。例如,
5)為了將代碼發布到真正展示的用戶簡介頁面上,我們需要得到這些頁面源碼。為了獲得包含客戶ID的瀏覽頁面的源碼,我們可以使用document.body.innerHTML。但是Myspace再次打擊了我,他們禁止了標識“innerHTML “.我們可以用eval函數來拼接兩個字符串組成“innerHTML”.例如,
6)是時候訪問其他頁面了。通常我們使用”iframes”格式,但是即便是隱藏的,“iframes”并不有效,會讓用戶明顯感到有其他東西在運行。所以我們采用AJAX(XML-HTTP)來讓實際用戶產生HTTP GET和POST到頁面。當然,Myspace禁止了XML-HTTP請求所必需的敏感詞“onreadstatechange”,我們再次使用EVAL來拼接生產該敏感詞。另外,要XML-HTTP在myspace 有效果還需要Cookies.例如,
7)是時候在用戶簡介上執行GET來獲得他們的Hero列表。我們不必刪除任何heros,我們僅僅是將自己添加到已有的列表中。如果我們GET他們的簡介,我們就能獲取他們的列表并且保存備用。綜上所述,用XML-HTTP來實現是簡單的,除非我們要獲得當前瀏覽該簡介的用戶ID。正如我說的,我們可以從獲取頁面源碼來實現。好了,我們需要在頁面中搜索關鍵詞。但是如果我們這么做,我們會發現自己,因為我們的代碼包含相同的關鍵字。我們再次使用eval()來拼接字符串來避免這個問題。
8)到此,我們有了heros列表。第一,讓我們在addFriends頁面執行一個XML-HTTP
POST請求把自己加到朋友列表中。歐不,這樣不行,為啥?我們正在profile.myspace.com頁面,但是POST動作要在www.myspace.com頁面去運行。但是XML-HTTP不允許在不同域名間實現GETs/POSTs。為了避免這樣,我們要去同一URL而不是在www.myspace.com頁面。你可以繼續從www.myspace.com 瀏覽簡介,通過在同一域名中重新裝載運行我們執行POST的頁面。例如,
9)最后我們執行POST請求。但是,當我們發送POST請求后沒有添加用戶。為啥?原來Myspace為一個預POST頁面生產了一個哈希值,例如在“你確定添加該用戶為朋友頁面”。如果這個哈希值沒有與POST一同發生的話,這個POST不會成功執行。為了避免這樣,在添加用戶前我們模擬一個瀏覽器去GET該頁面,通過分析源碼來取得該哈希值,然后帶上該哈希值去執行POST請求。
10)一旦POST請求結束,我們還要添加一個Hero和執行代碼。這段代碼執行完后就會到hero的同一地方,所以我們只有一個POST請求就可以了。但是,我們需要預GET一個頁面來得到一個新的哈希值。但是,第一我們不得不重新生成我們要POST的代碼。最簡單的辦法是獲取我們要的頁面源碼,分析出代碼后在發出POST請求。到此為止萬事俱備。為了POST請求正在運行我們需要對代碼做編碼或者轉義。可惡,還是不能運行。顯然,javascript的URL-Encoding和escape() 函數不能轉義所以必須要的代碼。所以我們不得不人工來做這些工作確保必要的代碼正確轉義。我們添加了一條“but most of all ,samy is my hero”到代碼。哇,我們自我復制了一個蠕蟲代碼。
11)還有其他限制,例如,最大長度,必需緊湊的代碼,沒有空格,混亂的命名,重復使用的函數等等。