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

support Extended Protection for Authentication (Channel Binding Tokens) #27

Closed
mwrock opened this issue Feb 9, 2016 · 2 comments · Fixed by #28
Closed

support Extended Protection for Authentication (Channel Binding Tokens) #27

mwrock opened this issue Feb 9, 2016 · 2 comments · Fixed by #28

Comments

@mwrock
Copy link
Member

mwrock commented Feb 9, 2016

Currently Organizatrions that have a Channel Binding Token Hardening Level domain policy set to "Strict" ("relaxed" is the default) are unable to authenticate to the WinRM service when using NTLM over SSL (note this has always been the case and is not a recent regression). This is because the strict policy requires a "channel binding token" which binds the outer transport channel (TLS in this case) to the inner channel (NTLM) and povides extra protection against "man in the middle" attacks.

For more info on this topic see:
https://msdn.microsoft.com/en-us/library/dd639324.aspx
https://datatracker.ietf.org/doc/rfc5056/?include_text=1

Logistically this involves embedding a hash of the X509 cert (usually SHA-256) in the target_info of the type3 message sent to authenticate the client to the server. This post does a good job clearly explaining how to create the token.

I have managed to get a valid token generated using the above technique and hacked the session class here to validate that it works. Here is the hack:

      def blob
        @blob ||=
          begin
            b = Blob.new
            b.timestamp = timestamp
            b.challenge = client_challenge
            b.target_info = inject_cbt
            b.serialize
          end
      end

      def inject_cbt
        cbt = "\x0A\x00\x10\x00\x04\x0E\x56\x28\xEC\x4A\x98\x29\x91\x70\x73\x62\x03\x7B\xB2\x3C".force_encoding(Encoding::ASCII_8BIT) #hard coded valid `MsvAvChannelBindings` using a self signed cert on a test VM

        target_info = challenge_message.target_info
        target_info.insert(target_info.length-4, cbt)

        target_info
      end

This resulted in succesfully authenticating over SSL to a VM with a Channel Binding Token Hardening Level set to strict.

I am starting a PR to this gem with a less "hacky" implementation and want to introduce a high level design for discussion:

  • Add a optional channel_binding_token to Net::NTLM::Client::Session.init_context which would be a ChannelBinding instance (see next item).
  • Add a Net::Ntlm::ChannelBinding class with a static create method that takes a options hash. There are different kinds of "outer channels" and even different kinds tls based tokens so one can imagine perhaps different subclasses at some point. This initial implementation would just take a X509 cert and be capable of generating a gss_channel_bindings_struct and a MsvAvChannelBindings MD5 byte stream.
  • Add a TargetInfo class that can be initialized from target info received in the type2 message and have the ability to add additional AV_PAIR structures. The to_s method of this class will dump a string representation that can be fed to a Blob's target_info accessor.

With this implementation, we can add a trivial change to the WinRM gem that would use its the SSL cert to create a ChannelBinding and feed that to the Ntlm::Session and then successfully authenticate to servers with a strict policy.

cc @sneal

@sneal
Copy link
Member

sneal commented Feb 9, 2016

Nice, so you can use NTLM over SSL. @mwrock Any idea how common this is?

@mwrock
Copy link
Member Author

mwrock commented Feb 9, 2016

Yeah. So today when you use WinRM with SSL, it uses the httpclient gem's authenticators to handle authentication. If you happen to have rubyntlm loaded, it will use that. see https://github.com/nahi/httpclient/blob/master/lib/httpclient/auth.rb

I don't have good metrics, only anecdotal experience. I don't think this is a widespread issue but I have run into this a couple times and recently with a well known enterprise customer. Its one of those things that is incredibly unobvious and can consume alot of time troubleshooting why someone cannot connect to winrm even though they seem to have everything wired up correctly and can connect successfully with MS based tools like powershell remoting. Its also interesting to look at this issue where people are complaining about Chrome's lack of implementation (they are implementing it now though) and how that is blocking several enterprise shops.

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 a pull request may close this issue.

2 participants