0

We are reconfiguring a SPNEGO / Kerberos SSO application to use AES128 / AES256 instead of the the weak encryption ciphers DES and RC4.

Some days ago I posted a preparatory question: Now we have a concrete error.

The token supplied to the function is invalid.

The components:

The Kerberos “back-end” is Windows Active Directory

The Application Server uses pure Java GSSAPI and runs on Windows Server.

The client runs on Windows 10, and is written in Java. It has 2 SPNEGO / SSO implementations:

  • pure Java GSSAPI
  • native Windows SSPI via Waffle and JNA.

We can switch the client SSO implementation by configuration. As SSPI and GSSAPI are interoperable, in either case the server remains pure Java GSSAPI.

The client and server use the SPNEGO protocol, but only support Kerberos, not NTLM.

In the “old” setup, using enctype RC4, the client is successfully authenticated, and successfully validates the SPNEGO token in the response from the server using either GSSAPI or SSPI.

The new configuration:

We then made changes to the configuration of the client, server, SPN, etc, removing RC4 / DES and enabling AES128.

After that change:

1) klist shows that the client has an AES128 TGT for the server SPN.

2) Using GSSAPI: the client is successfully authenticated by the server, and successfully validates the SPNEGO token in the response from the server —> OK.

3) Using SSPI: the client is successfully authenticated by the server, but cannot validate the SPNEGO token in the response from the server —> NOT OK.

The problem:

Instead we get the error: ”The token supplied to the function is invalid”.

Reading the Waffle code indicates that this error likely comes from Secure32.dll https://github.com/Waffle/waffle/blob/0c6f832222b59537847281adf7d2959583809dff/Source/WindowsAuthProvider/Secur32.cs

The “invalid” token starts with “oY…” indicating a KRB_AP_REP, and looks very similar to the tokens created using RC4, other than it is slightly longer.

As the token can validated using GSSAPI, I am reasonably sure that it is valid. Instead we suspect that the problem lies with the configuration of Windows 10 Workstation or user.

Googling for the error produces some hits, but none directly related to SSPI / SPNEGO SSO. I am reluctant to hack random registry settings without a clearer understanding of what we are changing. e.g.

TLS 1.2 - The token supplied to the function is invalid

SQL Server error after update: The token supplied to the function is invalid

Any ideas?

Note: While the pure GSSAPI client currently works, this option will die if Windows Credential Guard is activated (thus blocking access to the TGT). Once that happens, SSPI will be the only viable solution.


Update

We have spent a morning using Wireshark to analyse the requests and responses, and have discovered the following:

Request from Client using GSSAPI

  • negTokenInit / MechTypes —> contains only 1 mech type: for KRB5

Request from Client using SSPI

  • negTokenInit / MechTypes —> contains 4 mech types: for KRB5, MS KRB5, NEGOEX and NTLMSSP

Response from GSSAPI to a GSSAPI request using AES128 (token OK)

  • This response token is 32 chars long, and is identical that that produced on my Linux development environment. e.g.

    oRQwEqADCgEAoQsGCSgGSIb3EgECAg==

Response from GSSAPI to a SSPI request using RC4 (token OK)

  • Wireshark —> TODO: Given that the token is much longer than that made to a GSSAPI request. It will be interesting to see what is contains.

  • This response token is 320 chars long. e.g.

    oYHrMIHooA…CZKm8y+Kx8sow==

Response from GSSAPI to a SSPI request using AES128 (token NOT OK)

  • Wireshark does not show this response using the Http filter - even though the client receives the response, inc. body. Wireshark only shows the response as TCP/IP packets. We suspect that Wireshark has the same problem as SSPI in processing this as an SPNEGO token.

  • This response token is 328 chars long, i.e. 8 chars longer than the RC4 equivalent above. e.g.

    oYHzMIHwoA…4AE6jfTHu+U2qMMestyHKpH

We initially suspected that this token might have been mangled (e.g. cut short) “in-transit”, but could prove that the token was identical in length before being added by the server to the response headers to that received by the client.

The token is taken direct from the GSSAPI, before being base64 encoded and added to the response headers.

byte token[] = gssContext.acceptSecContext(gssapiData, offset, gssapiData.length);

We updated the Application Server from Oracle Java 8u45 to AdoptOpenJDK 11.0.6, but this changed nothing.

FlyingSheep
  • 804
  • 1
  • 9
  • 20
  • Did you check the token in Wireshark? – Michael-O Feb 26 '20 at 22:20
  • @Michael-O Wireshark is something we are working on, but getting the rights to do so in an Enterprise setup may not be quick. The Requests and Responses are via Https which adds another dimension of complexity. I spent some hours last night playing with Wireshark on my Linux Dev workstation until my brain turned into scrambled eggs and therefore decided to post this question in the meantime. – FlyingSheep Feb 27 '20 at 05:56
  • As an a example I sent my collegues this link: https://medium.com/@robert.broeckelmann/kerberos-wireshark-captures-a-spnego-example-e22e6b1d662a with examples of wireshark and spnego tokens. – FlyingSheep Feb 27 '20 at 06:10
  • The difference in mech types is perfectly normal. GSS-API support only KRB5 as a SPNEGO sub mech. I see no reason to use RC4 it is old and unsecure. Disable it immediately on your domain controller. MIT Kerberos and Java will follow suit. – Michael-O Mar 02 '20 at 12:43
  • 1
    Let's now get to your problem. Provide the Base 64 encoded version to https://lapo.it/asn1js/ and see whether it can be decoded. Moreover, calculate the SHA256 sum of your token on the server, and inspect the reponse token with curl. Calculate again. curl works perfectly with GSS-API and SSPI. – Michael-O Mar 02 '20 at 12:47
  • @Michael-O Our desire to disable RC4 is the reason for this thread! But until we get SSPI working with AES we cannot do so. We are working on decoding the problem response as you suggest above. – FlyingSheep Mar 02 '20 at 14:12
  • @Michael-O The problem token parses properly with lapo.it/asn1js. The structure appears identical to a response token produced with pure GSSAPI with mutalAuth=true on Linux. I need to do a field by field comparision before saying more. – FlyingSheep Mar 02 '20 at 15:57
  • Alright, will wait. – Michael-O Mar 02 '20 at 19:39
  • @Michael-O Using the ASN.1 decoder I have compared 3 response tokens, all made with mutalAuth=true: 1) Resp to SSPI Req with AES256 (NOT OK) 2) Resp to SSPI Req with RC4 (OK but to be deactivated) 3) Resp to GSS Req with AES128 (OK if Credential Guard not active). All can be parsed as ASN. They are identical in structure. The OIDs and enctypes used are visible. They differ only in: a) OIDs used 1.2.840.48018.1.2.2 vs 1.2.840.113554.1.2.2, b) enctypes (18, 23, 17), c) encrypted octet streams. d) length by a few bytes. – FlyingSheep Mar 03 '20 at 09:27
  • Examining the original requests showed that SSPI had mutalAuth flag = true, GSSAPI mutalAuth = false. With mutalAuth = true the response tokens are noticeably longer then when false. We have changed the GSSAPI client code to configure mutalAuth true/false as desired, and are puzzling how to do this for SSPI. https://stackoverflow.com/questions/60490501/waffle-sspi-how-to-set-the-spnego-mutualflag. – FlyingSheep Mar 03 '20 at 09:46
  • I would not recommend to disable mutual authentication. This makes the peer (server) trustworthy. – Michael-O Mar 03 '20 at 12:29
  • @Michael-O I don't want to disable mutal auth for real, but I want to try this on dev to narrow down the root cause of our problem. i.e. try both SSPI and GSSAPI with mutal auth true and false to see if it makes any difference. – FlyingSheep Mar 03 '20 at 13:04

0 Answers0