摘要:重要:ASP.NET安全漏洞
[原文發表位置]:Important: ASP.NET Security Vulnerability
[原文發表時間]:2010/9/18 4:23 AM
幾個小時前,我們發佈了一個關於ASP.NET安全漏洞的Microsoft 安全警告,該漏洞存在於目前所有的ASP.NET版本。
該漏洞是在上週五的一個安全會議上發現的。我們建議所有的客戶立即採取補救措施(見下文)來預防攻擊者利用此漏洞攻擊您的ASP.NET站點。
9月20日更新: 我發佈了另一篇部落格,其中包含關於此問題的一些FAQ,您可以從這裡閱讀。
9月24日更新: 我發佈了另一篇部落格,關於在補救措施中啟用URLScan,您可以從這裡閱讀。
通過該安全漏洞能夠做什麼?
潛在的攻擊者可以通過該漏洞來下載ASP.NET 應用程式中的檔案,比如Web.config (它經常包含一些敏感數據)。
通過進一步利用該漏洞,攻擊者可以解密發送到客戶端的加密數據(如保存在頁面中的ViewState)。
如何利用該漏洞
要理解該漏洞的原理,您需要先瞭解密鑰神諭,即向一個加密系統發出問題,而它會給暗示。目前的這個漏洞就扮演了這樣一個跳板,可以讓攻擊者不斷向伺服器發送加密過的數據,通過檢測傳回的錯誤碼瞭解它是否能被解密,經過許多次嘗試後,攻擊者可以得到足夠多的經驗來解密剩餘的加密內容。
避免該漏洞的臨時方案
一個來避免該漏洞的替代辦法就是啟用ASP.NET的 <customErrors>,並且對它進行顯式配置,使得不管伺服器發生什麼樣的錯誤都總是傳回相同的錯誤頁。通過將不同的錯誤映射到同一個錯誤頁,可以避免讓攻擊者辨別在伺服器上產生的不同錯誤型別。
注意: 僅僅將customErrors設置為RemoteOnly是不夠的。您必須確認所有的錯誤都傳回相同的錯誤頁,這需要您顯示地設置customErrors節點的defaultRedirect屬性,並確認它沒有只針對特定的狀態碼。
在ASP.NET V1.0 到 V3.5版本上啟用臨時方案
如果您正在使用ASP.NET 1.0, ASP.NET 1.1, ASP.NET 2.0 或者 ASP.NET 3.5,那麼您可以通過下面的步驟來設置 <customErrors> 將所有的錯誤映射到相同的錯誤頁。
1) 編輯ASP.NET 應用程式根目錄下的Web.config檔案,如果檔案不存在,則在應用程式的根目錄下建立一個。.
2) 建立或修改 <customErrors> 節點,並做如下設置:
<configuration>
<system.web>
<customErrors mode="On" defaultRedirect="~/error.html" />
</system.web>
</configuration>
3) 您可以在您的程序增加一個適當的error.html檔案(可以包含您喜歡的任意內容),當應用程式發生任何伺服端錯誤時就會顯示這個頁面。
注意:一個重要的事情就是customErrors節點的mode屬性必須設置成 「On」,這樣所有的錯誤才會被重定向到設定的錯誤頁。並且必須不對它指定任何錯誤狀態碼——也就是說 <customErrors /> 節點沒有任何子節點。這是做是為了避免攻擊者能夠區分伺服器發生的錯的型別,並且預防資訊洩露。
在ASP.NET V3.5 SP1或 ASP.NET 4.0 版本上啟用臨時方案
如果您正在使用ASP.NET 3.5 SP1 或 ASP.NET 4.0,則可以通過下面的步驟來設置 <customErrors> 將所有的錯誤映射到相同的錯誤頁。
1) 編輯ASP.NET 應用程式根目錄下的Web.config檔案,如果檔案不存在,則在應用程式的根目錄下建立一個。.
2) 建立或修改 <customErrors> 節點,並作如下設置,.NET 3.5 SP1 and .NET 4.0中還需要設置redirectMode=」ResponseRewrite」:
<configuration>
<system.web>
<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/error.aspx" />
</system.web>
</configuration>
3) 您可以在您的程序增加一個適當的error.aspx檔案(可以包含您喜歡的任意內容),當應用程式發生任何伺服端錯誤時就會顯示這個頁面。
4) 我們推薦您在Error.aspx檔案的伺服端Page_Load() 事件中增加下面的程式碼,設計一個小小的隨機延遲,這將能幫助混淆錯誤。
VB 版本
下面是您可以使用的VB版本的Error.aspx ,在程式碼中實現了一個隨機的延遲。您不需要將它和您的應用程式一起編譯——只需隨意地把Error.aspx檔案保存到伺服器上的某個應用程式目錄。
<%@ Page Language="VB" AutoEventWireup="true" %>
<%@ Import Namespace="System.Security.Cryptography" %>
<%@ Import Namespace="System.Threading" %>
<script runat="server">
Sub Page_Load()
Dim delay As Byte() = New Byte(0) {}
Dim prng As RandomNumberGenerator = New RNGCryptoServiceProvider()
prng.GetBytes(delay)
Thread.Sleep(CType(delay(0), Integer))
Dim disposable As IDisposable = TryCast(prng, IDisposable)
If Not disposable Is Nothing Then
disposable.Dispose()
End If
End Sub
</script>
<html>
<head runat="server">
<title>Error</title>
</head>
<body>
<div>
Sorry – an error occured
</div>
</body>
</html>
C# 版本
下面是您可以使用的C#版本的Error.aspx ,在程式碼中實現了一個隨機的延遲。您不需要將它和您的應用程式一起編譯——只需隨意地把Error.aspx檔案保存到伺服器上的某個應用程式目錄。
<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ Import Namespace="System.Security.Cryptography" %>
<%@ Import Namespace="System.Threading" %>
<script runat="server">
void Page_Load() {
byte[] delay = new byte[1];
RandomNumberGenerator prng = new RNGCryptoServiceProvider();
prng.GetBytes(delay);
Thread.Sleep((int)delay[0]);
IDisposable disposable = prng as IDisposable;
if (disposable != null) { disposable.Dispose(); }
}
</script>
<html>
<head runat="server">
<title>Error</title>
</head>
<body>
<div>
An error occurred while processing your request.
</div>
</body>
</html>
驗證 <customErrors> 節點是否已被正確設置
當完成上述配置後,您可以測試它來驗證設置是否正確且生效,比如在您的網站上請求類似這樣的URL: http://mysite.com/pagethatdoesnotexist.aspx
如果您看到之前設置的錯誤頁被顯示(因為您請求的檔案不存在),那麼配置就是正確的。而如果您看到一個標準的ASP.NET錯誤,則可能是您缺失了上面某個步驟。如果想查看導致錯誤的更多資訊,您可以嘗試設置 <customErrors mode="remoteOnly" /> ——只在伺服器上的本地瀏覽器進行連接時才可以看見這些錯誤消息。
安裝URLScan並啟用一個自訂規則
如果您還沒有安裝IIS URLScan元件,請下載並進行安裝:
- x86 版本
- x64 版本
只需要不到一分鐘就可以將它安裝到你的伺服器上。
增加一個新的URL掃瞄規則
URLScan安裝完畢後,在以下位置找到UrlScan.ini檔案,打開並修改它:
- %windir%\system32\inetsrv\urlscan\UrlScan.ini
在靠近UrlScan.ini檔案內容底部,您可以找到 [DenyQueryStringSequences] 節點,在緊跟它的下面的地方增加 「asoxerrorpath=」並保存:
[DenyQueryStringSequences]
aspxerrorpath=
上面這條規則可以禁止URL在QueryString中包含 「aspxerrorpath=」 這樣的屬性,如果有,則伺服器會傳回一個HTTP錯誤。有了這個規則就可以避免使攻擊者區分伺服器上的錯誤型別——即可以阻擋攻擊者利用這個漏洞。
保存以上修改以後,在命令提示符(需要管理員權限)中運行iisreset使它生效。您可以通過向伺服器的網站或應用程式請求QueryString中包含aspxerrorpath關鍵字的URL地址,來驗證它是否成功,正常情況下IIS應該發回一個HTTP錯誤。
在Web伺服器上找出存在安全漏洞的ASP.NET應用程式
我們發佈了一個.vbs指令碼檔案,您可以保存到Web伺服器並運行它,來檢測是否有ASP.NET應用程式沒有關閉 <customErrors />,或它只針對某些錯誤狀態碼。
您可以從這裡下載這個.vbs指令碼檔案。只要把指令碼內容複製/貼上到一個記事本檔案,比如」DetectCustomError.vbs」,並保存到硬碟。打開一個命令提示符窗口(需要管理員權限),然後運行csript DetectCustomErrors.vbs,它會列出Web伺服器上的所有網站應用程式並檢查<customErrors />設置是否正確。
它會標記出那些有問題的應用程式,比如在Web.config中沒有設置 <customErrors />節點 (需要進行添加),或沒有按照正確的方法進行設置(你需要修改它),如果每個應用程式都沒有問題,它則會列印出「OK」的結果,這應該很容易的找出潛在的問題。
注意: 我們僅僅在前面幾個小時內完成了這個檢測指令碼,將在以後對它進行完善,一有修改我即會在這裡發佈更新。
關於此漏洞的更多資訊
您可以從下面這些地方瞭解更多關於該漏洞的資訊:
- Microsoft Security Advisory 2416728
- Understanding the ASP.NET Vulnerability
- Microsoft Security Response Center Blog Post
可提問的論壇
我們已經在www.asp.net 上設置了一個專門的論壇,來幫助回答與該漏洞相關的問題。
您可以在這裡提問並獲得與該漏洞有關的幫助。
總結
我們將發表更多細節,並且我們將發佈一個修補檔來從根本上解決這個問題(並且不再需要上面的替代方案)。
在那之前,請繼續執行上面的替代方案來預防攻擊者來利用它。
9月20日更新: 發佈了另一篇部落格,其中包含關於此問題的一些FAQ,您可以從這裡閱讀。
9月24日更新: 發佈了另一篇部落格,關於在臨時方案中啟用一個額外步驟URLScan。您可以從這裡閱讀。
希望這能對您有所幫助。
附:[除了寫部落格以外,我現在也使用推特(Twitter)來及時更新狀態和分享連結,您可以到這個地址「推」我一下:twitter.com/scottgu]