Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
965 views
in Technique[技术] by (71.8m points)

java - Browsers keeps sending NTLM token instead of Kerberos - How to solve it?

I can't seem to correctly configure the system and have the browser send a ticket to the web-server. Instead, a NTLM token is sent.

Q: How can I solve this?

All details and configurations are listed below.


Infrastructure:

I have three machines within the domain COMPANY.local:

  • PC-I7.COMPANY.local (on 192.168.0.5). It acts as KDC, it's an Active-Directory server with the other machines (see below) registered in the AD. Also has the DNS for the local network configured. The domain in the Active Directory is: COMPANY.local
  • SOFTWARE.COMPANY.local (on 192.168.0.10) runs the web-application which has the Jetty/SPNego support configured.
  • OTHER.COMPANY.local (on 192.168.0.9), just a client so I can access the software server from another machine.

The last two are actually VMs running on a linux server in the intranet. They are reachable with their own IP. Their primary DNS in Network Configuration points to 192.168.0.5.

Both are joined in COMPANY.local and are present as computers in the AD.

I know client and server should stay on different machines; and being them onto two different VM's should avoid this issue.

All three machines are registered as A hosts in the DNS with a reverse pointer for each of them in the Reverse lookup zone.


SPN

After having created the user software in the Active Directory, I generate the keytab file

ktpass -princ HTTP/[email protected] -mapuser [email protected] -crypto ALL -ptype KRB5_NT_PRINCIPAL -pass __PassForADUserSoftware__ -out C:/winnt/krb5.keytab

I get the following output which seems to contain an error:

Targeting domain controller: PC-I7.COMPANY.local
  Failed to set property 'userPrincipalName' to 'HTTP/[email protected]' on Dn 'CN=Software SSO Kerberized WebServer,DC=COMPANY,DC=local': 0x13.
  WARNING: Failed to set UPN HTTP/[email protected] on CN=Software SSO Kerberized WebServer,DC=COMPANY,DC=local.
  kinits to 'HTTP/[email protected]' 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/[email protected] ptype 1 (KRB5_NT_PRINCIPAL) vno 8 etype 0x1 (DES-CBC-CRC) keylength 8 (0x0bf1688040abadba)
keysize 64 HTTP/[email protected] ptype 1 (KRB5_NT_PRINCIPAL) vno 8 etype 0x3 (DES-CBC-MD5) keylength 8 (0x0bf1688040abadba)
keysize 72 HTTP/[email protected] ptype 1 (KRB5_NT_PRINCIPAL) vno 8 etype 0x17 (RC4-HMAC) keylength 16 (0x737d9811dd38e108741461ba79153192)
keysize 88 HTTP/[email protected] ptype 1 (KRB5_NT_PRINCIPAL) vno 8 etype 0x12 (AES256-SHA1) keylength 32 (0xcc8ab2939f822f9df6904a987954e0cfaa261bc36803af6c5f8d9a98f1d4f2aa)
keysize 72 HTTP/[email protected] ptype 1 (KRB5_NT_PRINCIPAL) vno 8 etype 0x11 (AES128-SHA1) keylength 16 (0xd616b814dcd1b955f125ab4de5895d39)

The AD user has the two This account supports the Kerbers AES-... checkboxes checked.


The OTHER.COMPANY.local server

I login to this machine via RDP with the credentials:

user: Administrator
pass: ARandomPass

When asking for a ticket from OTHER server with

kinit HTTP/[email protected]

I can see this packets with wireshark

Packet traffic from browser server to KDC

Internet explorer (and therefore Chrome) have the following settings in Internet Options:

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

When I reach the web application on http://software.company.local:8998/software/login

I can see the browser sends a NTLM request

Wireshark: Browser sends a NTLM request

and I can see the Defective Token exception on the server side

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)

Also this info appears in the java log:

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/[email protected] tryFirstPass is false 
useFirstPass is false storePass is false clearPass is false

Information I can gather from the linked answer:

  • Point 1: The SPN for the HTTP service does match the URL entered by the browser. I input software.company.local in the browser which is the same as the SPN HTTP/[email protected]

  • Point 2: *.company.local is added to the trusted sites.

  • Point 3: I'm not restricting the encrpytion to DES-CBC-MD5

  • Point 3: I have checked AES-128 and AES-256 ... but not DES because the Windows Server version I am working with has the checkbox saying Use only Kerberos DES encryption types for this account, which is not what I want. Should I check it?


The SOFTWARE.COMPANY.local server

The web-application is registered as a Windows Server.

These are the configuration files:

krb5.ini file:

[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 file:

com.sun.security.jgss.initiate {
    com.sun.security.auth.module.Krb5LoginModule required
    principal = "HTTP/[email protected]"
    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/[email protected]"
    useKeyTab = true
    keyTab = "C:/software/inst/modules/common-config/auth/krb5.keytab"
    storeKey=true
    debug=true
    isInitiator=false;
};

and this is the spnego.properties file:

targetName = HTTP/software.company.local

My jetty-web.xml configuration file contains:

<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>

This is how I programmatically register the spnego configuration in Java:

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.getStrin

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Apparently, having client and server on two distinct virtual machines ( that are on the same physical server! ) can lead to a NTLM token.

I thought VM's would dodge the client-and-server-on-the-same-machine-issue.

So, if you

  • like me, are testing with VM's residing on the same physical machine, and
  • have set everything right but still getting a Defective token detected,

you should try to access the server from a different computer (as long as that machine is joined to the company domain).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...