none
CredSSP ServerClientHash Computation RRS feed

  • Question

  • Hi

    This is in response to the question https://social.msdn.microsoft.com/Forums/en-US/e24be500-b5bb-4409-a3e3-7c969a95fb19/credssp-protocol-versions?forum=os_windowsprotocols. I have installed the March KB on a Server 2016 host and I am trying to verify the server like the process in step 5 (https://msdn.microsoft.com/en-us/library/cc226791.aspx). I am able to verify the server if I specify the client protocol version to 4 as expected but when I change it to version 6 I am not able to validate the response is what it should be. So far here is a basic overview of the code;

    # the following variables are defined and used in the
    # hash calculations
    ClientServerHashMagic = "CredSSP Client-To-Server Binding Hash\0"
    # this is utf-8 encoded byte string, e.g. hex is
    # 43 72 65 64 53 53 50 20
    # 43 6C 69 65 6E 74 2D 54 
    # 6F 2D 53 65 72 76 65 72
    # 20 42 69 6E 64 69 6E 67
    # 20 48 61 73 68 00
    
    ServerClientHashMagic = "CredSSP Server-To-Client Binding Hash\0"
    # this is utf-8 encoded byte string, e.g. hex is
    # 43 72 65 64 53 53 50 20 
    # 53 65 72 76 65 72 2D 54 
    # 6F 2D 43 6C 69 65 6E 74
    # 20 42 69 6E 64 69 6E 67
    # 20 48 61 73 68 00
    
    Nonce = 32-byte random binary value
    SubjectPublicKey = The SubjectPublicKey field of the servers public certificate retrieved during the TLS Handshake
    SecContext = A handle to the authenticated sec context
    
    ### Step 1 - Generate client pubKeyAuth value
    ClientServerHash = SHA256(ClientServerHashMagic + Nonce + SubjectPublicKey)
    ClientHash = SecContext.Wrap(ClientServerHash)
    
    TSRequest.version = 6
    TSRequest.pubKeyAuth = ClientHash
    TSRequest.clientNonce = Nonce
    
    ### Step 2 - Send to the server and get TSRequest back
    
    ... # not really relevant to this question as I get a valid response back with a version of 6
    
    ### Step 3 - Unpack Server TSRequest and verify pubKeyAuth field
    ActualServerHash = SecContext.Unwrap(TSRequest.pubKeyAuth)
    
    ExpectedServerHash = SHA256(ServerClientHashMagic + Nonce + SubjectPublicKey)
    
    # the values never match with the logic above
    assert ActualServerHash == ExpectedServerHash

    The logic seems to match what's in the docs as the expected and actual length are both at 32-bytes (SHA256 hash size) and the server accepts the initial client request with it's computed value I just cannot verify the server's response. Hopefully I am doing something wrong and it is a simple mistake but if you need any more info from me, please let me know.

    Thanks

    Jordan


    • Edited by jborean93 Monday, March 19, 2018 4:01 AM update variable name
    Monday, March 19, 2018 3:56 AM

Answers

  • And I feel quite stupid, I was generating 2 nonce's, 1 in the function and 1 outside the function where the later was used in the server computation. I have since gotten rid of that and am able to verify the server's response now. Thanks for helping though.

    • Marked as answer by jborean93 Monday, March 19, 2018 11:32 PM
    Monday, March 19, 2018 11:32 PM

All replies

  • Hello Jordan,

    Thank you for posting your question regarding MS-CSSP and the ServerClientHash computation. We have created a service request to track your question and a member of the Open Specifications team will be reviewing your question and posting here with regards to your issue.

    Sincerely,
    Will Gregg | open specifications

    Monday, March 19, 2018 2:29 PM
    Moderator
  • Hello Jordan, I will be assisting you with your issue. Can you use the following values and check if you get the same Result as specified here?

    ServerClientHashMagic
      43 72 65 64 53 53 50 20 53 65 72 76 65 72 2d 54  CredSSP Server-T
      6f 2d 43 6c 69 65 6e 74 20 42 69 6e 64 69 6e 67  o-Client Binding
      20 48 61 73 68 00                                 Hash.

      Nonce (length )0x20)
      02 ce ee 0c df 03 49 30-c7 55 d7 dd 4a 8a da af  eb 7e 78 9d 86 9c b2 b8-d7 9f 71 0c e2 83 72 4d 

      publickey (length 0x10e)
      30 82 01 0a 02 82 01 01-00 9d b9 d2 d9 76 57 8b 
      22 3a 25 c5 4d d0 ef a9-29 1e 7b 4e ec 5e 13 00 
      06 4e ba ad f3 0b 84 d9-37 af 2f 2c 65 9e 9b af 
      47 f9 63 63 63 9f 7f 9c-dd 3e 85 96 b3 46 33 42 
      0a 0c 6d ee 67 78 a9 f0-73 dc 02 82 30 61 49 29 
      f7 55 b3 43 68 40 fc a1-72 d9 ca f3 1a a4 99 9d 
      52 c3 98 1a 8a 27 f8 8b-b8 e3 dc 1a 82 2b 92 1e 
      bc 50 8c a3 6a 1c 25 2f-39 b5 90 c5 56 19 01 03 
      19 fb 01 c9 16 7a 66 7c-78 64 7b d4 e6 40 65 db 
      09 21 8e 8b a5 99 ac b3-92 f2 46 f3 a2 88 0b 48 
      83 3f bf 74 af 03 d4 f7-50 52 3f ea de f1 33 04 
      c2 b4 3b 8e 54 a2 57 26-5a 66 28 64 fb fd 09 21 
      be bd 93 97 c2 70 80 69-99 36 37 71 0f 92 32 18 
      e7 73 8a 73 c6 df b1 b7-fb f2 af a3 84 af 69 12 
      e0 f0 87 c7 b4 32 3f 56-fc ba 10 88 62 fb a1 69 
      30 22 89 04 dd 51 a9 8e-3e 7a 32 79 17 1c 4f 47 
      2b f1 f9 f4 1e 35 09 fa-93 02 03 01 00 01       

     Result (length 0x20)
     de 4f c6 a6 ba b2 0e c5-29 6e 8d e5 e7 84 c7 11 
     ef b8 e4 d0 c3 39 4f 4b-b9 64 bd ff f1 c0 b8 c2

    Regards,
    Sreekanth Nadendla
    Microsoft Windows Open Specifications

    Monday, March 19, 2018 6:44 PM
    Moderator
  • That particular example works for me when I plug those values directly in. Here is an example of a normal process for me.

    Nonce

    71 0B AA 31 65 6C 08 15
    6A F9 AD 45 9E 82 12 DA
    94 61 B6 25 B5 87 3E 48
    8E 4A F8 6E 12 4C FC ED

    ServerPublicKey

    30 81 89 02 81 81 00 A8
    3C 7A 91 C8 C3 7B CE F4
    B8 38 B5 EA BF FC 37 FF
    8D 8B EE AA 70 6D C7 87
    AC DF 4A 78 4A 2C F7 33
    C1 61 97 EE 56 23 63 4B
    52 6C A0 88 06 9C 2F F5
    65 F9 A9 E6 02 AC BC B1
    8A 1B 8A C9 B6 B4 FB 0A
    E2 45 39 6E 01 64 58 CA
    9C D6 B4 4D F5 E5 75 BF
    F3 32 F2 9E 6A F6 3E A9
    C9 E5 75 FC CB 54 BF 34
    45 D9 51 0F 2B 22 36 B9
    73 6D 10 6A 20 C3 E8 92
    08 6E CB 98 03 73 C7 BD
    E5 1D CC C2 6A EA B3 02
    03 01 00 01

    Client pubKeyAuth (pre-wrapped)

    40 2B 57 64 01 19 34 54
    EA 55 06 A3 42 F3 55 E2
    49 B4 48 D4 AF 61 23 59
    AA 56 58 33 A8 5A D5 63

    Server pubKeyAuth response (post-unwrapped)

    F9 1C F6 63 73 EE 21 16
    EF E1 1D 96 83 28 B6 4C
    47 91 46 4C 36 07 15 8C
    D8 CA 3D 72 79 E3 23 2C

    Client computed Server pubKeyAuth response (doesn't match the response)

    E3 29 F6 FA 05 2E 9A 89
    2E 4A 71 3B 52 E3 60 C5
    87 D7 D6 6F 74 FD 86 82
    A3 D9 E3 7A 7B 8A FD EE

    In this process, the server accepts the client's pubKeyAuth value and returns it's own pubKeyAuth value with the ServerClientHashMagic and I assume wraps it. The client receives this response, unwraps the pubKeyAuth value and compares it to the client side computed value which ultimately fails. From your example I am able to verify the ServerClientHashMagic value I have in the code is the correct one. I am assuming the following

    • The nonce value is the same value that is used to compute the client and server pubKeyAuth value
    • The publickey value is the same value used in both client and server
    • I only need to unwrap the pubKeyAuth field returned by the server and compare that with the locally computed value
    • I have tried it with both NTLM and Kerberos auth to see if the wrapping/unwrapping part is causing the issue but both have the same result

    I'm starting to think I may have a MitM here but the VM just sits on a local virtualbox instance so I would be very surprised if that was the case. I am going to recreate the server from fresh and try it from there and see if that works.

    The file C:\Windows\System32\credssp.dll has the following file version in case it helps

    10.0.14393.2125 (rs1_release.180301-2139)

    The server is definitely responding with version 6 in the TSRequest so I would expect it to be using the newer logic plus the fact it accepts the client's original pubKeyAuth value seems to indicate I am doing at least something right.

    Thanks

    Jordan

    Monday, March 19, 2018 9:10 PM
  • Some further info, I have just tested it on a brand new Server 2016 host with just the newer patch applied and it still fails on the client side verification. The same occurs to a Server 2012 R2 host as well.

    Thanks

    Jordan

    Monday, March 19, 2018 11:14 PM
  • And I feel quite stupid, I was generating 2 nonce's, 1 in the function and 1 outside the function where the later was used in the server computation. I have since gotten rid of that and am able to verify the server's response now. Thanks for helping though.

    • Marked as answer by jborean93 Monday, March 19, 2018 11:32 PM
    Monday, March 19, 2018 11:32 PM