保證應用程式中私有物件安全技術(轉)

RegisterForBlog發表於2007-09-19
保證應用程式中私有物件安全技術(轉)[@more@]

  引言

  您是否考慮過擴充套件 Windows® 作業系統豐富的安全功能以將其應用於自己的應用程式的方法?您是否用過 Windows 檔案系統安全編輯器,並希望能夠為自己的業務物件提供這一級別的安全性?本文將首先介紹 Windows 安全授權的基礎。然後介紹操縱安全描述符的步驟、建立自己的安全描述符的方法,以及如何使用不同的方法來編輯安全描述符。讀過本文後,您將掌握足夠的資訊,使您能夠將這些技術應用到自己的應用程式中。

  撰寫本文的目的之一,是希望有助於使安全程式設計切實可行,且便於訪問。所以這裡不會對特定的函式進行全面、深入的剖析,我將介紹若干 helper 函式和類,使用它們可以使您的安全程式碼更可靠、更便於管理。helper 函式和示例不僅說明了使用各種安全函式的方法,而且著重說明了在出現異常和錯誤的情況下如何安全、可靠地使用它們。

  令牌及其概念

  本文的內容全部是有關管理訪問控制的,管理訪問控制也稱為授權。在討論此問題之前,我們需要具備一種方法,用來識別嘗試對採取了安全措施的資源進行訪問的使用者。這就是令牌的作用。令牌代表計算機中的登入會話。只要使用者以互動方式或遠端方式訪問計算機,就會建立登入會話。令牌是一個處理程式,可用來對登入會話進行查詢和操縱。如果具有令牌,您就可以得到登入會話所代表的使用者,以及確定是否應授予該使用者訪問已採取安全措施的資源的許可權。

  因為所有應用程式都執行於登入會話的上下文中,所以總是可以使用某些型別的令牌來指示使用者。在任何給定的時刻,可能有一個或多個不同的令牌或安全上下文,這會有些使人產生混淆。每一個登入會話都代表著不同的使用者。至少有一個令牌附加到該程式。可以使用 OpenProcessToken 函式獲取此令牌。

  CHandle token;

  Helpers::CheckError(::OpenProcessToken(::GetCurrentProcess(),

  TOKEN_QUERY,

  &token.m_h));

  CHandle 是一個由活動模版庫 (ATL) 提供的包裝類,當令牌超出範圍時,它用來確保能夠透過呼叫 CloseHandle 函式關閉處理程式。CheckError 是我的 Helpers 名稱空間中的一個 helper 函式。CheckError 丟擲一個 HRESULT,用於說明所發生的錯誤。使用不同的方法可以在 Windows 的 C 語言程式設計中表示出錯的情況,我傾向使 HRESULT 標準化,以保證一致性。如果下載本文,則可以使用 Helpers 名稱空間。GetCurrentProcess 函式的返回值是一個偽處理程式,它代表當前的程式。因為不是真正的處理程式,所以不需要呼叫 CloseHandle 函式來釋放返回的 HANDLE。

  可以使用的另外一個令牌是執行緒令牌。可以透過呼叫 OpenThreadToken 函式來檢索執行緒令牌。

  CHandle token;

  Helpers::CheckError(::OpenThreadToken(::GetCurrentThread(),

  TOKEN_QUERY,

  TRUE, // 開啟自身

  &token.m_h));

  與 GetCurrentProcess 相同,GetCurrentThread 也返回一個偽處理程式,所以也不需要針對該程式呼叫 CloseHandle。與 OpenProcessToken 不同的是,如果沒有任何令牌與當前執行緒相關聯,那麼可能無法成功呼叫 OpenThreadToken,這時函式返回 ERROR_NO_TOKEN。

  在某些情況下,甚至存在第三令牌,該令牌代表其他安全上下文。例如,ASP.NET 允許關閉客戶模擬,在這種情況下,可以透過 HttpContext 類獲取客戶標識。

  獲取令牌後,如果能夠利用它執行一些有趣的操作,會有助於我們對它的理解。使用令牌能夠執行的最簡單的操作,就是對它進行查詢,以獲取登入會話的有關資訊。可以使用 GetTokenInformation 函式執行此操作。因為 GetTokenInformation 函式可用來查詢不同類的資訊,呼叫方法相當複雜,所以我編寫了一個包裝函式模板,以減少呼叫時可能出現的錯誤。下面示例說明了查詢令牌以獲取令牌使用者資訊的方法。

  CLocalMemoryT tokenUser(Helpers::GetTokenInformation(token,

  TokenUser));

  CComBSTR string = Helpers::ConvertSidToStringSid(tokenUser->User.Sid);

  ConvertSidToStringSid helper 函式用於將二進位制安全識別符號 (SID) 轉換為使用者易識別的字串。使用 SID 表示使用者帳戶是計算機易識別的格式。如果您的興趣只在包裝函式的功能,可以下載並檢視本文所附的原始碼。有關 CLocalMemoryT 類别範本的內容將在介紹了記憶體管理之後討論。

  安全描述符基礎

  瞭解瞭如何識別使用者後,我們需要一種方法,用來管理不同使用者所具有的不同的許可權。這就是使用安全描述符的必要性。安全描述符包含許多不同型別的資訊。其中最有趣的是所有者安全識別符 (SID) 和兩個訪問控制列表 (ACL)。所有者 SID 可標識擁有物件的使用者。兩個 ACL 分別是隨機 ACL 和系統 ACL。因為系統 ACL 實際上與訪問控制無關,所以本文集中討論隨機 ACL (DACL)。

  安全描述符以 SECURITY_DESCRIPTOR 結構表示,因為沒有關於此結構的說明,所以應避免直接對其進行操縱。Microsoft 提供了若干使用簡便的函式,用於查詢和操縱內建物件(比如,檔案和登錄檔項)的安全描述符。下面示例說明了獲取本地計算機中 Program Files 目錄的所有者 SID 和 DACL 的方法。

  CLocalMemory securityDescriptor;

  PSID sid = 0;

  PACL dacl = 0;

  Helpers::CheckError(::GetNamedSecurityInfo(_T("C:Program Files"),

  SE_FILE_OBJECT,

  OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,

  &sid,

  0, // 組

  &dacl,

  0, // sacl

  &securityDescriptor.m_ptr));

  GetNamedSecurityInfo 是一個具有多種用途的函式。它允許查詢絕大多數(如果不要求全部查詢的話)內建安全物件。第一個引數是要查詢的物件的名稱(或路徑)。第二個引數指示物件的型別。本例查詢的是檔案系統物件。例如,若要查詢登錄檔物件,可以將其更改為 SE_REGISTRY_KEY。下一步是使用列舉型別的引數 SECURITY_INFORMATION 指定感興趣的資訊。再後面的四個引數是分別指向安全描述符的四個主要部分的指標。這裡的方便之處是,對於不感興趣的部分,可以向相應的引數傳遞 0。最後一個引數是指向安全描述符本身的指標,它實際上是安全描述符的一個副本,必須使用 LocalFree 函式釋放。

  還可以使用名為 SetNamedSecurityInfo 的函式來更新內建物件的安全描述符。因為此函式的工作方式與上面所述相同,所以這裡不對其進行深入的剖析。

  記憶體管理

  在繼續之前,我認為有必要討論一下記憶體管理方面的內容。記憶體管理以及對資源的整體管理,是編寫安全、可靠的程式碼的一個重要方面。編寫記憶體管理程式碼的最佳方式就是根本不編寫程式碼。首先需要了解將要呼叫的各種函式所使用的記憶體管理技術,然後應將這些函式包裝到一個或兩個類中,以確保能夠在合適的時機正確清除。如果不進行這個工作,那麼編寫的程式碼將洩露資源,甚至出現更嚴重的情況,使程式出現漏洞,為存心不良的人訪問採取了安全措施的資源提供可乘之機。

  上面介紹了 CLocalMemoryT 類别範本,但沒有真正說明它的用途。絕大多數與安全描述符有關的安全函式都使用了本地記憶體。本地記憶體的使用可溯源至 16 位的 Windows 作業系統,在這類作業系統中,記憶體管理相當複雜。目前可供使用的本地記憶體函式(比如,LocalAlloc 和 LocalFree)主要是用來向後相容 16 位的應用程式,以及相容該類應用程式將其作為部分語義的以前的 API 函式。

  為了使得處理本地記憶體更加容易,我編寫了一個簡單的類,該類用於包裝本地記憶體指標。在過載成員選擇運算子 (operator ->)時,可以將 CLocalMemoryT 看作一個具有智慧的指標類。這樣做是可能的,因為它是一個類别範本,並且您可以透過模板引數指示所指向的記憶體的型別或結構。可以使用 CLocalMemoryT 建立新的本地記憶體塊,但一般使用它附加到函式所返回的現有的記憶體塊。然後解構函式透過呼叫 LocalFree 釋放記憶體。安全函式所使用的某些資料結構是不透明的。為了能夠更方便地使用這些結構,我在 CLocalMemory 標頭檔案的末尾定義了以下型別定義。

  typedef CLocalMemoryT CLocalMemory;

  使用這些型別能夠有效地管理 SECURITY_DESCRIPTOR 物件佔用的記憶體單元,例如:

  私有安全描述符

  GetNamedSecurityInfo 和 SetNamedSecurityInfo 具有很強的處理內建物件的功能。但是對於私有物件(比如,在自己的應用程式業務邏輯中所使用的物件),它們具有什麼功能呢?可以對這些函式的功能進行擴充套件,使其支援私有物件嗎?很不幸,答案是否定的。因為每個資源(比如,檔案系統或登錄檔)都定義了自己的保留安全描述符的方法,這些函式不可能瞭解查詢或設定您所建立的私有物件的安全資訊。萬幸的是,我們有解決的方法。

  首先我們需要一種建立私有安全描述符的方法。使用 CreatePrivateObjectSecurityEx 函式

  

·上一篇:

·下一篇:
 
     最新更新
·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·


| | | | | | |

Copyright © 2004 - 2007 All Rights Reserved

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

保證應用程式中私有物件安全技術(轉)
請登入後發表評論 登入
全部評論

相關文章