none
NTLM authentication issues with Microsoft-HTTPAPI/2.0 RRS feed

  • Question

  • I am implementing a WS-Management client, which will communicate with the Windows Management service via HTTP on port 5985.  I can communicate successfully using basic authentication, but that is not a realistic means of authentication in the real world, so I am working to support stronger authentication methods and encryption... one step at a time.

    I have been working very diligently according to the NTLM specification, to authenticate with the service using a local (machine) account, but I always get a 401 response to my authenticate message.  I intercepted HTTP traffic from winrm to analyze it and compare to my own authentication headers and I've noticed a some peculiarities.

    Here is my hand-annotated analysis of winrm's authenticate message (from the Authenticate HTTP header):

    4e544c4d53535000    NTLMSSP\0

    03000000                   Type 3 message

    1800 1800 7c000000 LM security buffer data (i.e., len, max_len, offset)

    ee00 ee00 94000000 NT security buffer data

    0c00 0c00 58000000 domain security buffer data

    0c00 0c00 64000000 user security buffer data

    0c00 0c00 70000000 target security buffer data

    1000 1000 82010000 session-key security buffer data

    158288e2                 flags

    0601b11d0000000f  Windows7 version

    b15c1c0a91f995cbb3c5a11bc335906e  MIC

    Payload (starts at offset 88):

    540041005200440049005300  domain

    73006f006c0069006e006400  username

    540041005200440049005300  host string

    000000000000000000000000000000000000000000000000  LM data

    NT Data (238 bytes):

    af61995cadd9356dfd97ee4208876f8701010000000000002e62b098946acd0163844ecdcaf8615f0000000002000c0054004100520044004900530001000c0054004100520044004900530004000c0054004100520044004900530003000c00540041005200440049005300070008002e62b098946acd010600040002000000080030003000000000000000000000000030000037ef9963dfd0f6bab13ea8e0a9a0b9532cf2027e6d5206ffc5bbcb053bd31dc20a001000000000000000000000000000000000000900160048005400540050002f00540041005200440049005300000000000000000000000000

    Session Key:

    2969d300e08d04d50f77c931e196c882

    I noticed that the NT data contains a lot more information than the specification indicates:

    Set temp to ConcatenationOf(Responserversion, HiResponserversion, Z(6), Time, ClientChallenge, Z(4), ServerName, Z(4))

    Set NTProofStr to HMAC_MD5(ResponseKeyNT, ConcatenationOf(CHALLENGE_MESSAGE.ServerChallenge,temp))

    Set NtChallengeResponse to ConcatenationOf(NTProofStr, temp)

    My authentication NTChallengeResponse buffer ends up being about half the length.

    What is the extra information in the challenge response, and is it truly required?  If not, how might I go about determining why my NTLM authentication attempts are failing?

    Thursday, July 26, 2012 12:18 AM

Answers

  • This issue has been resolved!

    It turns out that the problem was that my HTTP client was not performing the entire negotiation inside of a single TCP connection (via HTTP 1.1 Keep-Alive).  This is necessary for the login to function properly.
    • Marked as answer by fhv_dave Friday, August 10, 2012 6:15 PM
    Friday, August 10, 2012 6:14 PM

All replies

  • Hi fhv_dave:

    I'll help you with this issue and would be in touch as soon as I have an answer.


    Regards, Obaid Farooqi

    Thursday, July 26, 2012 4:19 PM
    Owner
  • Hi

    The NTChallengeResponse field in your example does not contain any extra data. All the components of the NTChallengeResponse are documented in MS-NLMP. Please pay attention to the fact that ServerName in temp is just not the server name but a bunch of AvPairs. As explained in section 3.3.2 of MS-NLMP:

    ServerName - The NtChallengeResponseFields.NTLMv2_RESPONSE.NTLMv2_CLIENT_CHALLENGE.AvPairs field structure of the AUTHENTICATE_MESSAGE payload.

    In your question, I was able to decode the whole NTChallengeResponse using the information in MS-NLMP. ServerName makes the bulk of the message. I have broken ServerName into AvPairs for clarity. AvPairs are defined in section “2.2.2.1 AV_PAIR”.

    NtProofStr  = af61995cadd9356dfd97ee4208876f87  

    Responserversion = 01

    HiResponserversion = 01

    Z96) = 000000000000

    Time = 2e62b098946acd01

    ClientChallenge = 63844ecdcaf8615f

    Z(4)= 00000000

    ServerName = 0200 0c00 540041005200440049005300 (MsvAvNbDomainName)

    0100 0c00 540041005200440049005300 (MsvAvNbComputerName)

    0400 0c00 540041005200440049005300 (MsvAvDnsDomainName)

    0300 0c00 540041005200440049005300 (MsvAvDnsComputerName)

    0700 0800 2e62b098946acd01 (MsvAvTimestamp)

    0600 0400 02000000 (MsvAvFlags)

    0800 3000 3000000000000000000000000030000037ef9963dfd0f6bab13ea8e0a9a0b9532cf2027e6d5206ffc5bbcb053bd31dc2 (MsAvRestrictions)

    0a00 1000 00000000000000000000000000000000 (MsvChannelBindings)

    0900 1600 48005400540050002f00540041005200440049005300 (MsvAvTargetName)

    0000 0000 (MsvAvEOL)

    Z(4)= 00000000

    Padding = 00000000

    As you can see in the algorithm in section 3.3.2 that all this data is required for authentication, since the calculation of NtProofStr includes temp.

    Please include all the fields that are mentioned in MS-NLMP section 3.3.2, paying special attention to ServerName as I explained above and let us know if that still does not solve your issue.


    Regards, Obaid Farooqi

    Thursday, July 26, 2012 10:16 PM
    Owner
  • Hi Obaid,

    Thank you so much for your prompt assistance!

    According to 3.3.2: ServerName - The TargetInfo field structure of the CHALLENGE_MESSAGE payload.

    In my case, the challenge message I receive from the server is this (these are the Base64-decoded bytes from the Authenticate HTTP header):

    4e544c4d53535000020000000c000c003800000015ffffff82ffffff8affffffe2ffffffa81d2fffffffcf22ffffff8e420e000000000000000050005000440000000601ffffffb11d0000000f54004100520044004900530002000c0054004100520044004900530001000c0054004100520044004900530004000c0054004100520044004900530003000c0054004100520044004900530007000800ffffffb45f05ffffffe6ffffffa26bffffffcd0100000000

    And hence, the ServerName I get from the challenge is:

    02000c0054004100520044004900530001000c0054004100520044004900530004000c0054004100520044004900530003000c0054004100520044004900530007000800ffffffb45f05ffffffe6ffffffa26bffffffcd0100000000

    Parsed, the MsvAv pairs are:

    Domain Name: 540041005200440049005300

    Computer Name: 540041005200440049005300

    DNS Domain Name: 540041005200440049005300

    Computer Name: 540041005200440049005300

    Timestamp: ffffffb45f05ffffffe6ffffffa26bffffffcd01

    EOL: 00000000

    So, as you see, flags, restrictions, channel bindings and msvavtargetname do not appear in the challenge message ... how am I supposed to decide that they should be added to the response?

    Regards,

    --David

    Friday, July 27, 2012 3:26 AM
  • Hi David:

    The server uses whatever AV pairs are provided in the client authenticate messages. Some clients choose to include all the AvPairs. This does not necessarily have to be the same as the ones sent by the server. You can use the ones that server sent in the challenge messages and that should work too if you included the same AvPairs in the authenticate message that you used to calculate the NtProofStr.

    The do not have to include all AvPairs for successful authentication.

    Please let me know if it resolves your problem.


    Regards, Obaid Farooqi

    Friday, July 27, 2012 5:07 PM
    Owner
  • Hi Obaid,

    I am literally using the exact targetInfo bytes that I get from the server in the challenge message, to compute the NtProofStr, but I get back a 401.

    This is a sample conversation:

    My negotiate message:

    4e544c4d5353500001000000158208e20c000c00280000000c000c00340000000601b11d0000000f540041005200440049005300540041005200440049005300

    Server challenge response:

    4e544c4d53535000020000000c000c003800000015ffffff82ffffff8affffffe21f1e723072ffffffc3fffffff9ffffffe7000000000000000050005000440000000601ffffffb11d0000000f54004100520044004900530002000c0054004100520044004900530001000c0054004100520044004900530004000c0054004100520044004900530003000c00540041005200440049005300070008002bffffffcf5d321b6cffffffcd0100000000

    My authenticate message:

    4e544c4d5353500003000000180018005800000080008000700000000c000c00f00000000c000c00fc0000000c000c00080100001000100014010000158288e20601b11d0000000f4c6281f51749b72cd3a677680c4ce6d80000000000000000000000000000000000000000000000003e194c35b70ed3d3eff4b174bad01a6701010000000000002bcf5d321b6ccd0189387152457e37470000000002000c0054004100520044004900530001000c0054004100520044004900530004000c0054004100520044004900530003000c00540041005200440049005300070008002bcf5d321b6ccd01000000000000000054004100520044004900530073006f006c0069006e006400540041005200440049005300f75748080064563bd7155e1cef17dab2

    It looks to me like this /should/ succeed, and yet it does not.

    If there are AvPairs that I must send in the authenticate message that are not in the challenge, which should I send?  Where does the information come from?  Where is it documented?

    Regards,

    --David

    Friday, July 27, 2012 5:20 PM
  • Hi David:

    What is the password? I'll use that to verify if you are calculating the response correctly.

    Using the AvPairs that server sends should work fine.

    Please send me the network trace with the password at dochelp at microsoft dot com.


    Regards, Obaid Farooqi

    Friday, July 27, 2012 9:08 PM
    Owner
  • This issue has been resolved!

    It turns out that the problem was that my HTTP client was not performing the entire negotiation inside of a single TCP connection (via HTTP 1.1 Keep-Alive).  This is necessary for the login to function properly.
    • Marked as answer by fhv_dave Friday, August 10, 2012 6:15 PM
    Friday, August 10, 2012 6:14 PM