ASP.NET Forms驗證的安全性問題研究——為什么加密代碼需要配置為服務
申明:這個帖子不是要你去干啥壞事,就是提醒一下你可能會遇到的安全性問題。
ASP.Net提供了內置的登錄驗證,最為常用的就是Forms驗證。講解如何配置的文章非常多,這里就不再講如何配置使用這個驗證的方式了。下面講講其在安全性上存在的一些被忽視的問題。其實它本身沒有問題,而使用的方式上會附帶出來一些問題。
本文將分三部分講實際應用中將會遇到的安全性問題,并且加以研究,并嘗試提出解決方案。
一、簡單的Forms被破解危機
二、垂直劃分站點的Forms被破解危機
三、危機將帶來什么后果
一、簡單的Forms被破解危機
最簡單的一個Forms驗證,在web.config下配置節點:
<authentication mode="Forms"> <forms name=".MyCookies"></forms> </authentication>
編寫一個幫助類:

建立站點SiteA
建立站點SiteB
在SiteA的頁面設置Cookie:
CookieHelper.Set("yurow", "123123");
OK!這樣,就在SiteA建立了一份Cookie,這個本身并沒有任何問題。但是我們往往忽視了一些問題,大家看到,我在CookieHelper類里提供了Decrypt方法,這個方法可以解密Cookie。問題就在于這里!怎么?不知道?那就讓貧道來跟施主解釋。在這樣的網站下,我進行以下的操作步驟:
1、我注冊一個帳號;
2、我用這個帳號登錄(方便起見,我使用Firefox);
3、打開Firebug,并且啟用該網站的網絡監視;
4、刷新登錄后的頁面;
5、在該頁面被監視的HTTP頭中可以看到一段Cookie密文。例如:
.MyCookie=32DDE0B4E858248037E4D082EF7E9C9BC607B7AA878F8DD
7DE7C13630A5A38FD9A9DA89B709E79F97D05DEEFC9D55A45D29051D
66955439055D01476E8659E34ABDB42FA0018020194F26618FE74E11B
這樣的字符串。
OK,在該網站的操作到此為止。現在在SiteB中建立一個頁面,中間加上一個輸入框,一個按鈕,并且編寫以下事件:

把上面的Cookie密文,等于后面的部分復制到SiteB頁面中,點解密按鈕,看到了什么?
Version:1 Name:yurow Expiration:2009-9-23 19:12:44 IssueDate:2009-9-22 19:12:44 IsPersistent:True Expired:False UserData:123123 CookiePath:/
怎么樣?所有的信息都被解密了!不過好像高興地太早了,解密了自己的數據有啥用啊,又拿不到別人的Cookie密文。暫且打住,接下來先講垂直劃分站點安全隱患。
二、垂直劃分站點的Forms被破解危機
垂直劃分站點其外在表現一般是多域名的N多站點。比如博客園的space.cnblogs.com,news.cnblogs.com等等。而上面第一部分的描述中,貧道似乎漏掉了關于設置machineKey的問題,那是因為要留到這里來講,要是上面都說了,現在講啥?
是的,我們是可以在web.config中設置
這樣的節點。如果在A站點設置了這個,除非B站點也設置相同KEY的節點,否則SiteB將無法正確解密SiteA產生的Cookie密文。似乎一般的網站都設置了這個,好像我們不需要為此而擔心了嘛!
是的,一般情況是這樣的。但是,很多公司的人員流動性是較大的,而且垂直分割的站點中,可以接觸到web.config的人我相信是非常多的。這就能讓某些人,(當然,不包括貧道,嘿嘿)就可以比較容易地拿到這個關鍵的數據。這個數據能干啥?那還用說啊?我在SiteB我自己建立的站點的Web.config也配置上這個節點,那就可以輕易解開目標網站的Cookie密文。為了保證這方面的安全性不得不把Cookie加密解密部分做成服務,不但容易更新,而且讓盡可能少的人接觸,防止安全性上的問題被放大。要不然,有個人離職啊,或者電腦中毒啊,最好還是要改動改動machineKey,否則呢?否則就有可能出問題。出什么問題呢?這就是下面要講的。
三、危機將帶來什么后果
加密的Key泄露,會帶來什么后果?后果很嚴重。從上面的例子可以看到這個站點Cookie密文包含的關鍵信息。而是要CookieHelper類,根據這些關鍵信息,我們就可以輕易地制造出一個Cookies密文。而拿這個Cookies密文寫入目標網站的Coookies中,那么就會認為你已經登錄。并且這個(這里我們用的驗證可能是Cookie保持的用戶名或者ID一類的東西。)用戶名可以隨意偽造,也就是可以用不存在的用戶進行發帖!如果你每次在發帖等操作進行驗證無疑是增加了服務器的負擔,而最好的辦法當然是不外泄加密KEY了。這種方式不當可以偽造用戶(幾個月前我專門試過一些站點是可以的,而偽造用戶發帖會造成該論壇的某個版面甚至首頁無法訪問),而且可以偽造成管理員的帳號。不難想象,如果用其它用戶的帳號或者管理員的帳號進行隨意發帖,會造成怎么樣的惡劣影響了吧?
OK,意識到問題了吧?那貧道就不再多說了。