2012-03-06 83 views
5

我在創建NamedPipe時遇到了安全描述符設置問題。我希望在Windows服務(高完整性)中創建的管道能夠從中等和低完整性流程中打開。對中/高完整性管道安全描述符的低完整性

我正在使用Windows 7 x64。我不太明白我在這裏做什麼,但這裏是我用來爲我創建的管道創建安全描述符的代碼。下面的代碼不會讓我在從低完整性進程都高,中誠信LEVE創建開放管道:



    PSID psidWorldSid = NULL, pAdminSID = NULL, pLowSID = NULL, pHighSID = NULL; 
    WCHAR wszIntegritySid[] = L"S-1-16-4096"; 
    WCHAR wszSystemSid[] = L"S-1-16-16384"; 
    PACL pACL = NULL; 
    PSECURITY_DESCRIPTOR pSD = NULL; 
    SECURITY_ATTRIBUTES sa; 
    SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; 
    SID_IDENTIFIER_AUTHORITY siaWorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY; 
    EXPLICIT_ACCESS ea[4]; 

    // Create a security descriptor for the log file that allows 
    // access from both the privileged service and the non-privileged 
    // user mode programs 

    AllocateAndInitializeSid(&siaWorldSidAuthority, 1, 
     SECURITY_WORLD_RID, 
     0, 0, 0, 0, 0, 0, 0, 
     &psidWorldSid); 

    ZeroMemory(&ea, sizeof(ea)); 
    ea[0].grfAccessPermissions = FILE_ALL_ACCESS | GENERIC_WRITE | GENERIC_READ; 
    ea[0].grfAccessMode = SET_ACCESS; 
    ea[0].grfInheritance= NO_INHERITANCE; 
    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; 
    ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; 
    ea[0].Trustee.ptstrName = (LPTSTR) psidWorldSid; 

    // Create a SID for the BUILTIN\Administrators group. 
    AllocateAndInitializeSid(&SIDAuthNT, 2, 
     SECURITY_BUILTIN_DOMAIN_RID, 
     DOMAIN_ALIAS_RID_ADMINS, 
     0, 0, 0, 0, 0, 0, 
     &pAdminSID); 

    // Initialize an EXPLICIT_ACCESS structure for an ACE. 
    // The ACE will allow the Administrators group full access to 
    // the key. 
    ea[1].grfAccessPermissions = FILE_ALL_ACCESS | GENERIC_WRITE | GENERIC_READ; 
    ea[1].grfAccessMode = SET_ACCESS; 
    ea[1].grfInheritance= NO_INHERITANCE; 
    ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; 
    ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; 
    ea[1].Trustee.ptstrName = (LPTSTR) pAdminSID; 

    AllocateAndInitializeSid(&siaWorldSidAuthority, 1, 
     SECURITY_MANDATORY_LOW_RID, 
     0, 
     0, 0, 0, 0, 0, 0, 
     &pLowSID); 

    ea[2].grfAccessPermissions = FILE_ALL_ACCESS | GENERIC_WRITE | GENERIC_READ; 
    ea[2].grfAccessMode = SET_ACCESS; 
    ea[2].grfInheritance= NO_INHERITANCE; 
    ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID; 
    ea[2].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; 
    ea[2].Trustee.ptstrName = (LPTSTR) pLowSID; 

    AllocateAndInitializeSid(&siaWorldSidAuthority, 1, 
     SECURITY_MANDATORY_HIGH_RID, 
     0, 
     0, 0, 0, 0, 0, 0, 
     &pHighSID); 

    ea[3].grfAccessPermissions = FILE_ALL_ACCESS | GENERIC_WRITE | GENERIC_READ; 
    ea[3].grfAccessMode = SET_ACCESS; 
    ea[3].grfInheritance= NO_INHERITANCE; 
    ea[3].Trustee.TrusteeForm = TRUSTEE_IS_SID; 
    ea[3].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; 
    ea[3].Trustee.ptstrName = (LPTSTR) pHighSID; 

    SetEntriesInAcl(4, ea, NULL, &pACL); 

    pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); 
    InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); 
    SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE); 
    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); 


    sa.nLength    = sizeof(SECURITY_ATTRIBUTES); 
    sa.lpSecurityDescriptor = pSD; 
    sa.bInheritHandle  = FALSE; 

    m_hPipe = CreateNamedPipeA(
       m_szName.c_str(), 
       PIPE_ACCESS_DUPLEX, 
       PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | BlockFlag, 
       PIPE_UNLIMITED_INSTANCES, 
       BUFFER_SIZE, 
       BUFFER_SIZE, 
       NMPWAIT_USE_DEFAULT_WAIT, 
       &sa 
       ); 

    if (psidWorldSid) 
     FreeSid(psidWorldSid); 
    if (pAdminSID) 
     FreeSid(pAdminSID); 
    if (pLowSID) 
     FreeSid(pLowSID); 
    if (pHighSID) 
     FreeSid(pHighSID); 
    if (pACL) 
     LocalFree(pACL); 
    if (pSD) 
     LocalFree(pSD); 

看來,當我從字符串創建一個安全描述符的工作幾乎罰款:

ConvertStringSecurityDescriptorToSecurityDescriptorW(L"S:(ML;;NW;;;LW)", SDDL_REVISION_1, &pSD, NULL);

當我從上面的字符串創建安全描述符時,我至少可以打開使用低完整性進程創建的中等完整權限的管道。

謝謝你的任何建議。

問候, 庫巴

+0

你應該接受克里斯的回答。 – 2012-03-17 05:37:32

回答

5

告訴你的代碼似乎已創造一個安全描述符,並建立它的自由訪問控制列表(DACL)。 DACL與完整性控制機制完全沒有關係。

爲了讓低完整性進程打開一個句柄,通過該句柄寫入到命名管道,命名管道對象需要在其強制完整性標籤中標記爲低完整性。此標籤位於系統訪問控制列表(SACL)中,而不在DACL中。這就是S:(...前綴在安全描述符的SDDL字符串表示中的含義,您通過ConvertStringSecurityDescriptorToSecurityDescriptorW來創建SD。

如果您想在不從SDDL表示開始的情況下長時間執行此操作,則必須創建一個正確類型的ACE,SYSTEM_MANDATORY_LABEL_ACE,使用低完整性SID(S-1-16-4096)進行初始化;一個適當的完整性政策(例如SYSTEM_MANDATORY_LABEL_NO_WRITE_UP),然後通過將其放入SACL。

+0

嗨克里斯。我閱讀有關此問題的MSDN信息:http://msdn.microsoft.com/en-us/library/bb625960.aspx。在我看來,我用「S:(ML ;; NW ;;; LW)」正確設置了管道的完整性,因爲它們與MSDN示例中的相同。我知道這一點我正在失去安全。在將它們發送到高完整性流程之前,通過中等完整性流程代理/傳輸來自低完整性流程的所有連接可能會更好? – blackd0t 2012-03-13 12:28:01

+1

是的,如果你使用SDDL來做,'S:(ML ;; NW ;; LW)'是正確的,並且正在做我所描述的:'S:'表示你設置SACL,'ML'表示一個SYSTEM_MANDATORY_LABEL_ACE,'NW'是不可寫的完整性策略,'LW'表示您爲Low Integrity調用者啓用它。你只是以一種非常可控的方式「失去安全性」......低廉的完整性過程可以將數據寫入管道,但默認情況下他們將無法完成。只要您的管道服務器驗證並小心處理所有傳入的數據,這不是問題(它實際上就是您要實現的目標)。 – 2012-03-16 08:53:31

+1

@ChrisDickson:你可以提供一些源代碼如何添加SYSTEM_MANDATORY_LABEL_ACE。如果管道已經存在,如何更改安全性?如何打開該句柄,以便在更改任何SACL ACE時具有ACCESS_SYSTEM_SECURITY權限? – bkausbk 2012-05-24 15:08:57

3

我能解決這個問題。正如克里斯指出的那樣,儘管我錯過了我爲用戶提供的部分,但管道是以低完整性權限正確創建的。

我通過像這樣設置SDDL解決了這個問題:S:(ML;;NW;;;LW)D:(A;;0x12019f;;;WD) 這將設置Everyone用戶允許他打開,寫入,讀取管道的權限。我已經檢查過,現在可以從任何完整性級別和任何帳戶全局訪問管道。

更好的辦法是爲「Everyone」設置0x12019b權限,因爲它將允許所有用戶訪問管道,而無需向管道中添加新實例。然後,您必須爲創建管道的用戶添加0x12019f權限,但我不知道如何獲取當前用戶的ID。

在我的情況下,這很適合,因爲我只報告系統服務解析其他進程的數據信息,但是如果使用管道來控制系統服務,則可能不希望以不同方式設置安全描述符。通過管道將數據發送到系統服務時,請注意緩衝區/堆溢出是非常重要的,因爲這可能會導致安全漏洞留下漏洞,從而導致本地特權升級。

我希望這個問題可以幫助別人。

羅傑,出來!