如何针对域验证用户的缓存凭据?

时间:2015-07-10 20:57:52

标签: windows security authentication windows-authentication

登录Windows时,您的凭据已缓存。这允许您使用单点登录。如果你要浏览另一台计算机,例如:

\\hydrogen

enter image description here

您将提示输入凭据。

Windows将采用您的:

  • 当前用户名
  • (哈希)密码

并尝试自动验证您。有趣的是,如果您的工作站不在域上,这甚至可以工作。在连接到服务器时,Windows将 自动 使用您的用户名和密码。如果你的:

  • 本地用户名/密码与
  • 匹配
  • 用户名/密码

您将自动进入。

漂亮的照片:

enter image description here

这称为单点登录。您登录Windows一次,并且在您使用网络上的其他内容时,您的缓存凭据将用于验证您。

浏览器也会这样做

Chrome,Internet Explorer和Firefox也会对此做出改变。如果您需要登录网站,并且服务器支持协商授权,服务器将向您发回一个指示,您应该尝试使用用户的Windows /域/ Kerberos凭据:

HTTP/1.1 401 Unauthorized
Server: Microsoft-IIS/7.5
WWW-Authenticate: Negotiate
Date: Thu, 09 Jul 2015 14:35:58 GMT
Content-Length: 0

然后,Chrome会将您的缓存凭据和(在经过一些中级魔法之后)转发给网络服务器:

GET http://hr.woodglue.com HTTP/1.1
Host: hr.woodglue.com
Authorization: Negotiate YIIFzwYGKwYBBQUCoIIFwzCCBb....

enter image description here

Microsoft在旧文章中讨论了Internet Explorer中的这种机制:

  

HTTP-Based Cross-Platform Authentication by Using the Negotiate Protocol

     

enter image description here

     
      
  • 客户端使用SPN调用AcquireCredentialsHandle()InitializeSecurityContext()来构建从TGS / KDC请求会话票据的安全上下文。
  •   

您对域进行验证,而不是服务器

我要提到的最后一点是服务器,网络服务器,工作站,文件服务器,不针对服务器验证凭据,它们针对域控制器进行验证即可。您有许多域服务器的模糊,其中一个处理您的请求。

换句话说,您不会针对以下内容验证凭据:

  • \\uranium woodglue.com域上的域控制器)

您验证凭据:

  • woodglue.com

我们有一个重要的概念,有人可以:

  • 验证您的缓存凭据
  • 针对域名
  • 无需输入用户名或密码

我该怎么做?

如何验证某人的缓存凭据?

怎么样?
  • 验证用户的缓存凭据
  • 针对
  • 没有用户必须输入用户名或密码(即使用Windows缓存凭据)

重要的是,我们不知道(或关心):

  • 如果用户的计算机已加入域
  • 如果用户的计算机已加入工作组
  • 如果用户的计算机已加入 woodglue.com 或其他某个域(例如 superglue.com
  • superglue.com
  • 提供支持的服务器的名称

enter image description here

我不知道怎么做。
我不知道涉及哪些API技术。

我知道有一个称为安全支持提供程序接口(SSPI)的API。这就是权力WWW-Authenticate: Negotiate(尽管我不知道它是否是来自非域名加入PC的SMB的权力)。

Chromium的开源软件可能会使用http_auth_sspi_win.cc的代码段启动我们。他们使用SSPI函数AcquireCredentialsHandle

int AcquireDefaultCredentials(CredHandle* cred) 
{
   TimeStamp expiry;
   // Pass the username/password to get the credentials handle.
   // Note: Since the 5th argument is NULL, it uses the default
   // cached credentials for the logged in user, which can be used
   // for a single sign-on.
   SECURITY_STATUS status = library->AcquireCredentialsHandle(
         NULL,  // pszPrincipal
         const_cast<SEC_WCHAR*>(package),  // pszPackage
         SECPKG_CRED_OUTBOUND,  // fCredentialUse
         NULL,  // pvLogonID
         NULL,  // pAuthData
         NULL,  // pGetKeyFn (not used)
         NULL,  // pvGetKeyArgument (not used)
         cred,  // phCredential
         &expiry);  // ptsExpiry
}
  

传递用户名/密码以获取凭据句柄。

     

注意:由于第5个参数为NULL,因此它使用登录用户的默认缓存凭据,该凭据可用于单点登录。

此{em>&#34;出站&#34; 致电AcquireCredentialsHandle,然后拨打InitializeSecurityContext。我们的想法是InitializeSecurityContext生成一个代表客户端的不透明blob。

然后,您可以执行一组并行呼叫:

  • &#34; inbound&#34; 致电AcquireCredentialsHandle
  • 调用AcceptSecurityContext,传递先前从InitializeSecurityContext
  • 返回的blob

窃取 rehost Daniel Doubrovkine's excellent image

enter image description here

  

注意:在这种情况下,&#34;客户端&#34; &#34;服务器&#34; 用于引用生产者和消费者的背景。就我而言,&#34;客户端&#34; &#34;服务器&#34; 位于同一台机器上。

&#34;这一行显示研究工作&#34; 分崩离析,因为我无法在 InitializeSecurityContext 中看到任何地方可以指定 woodglue.com 作为要验证的域。

我知道InitializeSecurityContext与kerberos服务器联系,并获得&#34;票据&#34; blob。然后将该票据blob传递给&#34;服务器&#34;通过AcceptSecurityContext。有时blob可以通过网络传递;在我的情况下,它在内存中传递到同一台机器上。

但我不知道如何指定应该联系 该票证的域名服务器。

不要暗示SSPI对解决我的问题一无所知。它只是&#34;研究工作&#34;

较早的研究工作

当然,在所有这些过程中,如果缓存的凭据在指定的域上无效,我将不得不提示用户输入用户名和密码。但是用户名和密码是邪恶的,是计算的祸根,我想避免它们。

我使用的是本机代码;不是C#。

0 个答案:

没有答案