【问题标题】:Browsers keeps sending NTLM token instead of Kerberos - How to solve it?浏览器不断发送 NTLM 令牌而不是 Kerberos - 如何解决?
【发布时间】:2018-12-07 12:00:00
【问题描述】:

我似乎无法正确配置系统并让浏览器向网络服务器发送 票证。而是发送NTLM 令牌。

问:我该如何解决这个问题?

下面列出了所有详细信息和配置。


基础设施:

我在域COMPANY.local 中有三台机器:

  • PC-I7.COMPANY.local(在192.168.0.5)。它充当KDC,它是一个Active-Directory 服务器,其他机器(见下文)在AD 中注册。还为本地网络配置了DNS。 Active Directory 中的域是:COMPANY.local
  • SOFTWARE.COMPANY.local(在 192.168.0.10 上)运行配置了 Jetty/SPNego 支持的 Web 应用程序。
  • OTHER.COMPANY.local192.168.0.9),只是一个客户端,所以我可以从另一台机器访问软件服务器。

最后两个实际上是VMs 在内网的linux 服务器上运行。它们可以通过自己的 IP 访问。他们在Network Configuration 中的主要DNS 指向192.168.0.5

两者都加入COMPANY.local,并在AD 中作为计算机存在。

我知道客户端和服务器should stay on different machines;并将它们放在两个不同的VM 上应该可以避免这个问题。

所有三台机器都在DNS 中注册为A 主机,并在Reverse lookup zone 中为每台机器注册一个反向指针。


SPN

在 Active Directory 中创建用户 software 后,我生成 keytab 文件

ktpass -princ HTTP/software.company.local@COMPANY.LOCAL -mapuser software@COMPANY.LOCAL -crypto ALL -ptype KRB5_NT_PRINCIPAL -pass __PassForADUserSoftware__ -out C:/winnt/krb5.keytab

我得到以下似乎包含错误的输出:

Targeting domain controller: PC-I7.COMPANY.local
  Failed to set property 'userPrincipalName' to 'HTTP/software.company.local@COMPANY.LOCAL' on Dn 'CN=Software SSO Kerberized WebServer,DC=COMPANY,DC=local': 0x13.
  WARNING: Failed to set UPN HTTP/software.company.local@COMPANY.LOCAL on CN=Software SSO Kerberized WebServer,DC=COMPANY,DC=local.
  kinits to 'HTTP/software.company.local@COMPANY.LOCAL' will fail.
Successfully mapped HTTP/software.company.local to software.
Password successfully set!
Key created.
Key created.
Key created.
Key created.
Key created.
Output keytab to C:/winnt/krb5.keytab:
Keytab version: 0x502 
keysize 64 HTTP/software.company.local@COMPANY.LOCAL ptype 1 (KRB5_NT_PRINCIPAL) vno 8 etype 0x1 (DES-CBC-CRC) keylength 8 (0x0bf1688040abadba)
keysize 64 HTTP/software.company.local@COMPANY.LOCAL ptype 1 (KRB5_NT_PRINCIPAL) vno 8 etype 0x3 (DES-CBC-MD5) keylength 8 (0x0bf1688040abadba)
keysize 72 HTTP/software.company.local@COMPANY.LOCAL ptype 1 (KRB5_NT_PRINCIPAL) vno 8 etype 0x17 (RC4-HMAC) keylength 16 (0x737d9811dd38e108741461ba79153192)
keysize 88 HTTP/software.company.local@COMPANY.LOCAL ptype 1 (KRB5_NT_PRINCIPAL) vno 8 etype 0x12 (AES256-SHA1) keylength 32 (0xcc8ab2939f822f9df6904a987954e0cfaa261bc36803af6c5f8d9a98f1d4f2aa)
keysize 72 HTTP/software.company.local@COMPANY.LOCAL ptype 1 (KRB5_NT_PRINCIPAL) vno 8 etype 0x11 (AES128-SHA1) keylength 16 (0xd616b814dcd1b955f125ab4de5895d39)

AD 用户选中了两个 This account supports the Kerbers AES-... 复选框。


OTHER.COMPANY.local 服务器

我使用凭据通过RDP 登录到这台机器:

user: Administrator
pass: ARandomPass

当从OTHER服务器请求一张票时

kinit HTTP/software.company.local@COMPANY.LOCAL

我可以通过wireshark看到这个数据包

Internet Explorer(以及 Chrome)在 Internet Options 中具有以下设置:

Security > Local Intranet > Sites > *.company.local
Security > Custom level > Automatic logon only in Intranet area

当我到达http://software.company.local:8998/software/login 上的网络应用程序时

我可以看到浏览器发送了一个NTLM 请求

我可以在服务器端看到Defective Token exception

WARN:oejs.SpnegoLoginService:qtp506835709-28: 
GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag)
at sun.security.jgss.GSSHeader.<init>(GSSHeader.java:97)
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:306)
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:285)
at org.eclipse.jetty.security.SpnegoLoginService.login(SpnegoLoginService.java:138)
at org.eclipse.jetty.security.authentication.LoginAuthenticator.login(LoginAuthenticator.java:61)
at org.eclipse.jetty.security.authentication.SpnegoAuthenticator.validateRequest(SpnegoAuthenticator.java:99)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:483)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
at org.eclipse.jetty.server.Server.handle(Server.java:524)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
at java.lang.Thread.run(Thread.java:748)

此信息也出现在java 日志中:

Debug is true storeKey true useTicketCache false useKeyTab true doNotPrompt false 
ticketCache is null isInitiator false 
KeyTab is C:/software/inst/modules/common-config/auth/krb5.keytab refreshKrb5Config is false 
principal is HTTP/software.company.local@COMPANY.LOCAL tryFirstPass is false 
useFirstPass is false storePass is false clearPass is false

我可以从链接答案中收集到的信息:

  • 第 1 点:HTTP 服务的 SPN 与浏览器输入的 URL 匹配。我在浏览器中输入software.company.local,和SPN一样HTTP/software.company.local@COMPANY.LOCAL

  • 第 2 点:*.company.local 已添加到受信任站点。

  • 第 3 点:我没有将加密限制为 DES-CBC-MD5

  • 第 3 点:我检查了 AES-128AES-256 ... 但没有检查 DES,因为我正在使用的 Windows Server 版本的复选框显示 Use only Kerberos DES encryption types for this account,这不是我想要的.我应该检查一下吗?


SOFTWARE.COMPANY.local 服务器

网络应用程序已注册为 Windows 服务器。

这些是配置文件:

krb5.ini文件:

[libdefaults]
default_realm = COMPANY.LOCAL
permitted_enctypes = rc4-hmac,aes128-cts,aes256-cts,arcfour-hmac-md5,aes256-cts-hmac-sha1-96    
default_tgs_enctypes = rc4-hmac,aes128-cts,aes256-cts,arcfour-hmac-md5,aes256-cts-hmac-sha1-96
default_tkt_enctypes = rc4-hmac,aes128-cts,aes256-cts,arcfour-hmac-md5,aes256-cts-hmac-sha1-96
default_keytab_name = FILE:C:/software/inst/modules/common-config/krb5.keytab

[domain_realm]
COMPANY.local = COMPANY.LOCAL
.company.local = COMPANY.LOCAL

[realms]
COMPANY.LOCAL = {
    admin_server = PC-I7.COMPANY.local
    kdc = PC-I7.COMPANY.local:88
}

spnego.conf文件:

com.sun.security.jgss.initiate {
    com.sun.security.auth.module.Krb5LoginModule required
    principal = "HTTP/software.company.local@COMPANY.LOCAL"
    keyTab = "C:/software/inst/modules/common-config/auth/krb5.keytab"
    useKeyTab = true
    storeKey = true
    debug = true
    isInitiator = false;
};

com.sun.security.jgss.accept {
    com.sun.security.auth.module.Krb5LoginModule required
    principal = "HTTP/software.company.local@COMPANY.LOCAL"
    useKeyTab = true
    keyTab = "C:/software/inst/modules/common-config/auth/krb5.keytab"
    storeKey=true
    debug=true
    isInitiator=false;
};

这是spnego.properties 文件:

targetName = HTTP/software.company.local

我的jetty-web.xml 配置文件包含:

<Get name="securityHandler">
    <Set name="loginService">
        <New class="org.eclipse.jetty.security.SpnegoLoginService">
            <Set name="name">Company Realm</Set>
            <Set name="config">
                <SystemProperty name="jetty.home" default="."/>/modules/common-config/auth/spnego.properties</Set>
        </New>
    </Set>
    <Set name="checkWelcomeFiles">true</Set>
</Get>

这就是我在Java 中以编程方式注册spnego 配置的方式:

private SecurityHandler wrapEnableSSOAuthHandlers(final Handler collection) {

    // ini file
    System.setProperty(
            "java.security.krb5.conf",
            _config.getString("authentication.win_sso.spnego.krb5") // the krb5.ini file
    );
    System.setProperty(
            "java.security.auth.login.config",
            _config.getString("authentication.win_sso.spnego.login") // the spnego.conf file
    );
    System.setProperty(
            "javax.security.auth.useSubjectCredsOnly",
            "false"
    );

    final Constraint spnegoConstraint = new Constraint();
    spnegoConstraint.setName(Constraint.__SPNEGO_AUTH);

    final String domainRealm = _config.getString("authentication.win_sso.domain.realm");    // resolves to COMPANY.LOCAL

    spnegoConstraint.setRoles(new String[]{domainRealm});
    spnegoConstraint.setAuthenticate(true);

    final ConstraintMapping mapping = new ConstraintMapping();
    mapping.setConstraint(spnegoConstraint);
    mapping.setPathSpec("/*");

    final String spnegoProperties = _config.getString("authentication.win_sso.spnego.properties");      // the spnego.properties file

    final SpnegoLoginService loginService = new SpnegoLoginService();
    loginService.setConfig(spnegoProperties);
    loginService.setName(domainRealm);

    final ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
    securityHandler.setLoginService(loginService);
    securityHandler.setConstraintMappings(new ConstraintMapping[]{mapping});
    securityHandler.setRealmName(domainRealm);
    securityHandler.setAuthenticator(new SpnegoAuthenticator());
    securityHandler.setHandler(collection);
    return securityHandler;
}

// here I disable the TRACE method for all calls 
Handler wrappedSecurityHandler = wrapDisableTraceHandlers(handlers);
wrappedSecurityHandler = wrapEnableSSOAuthHandlers(wrappedSecurityHandler);
_server.setHandler(wrappedSecurityHandler);

编辑 1:附加信息

我已经下载了Kerberos Authentication Tester Tool,当从KDC 服务器(192.168.0.5) 运行它并针对http://software.company.local:8998 进行测试时,它显示了正确的Kerberos 身份验证。

192.168.0.10 服务器(浏览器所在的位置)运行它时,它会说:

意外的授权标头

及认证方式:NTLM

我猜这要么是DNS 的问题,要么是它们是同一服务器上的两个VM

【问题讨论】:

    标签: kerberos jetty jetty java active-directory jetty kerberos spnego


    【解决方案1】:

    显然,将客户端和服务器放在两个不同的虚拟机上(在同一台物理服务器上!)可能会产生NTLM 令牌。

    我以为VM 会避开client-and-server-on-the-same-machine-issue

    所以,如果你

    • 和我一样,正在使用驻留在同一物理机器上的VM 进行测试,并且
    • 一切都已正确设置,但仍收到Defective token detected

    您应该尝试从另一台计算机访问server(只要该计算机已加入公司域)。

    【讨论】:

    • 嗨,Marko,我在开发基于 CAS、Kerberos 和 AD 的自定义访问管理解决方案时遇到了同样的问题。事实上,我在 Linux 机器上运行 Kerberos,但 CAS 在我的本地 tomcat 上运行。我看到 CAS 总是属于 NTML 身份验证,实际上我收到的令牌总是包含 NTML 机制标识。因此,显然,除非 CAS 在另一台机器上运行,否则无法执行此操作。我将测试这个场景并让你知道。
    猜你喜欢
    • 2014-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-14
    • 2012-07-16
    • 2011-02-27
    • 1970-01-01
    相关资源
    最近更新 更多