低完整性到中/高完整性管道安全描述符

时间:2012-03-06 17:51:04

标签: windows winapi named-pipes

在创建NamedPipe时,我无法设置安全描述符。我希望从中等和低完整性过程中打开在Windows服务中创建的管道(高完整性)。

我正在使用Windows 7 x64。我不太明白我在这里做什么,但这里是我用来为我创建的管道创建安全描述符的代码。以下代码不允许我打开从低完整性过程中创建的高中和中等完整管道:



    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);

当我从字符串中创建安全描述符时,我至少可以打开使用低完整性进程的中等完整性权限创建的管道。

感谢您提出任何建议。

此致 库巴

2 个答案:

答案 0 :(得分:5)

您显示的代码似乎是创建安全描述符并设置其自由访问控制列表(DACL)。 DACL与完整性控制机制没有任何关系。

为了使低完整性进程打开一个句柄,通过该句柄写入命名管道,命名管道对象需要在其强制完整性标签中标记为低完整性。此标签位于系统访问控制列表(SACL)中,而不是DACL中。这就是S:(...前缀在您用于通过ConvertStringSecurityDescriptorToSecurityDescriptorW创建SD的安全描述符的SDDL字符串表示中的含义。

如果您想在不从SDDL表示开始的情况下执行此操作,则必须创建一个正确类型的ACE SYSTEM_MANDATORY_LABEL_ACE,使用低完整性的SID初始化(S-1-16- 4096)和适当的完整性策略(例如SYSTEM_MANDATORY_LABEL_NO_WRITE_UP),然后通过SetSecurityDescriptorSacl将其放入SACL。

答案 1 :(得分:5)

我能够解决问题。正如克里斯所指出的那样,管道是使用低完整性权限正确创建的,尽管我错过了我为用户提供的部分。

我通过设置SDDL来解决这个问题:S:(ML;;NW;;;LW)D:(A;;0x12019f;;;WD) 这将为Everyone用户设置权限,允许他打开,写入和读取管道。我已经检查过,现在可以从任何完整性级别和任何帐户全局访问管道。

更好的方法是为“Everyone”设置0x12019b权限,因为它将为所有用户提供对管道的访问权限,而无权向管道添加新实例。然后,您必须仅为创建管道的用户添加0x12019f权限,但我不知道如何获取当前用户的ID。

在我的情况很合适,因为我只报告来自其他进程的数据信息以供系统服务进行解析,但是如果使用管道来控制系统服务,则可能不希望以不同的方式设置安全描述符。当您通过管道向系统服务发送数据时,请务必小心任何缓冲区/堆溢出,因为它可能会导致安全漏洞,从而留下可能允许本地权限升级的漏洞。

我希望这个问题可以帮助别人。

罗杰,出去!