【问题标题】:How to check if a process has access to a securable object in windows如何检查进程是否可以访问 Windows 中的安全对象
【发布时间】:2020-07-01 20:17:24
【问题描述】:

场景:我有一个可以创建、启动、停止其他服务并通过 IPC 将其提供给用户进程的服务。

如果调用进程有权访问 SCM,我如何签入我的服务?

所以在更抽象的层面上,我有一些安全对象,在这种情况下是 SCM,但它实际上可以是任何其他进程、线程、文件、文件夹或 reg 键等... 而且我有一些用户进程可能有也可能没有访问该资源的权限。 如何在第 3 方进程中确定所述用户进程是否有权访问给定的安全对象?

【问题讨论】:

  • 您需要枚举目标进程的令牌:docs.microsoft.com/en-us/windows/win32/secauthz/access-tokens,然后使用GetTokenInformation 查看每个令牌授予的权限。
  • 这给了我一个用户和组的列表以及相应的授予或阻止的访问权限,然后我必须枚举安全对象的权限并“手动”比较它们。难道没有更简单的方法来做一些函数调用,它接受令牌、对象和访问掩码并返回真/假
  • 我的意思是我总是可以模拟用户进程并尝试自己打开对象并检查它是失败还是成功,但这并不那么漂亮,我希望有一种更优雅的方式来做到这一点
  • 如果你想限制自己的客户端的权限,那么冒充客户端是标准的解决方案。

标签: windows security dacl


【解决方案1】:

好的,我有它:D 接缝可以做我需要的事情,它基于http://blog.aaronballman.com/2011/08/how-to-check-access-rights/

bool CanAccessSCM(HANDLE idProcess)
{
    bool bRet = false;

    DWORD genericAccessRights = SC_MANAGER_ALL_ACCESS;
    SC_HANDLE scHandle = OpenSCManager(NULL, NULL, READ_CONTROL);
    if (scHandle != NULL) {
        PSECURITY_DESCRIPTOR securityDescriptor;
        if (NT_SUCCESS(GetSecurityInfo(scHandle, SE_SERVICE, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION
            , NULL, NULL, NULL, NULL, &securityDescriptor))) {
            HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, (DWORD)(ULONG_PTR)idProcess);
            if (hProcess != NULL) {
                HANDLE hToken = NULL;
                if (OpenProcessToken(hProcess, TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_DUPLICATE | STANDARD_RIGHTS_READ, &hToken)) {
                    HANDLE hImpersonatedToken = NULL;
                    if (DuplicateToken(hToken, SecurityImpersonation, &hImpersonatedToken)) {
                        GENERIC_MAPPING mapping = { 0xFFFFFFFF };
                        PRIVILEGE_SET privileges = { 0 };
                        DWORD grantedAccess = 0, privilegesLength = sizeof(privileges);
                        BOOL result = FALSE;
                        /*
                        mapping.GenericRead = FILE_GENERIC_READ;
                        mapping.GenericWrite = FILE_GENERIC_WRITE;
                        mapping.GenericExecute = FILE_GENERIC_EXECUTE;
                        mapping.GenericAll = FILE_ALL_ACCESS;
                        ::MapGenericMask( &genericAccessRights, &mapping );*/
                        if (::AccessCheck(securityDescriptor, hToken, genericAccessRights,
                            &mapping, &privileges, &privilegesLength, &grantedAccess, &result)) {
                            bRet = (result == TRUE);
                        }
                        CloseHandle(hImpersonatedToken);
                    }
                    CloseHandle(hToken);
                }
                CloseHandle(hProcess);
            }
            LocalFree(securityDescriptor);
        }
        CloseHandle(scHandle);
    }

    return bRet;
}
´´´

【讨论】:

  • 首先你使用哪个ipc。许多有内置的模拟api,如RpcImpersonateClientImpersonateNamedPipeClient..如果您使用其他方式但知道客户端的client_id - 您需要首先尝试打开线程(通常)而不是(如果线程失败)进程令牌,重复获取模拟令牌(如果您打开进程令牌)并将此令牌设置为线程(SetThreadToken,或使用ImpersonateLoggedOnUser - 如果需要,在查询后在内部复制令牌)。并使用此令牌进行操作,但不检查
  • 注释的通用文件权限是阅读代码时不必要的干扰,应该删除。 SCM 和服务的权利定义为hereGenericMapping 参数用于 GenericAll,以满足检查 MAXIMUM_ALLOWED 是否一个对象没有安全性,但这对于文件以外的大多数安全对象来说是不寻常的。
  • 将所需的访问权限设置为MAXIMUM_ALLOWED -- 加上ACCESS_SYSTEM_SECURITYWRITE_OWNER,如果您希望检查包括分别检查SeSecurityPrivilege 和SeTakeOwnershipPrivilege。也就是说,最好简单地模仿并尝试而不是使用AccessCheck
猜你喜欢
  • 1970-01-01
  • 2017-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多