解決兩個難懂的安全性問題(轉)

heying1229發表於2007-07-28
性、服務和互動式桌面
  與 Unix 守護程式類似,服務是 Microsoft Windows NT? 的中樞,可以向作業系統和使用者提供重要功能而無需使用者的參與。建立服務時,有一些問題需要注意。

  Microsoft Windows? 中的服務通常是控制檯應用程式,它們的執行無需使用者參與,也沒有使用者介面。但在某些例項中,服務可能需要與使用者進行互動。執行在較高環境中的服務(如 SYSTEM)不應作為互動式服務執行。在 Windows 使用者介面中,桌面是邊界,在互動式桌面上執行的任何應用程式可以與互動式桌面上的任何視窗互動,即使視窗並不可見。無論建立視窗的應用程式的環境和應用程式的環境如何,都是這樣。 由於這些設計特點,任何在互動式桌面上開啟視窗的服務都會向登入使用者所執行的應用程式公開。如果服務試圖使用視窗訊息控制其功能,則登入使用者可以透過使用惡意訊息來干擾該功能。

  將服務作為 SYSTEM 執行的做法(即,服務透過呼叫 OpenWindowStation 和 GetThreadDesktop 來支援互動式桌面)十分不可取。請注意,Windows 將來的版本可能會完全取消對互動式服務的支援。

  我們建議服務編寫人員使用客戶端/伺服器技術(例如 RPC、套接字、命名管道或 COM)實現與來自某個服務的登入使用者的互動,使用帶 MB_SERVICE_NOTIFICATION 的 MessageBox 顯示簡單的狀態。如果您的服務程式碼具有以下任何屬性,請提高警惕:

  • 作為 LocalSystem 執行,並且服務在安全配置管理器中進行了標記(“登入為”->“允許服務與桌面互動”),或登錄檔項 -> HKLMCCSServicesMyServiceType & 0x0100 == 0x0100)
    CreateService,並且 dwServiceType & SERVICE_INTERACTIVE_PROCESS == SERVICE_INTERACTIVE_PROCESS
  • 呼叫 MessageBox(),其中 uType and (MB_DEFAULT_DESKTOP_ONLY | MB_SERVICE_NOTIFICATION | MB_SERVICE_NOTIFICATION_NT3X) != 0
  • 呼叫 OpenDesktop("winsta0",...) 並在該桌面上建立使用者介面
  • 在 OpenDesktop 上呼叫 LoadLibrary/GetProcAddress

  小心 _alloca

  _alloca 函式可以在堆疊中分配動態記憶體。分配的空間將在呼叫函式退出時自動釋放,而不只是在分配超出範圍時釋放。下面是使用 _alloca 的示例程式碼:

void function(char *szData) {
PVOID p = _alloca(lstrlen(szData));
// 使用 p
}

  如果攻擊者提供一個比堆疊大小還要長的 szData,_alloca 會引發一個異常並導致應用程式停止。如果該程式碼位於伺服器中,則情況會更糟。處理這種錯誤情況的正確方法是將對 _alloca 的呼叫打包在異常處理程式中,並在出現錯誤時重置堆疊。

void function(char *szData) {
__try {
PVOID p = _alloca(lstrlen(szData));
// 使用 p
} __except ((EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) ?
EXCEPTION_EXECUTE_HANDLER :
EXCEPTION_CONTINUE_SEARCH) {
_resetstkoflw();
}
}

  相關問題:ATL 轉換宏

  您還應當小心某些呼叫 _alloca 的 ATL 字串轉換宏。這些宏包括 A2W、W2A 和 CW2CT 等。如果您的程式碼是伺服器程式碼,則呼叫其中任何轉換函式時都必須考慮資料的長度。這是不要輕易相信輸入的又一個示例。如果攻擊者向您的程式碼提供一個 10 MB 的字串,便會摧毀堆疊並引發異常;或者如果未引發異常,則導致失敗。所以千萬不要這樣做!

  發現缺陷
  沒有人看出上星期的程式碼中的錯誤,但很多人已接近目標。其中的問題是為明文和密文使用了相同的緩衝區。您永遠都不能這樣做。

  乍看起來,使用相同的緩衝區儲存明文,然後加密明文產生的密文似乎很好。在大多數情況下也是這樣。但在多執行緒環境中就不是這樣了。設想一下,您的程式碼中出現了一個“競爭狀態”,而您卻並不知道。(競爭狀態是由對軟體中的事件的相對時間產生意外的嚴格依賴而引起的。它們通常與同步錯誤一起出現。)坦白地說,您永遠不會知道存在著嚴重的競爭狀態,等知道時已經太晚了。請再考慮一下,您的應用程式的正常流程如下所示:

  使用明文載入緩衝區。
  加密緩衝區。
  將緩衝區內容傳送給接收者。

  這看起來很正常。但是,設想您有一個多執行緒應用程式,由於某種原因,最後兩個步驟由於競爭狀態而被交換:

  使用明文載入緩衝區。
  將緩衝區環境傳送給接收者。
  加密緩衝區。

  接收者只接收到一些明文!這是在 Internet Information Server 4.0 中修復的一個錯誤。在非常特殊的負載和極少數情況下,當使用套接字層 (SSL) 保護從伺服器至使用者的資料通道時,伺服器可能會遵循此模式,並將一個未加密的資料資訊包傳送給使用者。這種潛在問題的破壞很小;只向使用者(或者可能是一個攻擊者)傳送了一個資訊包。並且當使用者接收到資訊包時,客戶端軟體將斷開連線。據說該問題已被 Microsoft 修復了。

  修復的方法是使用兩個緩衝區。一個緩衝區用於明文,另一個用於密文,並確保密文在執行不同呼叫時已被清空。

  您能指出此程式碼中的錯誤嗎?

void ShuffleAndUpdate(char *szName, char *szPwd,
DWORD index,
DWORD d) {
DWORD dwArray[32];
ZeroMemory(dwArray,sizeof(dwArray));
BOOL fAllowAccess = FALSE;
if (IsValidUser(szName,szPwd)) {
fAllowAccess = TRUE;
ShuffleArray(dwArray,szName);
}
dwArray[index]= d;
if (fAllowAccess) {
// 執行某些敏感的操作
}
}

[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10172717/viewspace-928869/,如需轉載,請註明出處,否則將追究法律責任。

相關文章