从会话 id 获取正确的令牌

Posted

技术标签:

【中文标题】从会话 id 获取正确的令牌【英文标题】:Getting correct Token from session id 【发布时间】:2015-02-26 12:32:20 【问题描述】:

当进程在非管理员用户(Windows 登录用户)下以管理员身份运行时,我想要实现的是会话 ID 中的实际令牌句柄。

        DWORD dwSessionId = 0;
        if (false == ProcessIdToSessionId(dwProcessId, &dwSessionId))
        
            LOG_ERROR(L"Failed obtaining session id");
            return false;
        

        HANDLE hToken
        if (false == WTSQueryUserToken(dwSessionId, &hToken))
        
            LOG_ERROR(L"Failed to obtain session's handle");
            return false;
        

当我调用 WTSQueryUserToken 时出现问题,它失败并出现错误 1314,这意味着我需要授予调用令牌 SE_TCB_NAME 权限。

所以我尝试使用以下代码:

tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
bool bSuccess = DynamicAPI::AdjustTokenPrivileges(
    %%WHICH_TOKEN_EXACTLLY%%,
    FALSE,
    &tp,
    sizeof(TOKEN_PRIVILEGES),
    (PTOKEN_PRIVILEGES)nullptr,
    (DWORD)nullptr);

但我不完全确定应该准确提供哪个令牌。我用 %%WHICH_TOKEN_EXACTLLY%% 占位符标记了它。对于我的测试,我尝试 AdjustTokenPriviliges 我的进程的令牌(管理员权限),但它也没有帮助。

【问题讨论】:

【参考方案1】:

如果需要调整权限的线程冒充用户,使用OpenThreadToken(GetCurrentThread())获取被冒充的token。否则,使用OpenProcessToken(GetCurrentProcess())获取调用进程的token。

【讨论】:

【参考方案2】:

您通常需要在您的进程令牌中启用权限,您可以使用 GetProcessToken() 函数获得该权限。例外情况是,如果您打算在模拟时使用该特权,则应改为在模拟令牌中启用该特权。

我使用此代码启用恢复权限:

DWORD enable_restore() 
    
  // This allows us to override security to delete files

  HANDLE token;
  BOOL flag;

  struct 
    DWORD count;
    LUID_AND_ATTRIBUTES privilege;
   token_privileges;

  token_privileges.count = 1;
  token_privileges.privilege.Attributes = SE_PRIVILEGE_ENABLED;

  flag = LookupPrivilegeValue(0, SE_RESTORE_NAME, &token_privileges.privilege.Luid);
  if (!flag) return GetLastError();

  flag = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token);
  if (!flag) return GetLastError();

  flag = AdjustTokenPrivileges(token, 0, (PTOKEN_PRIVILEGES)&token_privileges, 0, 0, 0);
  if (!flag) return GetLastError();

  return 0;    

请注意,此代码不会检查权限是否实际被授予。为此,请在调用 AdjustTokenPrivileges() 后检查 GetLastError() - 这是最后一个错误代码有意义的罕见情况之一,即使函数报告成功也是如此。

注意:这是您尝试使用进程令牌失败的最可能原因;如果您没有将代码作为本地系统运行,并且没有重新配置 Windows 以赋予您使用 SE_TCB_NAME 权限的帐户,则对 AdjustTokenPrivileges() 的调用将报告成功但没有效果。

另外,请记住,无论您是否具有 SE_TCB_NAME 权限,如果您在本地系统上下文中运行,则只能使用 WTSQueryUserToken(),即通常只有系统服务或应用程序在系统服务可以使用它。 (我不确定冒充本地系统是否足够。我怀疑不是。)

【讨论】:

以上是关于从会话 id 获取正确的令牌的主要内容,如果未能解决你的问题,请参考以下文章

在获取访问令牌以代表用户执行 API 请求后,保持用户会话和令牌连接的“正确”方式是啥?

在 Kong 中启用基本身份验证和会话插件时如何获取用户 ID?

如何从打开的SAP会话中获取用户ID?

验证 Firebase ID 令牌与获取用户数据

如何从 JWT 令牌中获取用户 ID

如何从 FirebaseAuth 获取 ID 令牌