Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NTLMRelayX SMB->LDAP ensure that negotiate request disables signing #500

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

Meatballs1
Copy link

@Meatballs1 Meatballs1 commented Oct 11, 2018

Having this commented out prevents LDAP NTLM relay from working..?

@asolino
Copy link
Collaborator

asolino commented Oct 11, 2018

That is actually a good question @Meatballs1

Any take on this @dirkjanm?

@dirkjanm
Copy link
Contributor

Yes that was one of my experiments to solve the SMB->LDAP relay problem which doesn't work because the signing flag is set.
The reason it is commented out is because it is pointless to modify the flags, flag modification will cause the authentication to fail since the signature will be invalid. So SMB->LDAP is still an unsolved problem.

@Meatballs1
Copy link
Author

Meatballs1 commented Oct 11, 2018

Well I uncommented it out and it worked for me..!

Without this I would get a connection in, relay it to the domain controller, I would get a bind success response, then doing a searchRequest the server would just ignore my request.

I couldn't understand why, then I looked in the bind request and saw that we were setting a session key, so the server expects future requests to be signed.

I only really noticed after doing a normal query with the LDAP3 NTLM auth to compare this doesn't bother with signing as far as I can tell - or not unless its required.

@dirkjanm
Copy link
Contributor

Can't reproduce this, as soon as I uncomment it the auth starts failing.
Are you sure that when it worked you were not relaying from HTTP->LDAP? This doesn't have the signing bit set and thus the code doesn't change anything here.

@asolino
Copy link
Collaborator

asolino commented Oct 11, 2018

Might the target OS be the factor changing behaviour here?

@Meatballs1
Copy link
Author

Meatballs1 commented Oct 11, 2018 via email

@Meatballs1
Copy link
Author

Meatballs1 commented Oct 11, 2018 via email

@dirkjanm
Copy link
Contributor

Maybe the appliance SMB/NTLM stack does not use all the security options of NTLM that Windows does and thus the removal of the flag goes unnoticed.

@asolino
Copy link
Collaborator

asolino commented Oct 11, 2018

Is uncommenting this line affecting any working scenario @dirkjanm?

@Meatballs1
Copy link
Author

Meatballs1 commented Oct 12, 2018

Couple of tested use cases (all using -smb2support)

NetLM/NTLM

  1. Windows 10 client set to use LM or NTLM auth
  2. The bind request ntlmssp_negotiate left at 1
  3. The bind request ntlmssp_auth succeeds
  4. Server doesn't respond to further requests (as they are not signed)

NetLM/NTLM

  1. Windows 10 client set to use LM or NTLM auth
  2. Changing the bind request ntlmssp_negotiate sign to 0
  3. The bind request ntlmssp_auth still has signing set to 1 (forwarded without changes from the client)
  4. Server (W2k8R2) doesnt care that there is a discrepancy between the negotiate and the auth flags
  5. Requests to the server unsigned succeed.

Windows client doesn't care that the negotiate came back with sign disabled - still sends signing to the server.
Windows server seems to base whether signing is required based on the negotiate rather than the auth.
These messages have a MIC but the NTLM attribute 'flags' is not present so it isn't checked.

NetNTLMv2

  1. Windows 10 client set to use NTLMv2 auth
  2. The bind request ntlmssp_negotiate left at 1
  3. The bind request ntlmssp_auth succeeds
  4. Server doesn't respond to further requests (as they are not signed)

NetNTLMv2

  1. Windows 10 client set to use NTLMv2 auth
  2. Changing the bind request ntlmssp_negotiate sign to 0
  3. The bind request ntlmssp_auth still has signing set to 1 (forwarded without changes from the client)
  4. Server responds with Auth Failed Security Context Error

This would appear to be due to the MIC (sent in the auth message) failing. The MIC is a hash based on all of the messages. Don't think we can modify this to get this use case to suceed?

Appliance

  1. Appliance sends NTLMv2 auth
  2. The bind request ntlmssp_negotiate left at 1
  3. The bind request ntlmssp_auth succeeds
  4. Server doesn't respond to further requests (as they are not signed).

Appliance

  1. Appliance sends NTLMv2 auth
  2. Appliance has sign set to 1 in negotiate
  3. Change the bind request ntlmssp_negotiate sign to 0
  4. The appliance sends auth with signing set to 0.
  5. Requests to the server unsigned succeed.

The appliance doesn't set a MIC nor the flags specifying whether a MIC should be present or not. The library probably doesn't support MICs. Therefore we can modify the negotiate flags to disable signing.

Appliance sees that negotiate says sign disabled, and sends auth request with signing disabled. (Windows doesn't do this)

In conclusion we think that SMB->LDAP works when:

Server doesn't require LDAP signing (this is rare as default domain controller policy is to enforce signing); and

  1. NetLM/NTLMv1 is used on Windows clients; or
  2. A third party library which doesn't support Message Integrity Checks (MIC)s is used; or
  3. Old windows server (<2003) that doesn't support MIC (not tested)

@Meatballs1 Meatballs1 changed the title Dunno why this commented out NTLMRelayX SMB->LDAP ensure that negotiate request disables signing Oct 12, 2018
@dirkjanm
Copy link
Contributor

Nice research on the different scenarios! This does agree with my reading of the documentation, except for the MIC not being checked if NTLM (v1) is used, which is interesting.

The only downside I see to uncommenting this line is that it will generate failed authentications. We'd need to check if this locks out accounts, otherwise the only reason for not including it would be stealth.

@asolino
Copy link
Collaborator

asolino commented Oct 13, 2018

Thanks for the research and comments.

I can live w/o being super stealthy but locking out account could be an issue. Can you please verify that?

@Meatballs1
Copy link
Author

Meatballs1 commented Oct 14, 2018 via email

@eladshamir
Copy link
Contributor

I spent a bit of time investigating this issue as well.

NTLMv1 is irrelevant. If you get an NTLMv1 response, don't relay; just crack it (crack.sh).

As for NTLMv2, if you change any flag (or anything in any of the messages), the MIC won't be valid anymore. If you remove the MIC, you also need to remove the flag that indicates that the MIC is there, which will affect the NtProofStr and make the NTLM response invalid (it's sort of part of the salt).

As for recalculating the MIC, you'd need the NTLM hash to obtain the key, so that's either pointless or infeasible.

As far as I can see at this point, you can only relay from a client that doesn't support MIC (Win XP/2003 and prior), or a client that don't set the Sign or Seal flags. HTTP is one of them.

@n0skill
Copy link

n0skill commented Nov 7, 2018

Thank you all for your work ! It's helping me understand the mechanisms of ntlm which I didn't know before 😎

@omriman067
Copy link

I spent a bit of time investigating this issue as well.

NTLMv1 is irrelevant. If you get an NTLMv1 response, don't relay; just crack it (crack.sh).

As for NTLMv2, if you change any flag (or anything in any of the messages), the MIC won't be valid anymore. If you remove the MIC, you also need to remove the flag that indicates that the MIC is there, which will affect the NtProofStr and make the NTLM response invalid (it's sort of part of the salt).

As for recalculating the MIC, you'd need the NTLM hash to obtain the key, so that's either pointless or infeasible.

As far as I can see at this point, you can only relay from a client that doesn't support MIC (Win XP/2003 and prior), or a client that don't set the Sign or Seal flags. HTTP is one of them.

Thank you all for the awesome thread! I really learned a lot from reading here, especially considering my own results from experimenting with relayed credentials.
The one thing i still don't understand is this:
When relaying SMB->SMB I can see in that in both auth packets (the one from the client and the one sent to the victim) the MIC fields have the same value (and the relay is successful).
how could that be? does it mean that all 3 packets were passed untouched?
Thank you very much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants