在具有 UAC 的 Vista 上将 SSPI (NTLM) Api 与 Windows AccessCheck() 一起使用
概括 客户端(Windows XP SP3) 服务器 (Windows Vista Business SP1) / 作为 LocalSystem 服务
Api 序列 运行 客户端 - AcquireCredentialsHandle 客户端 - 初始化安全上下文 服务器 - 获取凭证句柄 服务器-AcceptSecurityContext 客户端/服务器 - CompleteAuthnToken 服务器 - ImpersonateSecurityContext 服务器 - AccessCheckAndAuditAlarm (MAXIMUM_allowed) 服务器 - 然后我将请求的访问与允许的访问进行比较。
我对使用 createprivateobjectsecurityex 创建的私有安全对象调用访问检查。 打开 Uac 后,我从访问检查中获得成功,但没有保留任何权限。 关闭 uac 后,我成功恢复了 GantedAccess 参数
详细信息 中的所有权限 该应用程序有两个组件:客户端和服务器。 它 使用 tcp 通过不安全的网络进行通信。 去认证 我使用上面列出的 sspi api 的传入连接,以及 冒充呼叫用户。 一旦调用用户被冒充,我 使用 Accesscheckandauditalarm,如果失败,我将恢复为刚刚 访问检查。 打开UAC后,我从以下位置获得了成功 accesscheckandauditalarm 但没有任何访问权限 grandedaccess 参数,但如果 uac 关闭,它会按预期工作。 我已检查服务器进程的完整性级别并已设置 至高,我查看了模拟令牌的完整性级别 用于模拟主叫用户,设置为“中”。 我有 尝试将调用用户的完整性级别设置为高, 成功,但访问检查仍然返回不正确的结果。 我想我可能有一个链接令牌,我尝试使用链接令牌 调用 GetTOkenInformation(TokenLInkedToken),结果为 0x520。 任何关于我下一步可能尝试的想法将不胜感激。
验证后的代码。
SECURITY_STATUS ss = SEC_E_OK;
HANDLE _hToken = NULL;
ss = QuerySecurityContextToken((PCtxtHandle)pContext,&_hToken);
if(SEC_E_OK != ss)
{
return ss;
}
CAccessToken impToken;
impToken.Attach(_hToken);
if(CWin32::IsVista())
{
/*TOKEN_LINKED_TOKEN linkedToken;
DWORD nLen = 0;
BOOL bRet = GetTokenInformation(_hToken,
(TOKEN_INFORMATION_CLASS)TokenLinkedToken,&linkedToken,sizeof(linkedToken), &nLen);
if(bRet)
{
CloseHandle(impToken.Detach());
impToken.Attach(linkedToken.LinkedToken);
}
else
{
TRACE(_T("GetTokenInfo Failed 0x%x\n"),GetLastError());
}*/
PSID pHighIntegritySid = NULL;
BOOL bConvertSid = FALSE;
bConvertSid = ConvertStringSidToSid(SDDL_ML_HIGH,
&pHighIntegritySid);
if (bConvertSid)
{
TOKEN_MANDATORY_LABEL TML = {0};
TML.Label.Attributes = SE_GROUP_INTEGRITY |
SE_GROUP_INTEGRITY_ENABLED;
TML.Label.Sid = pHighIntegritySid;
BOOL bSetTokenRet = SetTokenInformation(_hToken,
(TOKEN_INFORMATION_CLASS)TokenIntegrityLevel,&TML,sizeof(TML) +
GetLengthSid(pHighIntegritySid));
LocalFree(pHighIntegritySid);
if(!bSetTokenRet)
{
nReturn = GetLastError();
DBGOUT(DebugOut::LOG_COMP_AUTH_LAYER,DebugOut::LOG_DETAIL_ERROR,
_T("Failed to set Token information %x\n"),nReturn);
return nReturn;
}
}
}
bool bRet = impToken.Impersonate();
if(false == bRet)
{
return GetLastError();
}
_GetTokenSecurityLevel(impToken.GetHandle());
::MapGenericMask(&nRights, GetGENERIC_MAPPING());
DWORD nAccessGranted = 0;
BOOL bAccessStatus = FALSE;
BOOL bGenerateOnClose = FALSE;
BOOL bAccessCheckRet = FALSE;
bAccessCheckRet = ::AccessCheckAndAuditAlarm(_T("Purgos
Security"),impToken.GetHandle(),_T("Purgos"),m_csObjectName.GetBuffer(0),
const_cast<SECURITY_DESCRIPTOR*>(m_ObjectSD.GetPSECURITY_DESCRIPTOR())/
*privObjectSD.GetPSECURITY_DESCRIPTOR())*/,MAXIMUM_ALLOWED,GetGENERIC_MAPPI NG(),FALSE,&nAccessGranted,&bAccessStatus,&bGenerateOnClose);
Summary
Client (Windows XP SP3)
Server (Windows Vista Business SP1) / Running as LocalSystem Service
Api Sequence
Client - AcquireCredentialsHandle
Client - Initializesecuritycontext
Server - Acquirecredentialshandle
Server - AcceptSecurityContext
Client/Server - CompleteAuthnToken
Server - ImpersonateSecurityContext
Server - AccessCheckAndAuditAlarm (MAXIMUM_allowed)
Server - I then compare the access requested with the allowed accesses.
I call access check against a private security object created with createprivateobjectsecurityex. With Uac turned on I get success back from accesscheck, but none of the privledges are held. With uac turned off I get success back with all of the rights in the GantedAccess parameter
Details
The application has two componets to it, a client and a server. It
uses tcp to communicat over an unsecured network. To authentication
the incomming connections I use the sspi api's listed above, and
impersonate the calling user. Once the calling user is impersonated I
use Accesscheckandauditalarm, if this fails the i revert back to just
accesscheck. With UAC turned on I am getting success back from
accesscheckandauditalarm but none of the access rights are in the
grandedaccess paramter, but if uac is turned off it works as expected.
I have check the integrity level of the server process and it is set
to High, I have looked the integrity level of the impersonation token
used to impersonate the calling user and it is set to Medium. I have
tried setting the integrity level of the calling user to high, with
success but the access check still returns incorrrect results.
THinking I might have a linked token I tried the linked token with a
call to GetTOkenInformation(TokenLInkedToken) with a result of 0x520.
Any thoughts on what I might try next would be appreciated.
Code after authentication.
SECURITY_STATUS ss = SEC_E_OK;
HANDLE _hToken = NULL;
ss = QuerySecurityContextToken((PCtxtHandle)pContext,&_hToken);
if(SEC_E_OK != ss)
{
return ss;
}
CAccessToken impToken;
impToken.Attach(_hToken);
if(CWin32::IsVista())
{
/*TOKEN_LINKED_TOKEN linkedToken;
DWORD nLen = 0;
BOOL bRet = GetTokenInformation(_hToken,
(TOKEN_INFORMATION_CLASS)TokenLinkedToken,&linkedToken,sizeof(linkedToken), &nLen);
if(bRet)
{
CloseHandle(impToken.Detach());
impToken.Attach(linkedToken.LinkedToken);
}
else
{
TRACE(_T("GetTokenInfo Failed 0x%x\n"),GetLastError());
}*/
PSID pHighIntegritySid = NULL;
BOOL bConvertSid = FALSE;
bConvertSid = ConvertStringSidToSid(SDDL_ML_HIGH,
&pHighIntegritySid);
if (bConvertSid)
{
TOKEN_MANDATORY_LABEL TML = {0};
TML.Label.Attributes = SE_GROUP_INTEGRITY |
SE_GROUP_INTEGRITY_ENABLED;
TML.Label.Sid = pHighIntegritySid;
BOOL bSetTokenRet = SetTokenInformation(_hToken,
(TOKEN_INFORMATION_CLASS)TokenIntegrityLevel,&TML,sizeof(TML) +
GetLengthSid(pHighIntegritySid));
LocalFree(pHighIntegritySid);
if(!bSetTokenRet)
{
nReturn = GetLastError();
DBGOUT(DebugOut::LOG_COMP_AUTH_LAYER,DebugOut::LOG_DETAIL_ERROR,
_T("Failed to set Token information %x\n"),nReturn);
return nReturn;
}
}
}
bool bRet = impToken.Impersonate();
if(false == bRet)
{
return GetLastError();
}
_GetTokenSecurityLevel(impToken.GetHandle());
::MapGenericMask(&nRights, GetGENERIC_MAPPING());
DWORD nAccessGranted = 0;
BOOL bAccessStatus = FALSE;
BOOL bGenerateOnClose = FALSE;
BOOL bAccessCheckRet = FALSE;
bAccessCheckRet = ::AccessCheckAndAuditAlarm(_T("Purgos
Security"),impToken.GetHandle(),_T("Purgos"),m_csObjectName.GetBuffer(0),
const_cast<SECURITY_DESCRIPTOR*>(m_ObjectSD.GetPSECURITY_DESCRIPTOR())/
*privObjectSD.GetPSECURITY_DESCRIPTOR())*/,MAXIMUM_ALLOWED,GetGENERIC_MAPPI NG(),FALSE,&nAccessGranted,&bAccessStatus,&bGenerateOnClose);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
为所有感兴趣的各方找到了解决方案。
问题在于,正在进行身份验证的用户是本地帐户,并且默认情况下,本地帐户具有已过滤的令牌,且 BUILTIN\Administrators 组具有拒绝 ACL。 我正在检查 BUILTIN\Administrators 组的权限。 因此必须设置注册表设置或使用域帐户。
瑞安
Found the Solution to all interested parties.
The problem was that the user being authenticated was a local account, and by default local accounts have a filtered token with the BUILTIN\Administrators group having a deny ACL. And I was checking rights against the BUILTIN\Administrators group. So had to set a registry setting or use a domain account.
Ryan