security - 调用InitializeSecurityContext(协商)时要使用什么TargetName?

标签 security winapi kerberos ntlm

问题

调用 InitializeSecurityContext 时,我应将什么值传递给TargetName参数?

修改后的背景

我正在调用 InitializeSecurityContext 函数:

InitializeSecurityContextA(
      @pAS.hcred,           //[in] credentials
      phContext,            //[in] optional] Context handle structure
      pszTargetName,        //[in, optional] Target name
      0,                    //[in] context requirements
      0,                    //[in] reserved1, must be zero
      SECURITY_NATIVE_DREP, //[in] target data representation
      pInput,               //[in] optional] SecBufferDescription
      0,                    //[in] reserved2, must be zero
      @pAS.hctxt,           //[in, out] pointer to context handle structure
      @OutBuffDesc,         //[in, out] pointer to SecBufferDesc
      ContextAttributes,    //[out] context attributes
      @lifetime);           //[out] expiration timestamp

我要传递给pszTargetName吗?

我试过了
  • null :InitializeSecurityContextA(@pAS.hcred, phContext, null, ...);
  • "" :InitializeSecurityContextA(@pAS.hcred, phContext, "", ...);
  • "spn/HOSTNAME" :InitializeSecurityContextA(@pAS.hcred, phContext, "spn/HOSTNAME", ...);
  • spn/HOSTNAME.DOMAIN.COM :InitializeSecurityContextA(@pAS.hcred, phContext, "spn/HOSTNAME.DOMAIN.COM", ...);
  • "cargocult/PROGRAMMING" :InitializeSecurityContextA(@pAS.hcred, phContext, "cargocult/PROGRAMMING", ...);
  • "http/TFS.DOMAIN.COM" :InitializeSecurityContextA(@pAS.hcred, phContext, "http/TFS.DOMAIN.COM", ...);
  • "http/HOSTNAME" :InitializeSecurityContextA(@pAS.hcred, phContext, "http/HOSTNAME", ...);
  • "qwertyasdf" :InitializeSecurityContextA(@pAS.hcred, phContext, "qwertyasdf", ...);
  • "AuthSamp" :InitializeSecurityContextA(@pAS.hcred, phContext, "AuthSamp", ...);

  • 它们要么全部失败,要么降级为NTLM。

    注意:我的机器已加入域,但域是而不是而不是domain.com,甚至hostname.domain.com,甚至qwertyasdf。因此,对于这些尝试失败我并不感到惊讶。但是人们说尝试http/HOSTNAME之类的东西,所以我放入http/HOSTNAME

    背景

    InitializeSecurityContext (Negotiate)函数具有可选的TargetName参数:

    pszTargetName [in, optional]

    A pointer to a null-terminated string that indicates the service principal name (SPN) or the security context of the destination server.
    Applications must supply a valid SPN to help mitigate replay attacks.



    这应该是什么?

    更多背景

    我正在尝试验证一组用户凭据,例如:
    Boolean ValidateCredentials(String username, String password, String domain)
    {
       ...
    }
    

    验证一组用户凭据需要使用SSPI API。调用的第一个函数是InitializeSecurityContextInitializeSecurityContext的参数之一是“TargetName”字符串。

    我尝试将其保留为 null ,但是Application Verifier触发一个断点,写出错误:

    VERIFIER STOP 00005003: pid 0xF08:
    InitializeSecurityContext uses NULL target or malformed target for Kerberos service.
    Please see pszTargetName for the value of the target.
    00000000 : Not used.
    00000000 : Not



    在这一点上,记住Negotiate提供程序将尝试使用Kerberos会有所帮助,但会回退到NTLM。对于NegotiateKerberosNTLMTargetName参数is documented to be:

    Service principal name (SPN) or the security context of the destination server.



    但是那我应该通过什么呢?

    我尝试做SSPI知识库文章中的操作,什么也没做(即传递NULL):

    How to validate user credentials on Microsoft operating systems

    ss = _InitializeSecurityContext(
            &pAS->hcred,
            pAS->fInitialized ? &pAS->hctxt : NULL, 
            NULL,        //<-------pszTargetName
            0, 
            0,
            SECURITY_NATIVE_DREP, 
            pAS->fInitialized ? &sbdIn : NULL,
            0, 
            &pAS->hctxt, 
            &sbdOut, 
            &fContextAttr, 
            &tsExpiry);
    


    但是没有任何事情(即NULL)不起作用。

    注意:该知识库文章在2007年被大规模重写。在其最初的1999年化身中,他们将"AuthSamp"作为目标,但也失败了。

    Bonus Chatter:

    service principal name
    (SPN) The name by which a client uniquely identifies an instance of a service. If you install multiple instances of a service on computers throughout a forest, each instance must have its own SPN. A given service instance can have multiple SPNs if there are multiple names that clients might use for authentication

    security context
    The security attributes or rules that are currently in effect. For example, the current user logged on to the computer or the personal identification number entered by the smart card user. For SSPI, a security context is an opaque data structure that contains security data relevant to a connection, such as a session key or an indication of the duration of the session.



    Bonus Chatter 2

    从应用程序验证程序文档中:

    The Verifier plug detects the following errors:

    • The NTLM package is directly specified in the call to AcquireCredentialsHandle (or higher level wrapper API).

    • The target name in the call to InitializeSecurityContext is NULL.

    • The target name in the call to InitializeSecurityContext is not a properly-formed SPN, UPN or NetBIOS-style domain name.

    • The latter two cases will force Negotiate to fall back to NTLM either directly (the first case) or indirectly (the domain controller will return a “principal not found” error in the second case causing Negotiate to fall back).

    • The plug-in also logs warnings when it detects downgrades to NTLM; for example, when an SPN is not found by the Domain Controller. These are only logged as warnings since they are often legitimate cases – for example, when authenticating to a system that is not domain-joined.



    在我的情况下,我要验证的域是null(因为我不知道计算机的域名,甚至没有域)。但是,如果硬编码我的开发计算机的域名,结果是相同的。

    更新3

    触发AppVerifier错误,但登录成功的pszTargetName的值:
  • null
  • ""
  • "AuthSamp"
  • "qwertyasdf"
  • *我要针对其进行验证的域的名称(例如"avatopia.com")
  • *计算机加入的域的名称(例如"avatopia.com")
  • *用户帐户所在域的名称(例如"avatopia.com")

  • pszTargetName的值不会触发AppVerifier错误,但登录会使失败:
  • "http/HOSTNAME"
  • "http/TFS.DOMAIN.COM"
  • "frob/GROBBER"
  • "cargocult/PROGRAMMING"
  • "spn/HOSTNAME"
  • "spn/HOSTNAME.DOMAIN.COM"

  • 不会触发AppVerifier错误,登录的pszTargetname值成功:

  • 更新4

    我正在尝试做的事情:弄清楚用户名/密码是否有效。
  • 我有一个用户名:例如"ian"
  • 我有密码:例如"pass1"

  • 现在,还有一个问题是,帐户ian可以是本地帐户,也可以是帐户。您需要先确定ian是本地帐户还是域帐户,然后才能提出要求。这是因为ian可以拥有两个帐户:

    域上的
  • ian stackoverflow.com
  • 本地计算机上的
  • ian

  • 因此,我需要指定是否要:
  • 询问特定域(例如stackoverflow.com)或
  • 询问本地计算机(我将其表示为".")

  • 现在我们可以提出一个交叉引用:
    Username  Password  Domain             Machine on domain?  Validate as
    ========  ========  =================  ==================  ==============
    iboyd     pass1     .                  No                  Local account
    iboyd     pass1     (empty)            No                  Local account
    iboyd     pass1     stackoverflow.com  No                  Domain account
    
    iboyd     pass1     .                  Yes                 Local account
    iboyd     pass1     (empty)            Yes                 Domain account
    iboyd     pass1     stackoverflow.com  Yes                 Domain account
    

    更新5

    它可能有助于解释我要做什么,然后也许怎么做会变得更容易。假设我走进市区的随机办公楼,走进随机的隔间,然后输入随机的用户名和密码:

    我将尝试登录到域TURBOENCABULATOR。我指定了我想通过对我的用户名加上前缀作为TURBOENCABULATOR域的身份验证:
    TURBOENCABULATOR\ian
    

    注意:我非常怀疑该网络具有一个名为turboencabulator的域,因为名称本身仅来自from Rockwell automation。登录尝试几乎肯定会失败。但是Windows如何检查它们?

    Windows 如何尝试验证这些凭据? Windows 如何验证凭据:
  • 用户名:ian
  • 密码:pass1
  • :TURBOENCABULATOR

  • Windows 是否使用安全支持包界面?假设Windows使用协商 Kerberos 进行身份验证,那么 Windows 通过什么作为pszTarget参数?几乎可以肯定,我输入的凭据将无效。 Windows 如何确定它们是否有效? Windows 将调用什么API来验证credentails?

    Windows 是可以验证credentails。 还想验证凭据。

    也许我没有尝试连接到TURBOENCABULATOR域,而是尝试通过将该域添加到我的用户名turboencabulator.com来连接到turboencabulator.com\ian域:

    同样的问题也适用。 Windows 如何验证凭据?我想做Windows要做的事情。假设Windows使用Kerberos进行授权,那么Windows作为SSPI中的pszTargetName参数传递什么?

    也许不是尝试连接到turboencabulator.com域,而是尝试连接到turboencabulator.net域:

    请注意,在此示例中,我将域名附加到了我的用户名上,而不是在域名前面。

    也许我没有尝试连接到turboencabulator.net域,而是尝试通过用.\为我的用户名添加前缀来验证用户是否为本地(计算机)帐户:

    Windows如何根据本地帐户数据库验证用户名和密码?它是否使用带有协商包的SSPI?如果是这样,它将作为pszTargetName传递什么值?

    人们谈论的是Web服务器,http,团队基础服务器。我真的不知道他们从哪里得到的。或者他们谈论在 Activity 目录中编辑用户以确保某些内容存在-我不知道为什么需要编辑任何内容: Windows 不编辑任何内容。

    调用TargetName来验证一组凭据时,我使用什么InitializeSecurityContext

    奖金Chat不休

    这是Application Verifier文档中的一章,内容涉及为什么他们要测试是否有人错误地使用NTLM:

    Why the NTLM Plug-in is Needed

    NTLM is an outdated authentication protocol with flaws that potentially compromise the security of applications and the operating system. The most important shortcoming is the lack of server authentication, which could allow an attacker to trick users into connecting to a spoofed server. As a corollary of missing server authentication, applications using NTLM can also be vulnerable to a type of attack known as a “reflection” attack. This latter allows an attacker to hijack a user’s authentication conversation to a legitimate server and use it to authenticate the attacker to the user’s computer. NTLM’s vulnerabilities and ways of exploiting them are the target of increasing research activity in the security community.

    Although Kerberos has been available for many years many applications are still written to use NTLM only. This needlessly reduces the security of applications. Kerberos cannot however replace NTLM in all scenarios – principally those where a client needs to authenticate to systems that are not joined to a domain (a home network perhaps being the most common of these). The Negotiate security package allows a backwards-compatible compromise that uses Kerberos whenever possible and only reverts to NTLM when there is no other option. Switching code to use Negotiate instead of NTLM will significantly increase the security for our customers while introducing few or no application compatibilities. Negotiate by itself is not a silver bullet – there are cases where an attacker can force downgrade to NTLM but these are significantly more difficult to exploit. However, one immediate improvement is that applications written to use Negotiate correctly are automatically immune to NTLM reflection attacks.

    By way of a final word of caution against use of NTLM: in future versions of Windows it will be possible to disable the use of NTLM at the operating system. If applications have a hard dependency on NTLM they will simply fail to authenticate when NTLM is disabled.

    How the Plug-in Works

    The Verifier plug detects the following errors:

    • The NTLM package is directly specified in the call to AcquireCredentialsHandle (or higher level wrapper API).

    • The target name in the call to InitializeSecurityContext is NULL.

    • The target name in the call to InitializeSecurityContext is not a properly-formed SPN, UPN or NetBIOS-style domain name.

    The latter two cases will force Negotiate to fall back to NTLM either directly (the first case) or indirectly (the domain controller will return a “principal not found” error in the second case causing Negotiate to fall back).

    The plug-in also logs warnings when it detects downgrades to NTLM; for example, when an SPN is not found by the Domain Controller. These are only logged as warnings since they are often legitimate cases – for example, when authenticating to a system that is not domain-joined.

    NTLM Stops

    5000 – Application Has Explicitly Selected NTLM Package

    Severity – Error

    The application or subsystem explicitly selects NTLM instead of Negotiate in the call to AcquireCredentialsHandle. Even though it may be possible for the client and server to authenticate using Kerberos this is prevented by the explicit selection of NTLM.

    How to Fix this Error

    The fix for this error is to select the Negotiate package in place of NTLM. How this is done will depend on the particular Network subsystem being used by the client or server. Some examples are given below. You should consult the documentation on the particular library or API set that you are using.

    APIs(parameter) Used by Application    Incorrect Value  Correct Value  
    =====================================  ===============  ========================
    AcquireCredentialsHandle (pszPackage)  “NTLM”           NEGOSSP_NAME “Negotiate”
    


    也可以看看
  • InitializeSecurityContext parameter pszTargetName
  • 最佳答案

    伊恩(Ian),我想我们仍然不明白您要做什么。为了帮助您向我们提供有关您要执行的操作的更多信息,以下是有关SSPI的一些背景知识。您可能已经知道这一点,但只是为了确保我们在同一页面上。

    SSPI通常用于通过网络对用户进行身份验证。客户端调用AcquireCredentialsHandle以获得凭据句柄,然后通过调用InitializeSecurityContext创建安全上下文。将安全缓冲区传递给服务器。请注意,SSPI并不决定如何传递安全缓冲区。您可以随意使用http,tcp,命名管道。服务器收到安全缓冲区后。同样,它首先调用AcquireCredentialsHandle。然后,它将接收到的安全缓冲区传递给AcceptSecurityContext并生成新的安全缓冲区。在某些情况下,新生成的安全缓冲区需要发送回客户端,然后客户端将其传递给InitializeSecurityContext并再次生成另一个新的安全上下文。此SSPI握手过程将继续进行,直到InitializeSecurityContextAcceptSecurityContext都返回SEC_E_OK
    尽管SSPI是为通过网络进行身份验证而设计的,但实际上许多应用程序都在进行环回SSPI握手,这意味着客户端和服务器都在同一盒中。这实际上只是网络身份验证的一种特殊情况。回送SSPI握手的最终结果是经过身份验证的SSPI安全上下文。使用此经过身份验证的SSPI,应用程序可以执行QueryContextAttributesImpersonateSecurityContext。由于您似乎不知道targetName是什么意思,我猜您正在尝试进行回送握手。虽然我可能是错的,但您需要告诉我们您要做什么。

    要了解为什么在Kerberos中需要targetName而不在NTLM中需要credentials,则需要了解一些其他基础实现。

    有两种不同的方式来获取凭据句柄。通常,人们会指定使用当前的安全上下文。 (即您用来登录计算机的帐户)。您还可以提供另一组用户名/密码。不同的安全软件包对InitializeSecurityContext的含义不同。 NTLM表示它将保存密码的哈希值。 Kerberos意味着它将保存票证授予票证(TGT)。对于SSPI程序员而言,您不必为此担心。

    现在,当客户端将获取的凭据句柄传递到InitializeSecurityContext时,类似地,不同的安全包将做不同的事情。 NTLM将在第一个InitializeSecurityContext调用上生成一个NEGOTIATE数据包。生成NEGOTITATE数据包的过程中没有其他机器。 Kerberos软件包非常不同。将与KDC对话以请求所请求服务的服务票证。该服务由Kerberos中的服务主体名称(SPN)标识。我无法在这里涵盖所有细节。网络是针对NTLM的服务请求未定目标,而针对Kerberos的服务请求则定目标。您可以使用NTLM身份验证方法将相同的NTLM NEGOTIATE数据包用于不同的服务。但是,对于使用Kerberos身份验证方法的不同服务,您需要使用不同的Kerberos服务票证。这就是为什么在为Kerberos / Negotiate调用targetName时,需要提供servicePrincipalName的原因。

    当KDC收到服务票证请求时,它将在其LDAP数据库上进行搜索,并找出哪个帐户与指定的AcquireCredentialsHandle关联。该帐户可以是AD用户帐户或AD计算机帐户。 KDC将使用目标服务帐户的主密钥(由帐户密码生成)来加密 session 密钥。此加密的 session 密钥将稍后从客户端传递到服务器。

    现在,还记得我说过服务器还需要执行domain\jane的问题,并且我说过有两种主要方法来获取凭据处理吗?我想您正在使用第一种方法来获取凭据句柄。这意味着它将使用当前的安全上下文。在正常的网络身份验证情况下,可以通过以下示例进行说明。如果您的服务器是HTTP服务器,它将是IIS服务器的服务帐户。 IIS服务器将使用其服务帐户主密钥来解密加密的 session 密钥。一旦获得 session 密钥,客户端和服务器就可以使用 session 密钥继续进行通信以进行加密和解密。

    如果是环回SSPI方案,则比较棘手。如果您正在运行AcquireCredentialsHandle并自己循环回去。您需要为domain \ jane指定一个SPN。什么是domain \ jane的SPN。如果检查AD用户对象,则默认情况下没有任何对象。您需要手动修复它。

    曾经有一件事情对我有用,但是没有记载。您可以将用户的UPN(即jane@domain.com)指定为SPN。这对我有用。你可以尝试一下。

    如果那不起作用,另一种解决方法是使用第二种方法来处理服务器部分domain\jane。您可以指定另一个服务帐户凭据,而不是使用InitializeSecurityContext凭据句柄。您可以确保该服务帐户设置了正确的SPN。然后,您可以在ojit_code中使用该服务帐户的SPN。当然,这也意味着您需要在代码中对服务帐户的密码进行硬编码。您需要小心并确保完全锁定此服务帐户,以便即使密码被盗,您的AD环境也不会受到很大的威胁。

    关于security - 调用InitializeSecurityContext(协商)时要使用什么TargetName?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9788318/

    相关文章:

    php - 使用 md5 哈希作为注册字符串 token 是否安全?

    c++ - Windows API 中的驱动器/分区和唯一驱动器 ID

    c# - 从 session 0(服务)启动提升的用户进程

    hadoop - OpenTSDB 与 kerberized HBase 集成

    java - 在同一 Java 应用程序中使用不同的 Kerberos KDC 进行身份验证

    security - parse.com 安全性

    security - Logstash:logstash输入中的多个插件

    windows - Windows 从休眠状态恢复时如何运行任意代码?

    python - 如何在 Python 应用程序中建立与 Kerberos 的连接?

    iphone - 源代码安全 - 与公司合作 iOS