Implement MITM detection described by Durumeric, et. al. #1420

mholt opened this Issue Feb 10, 2017 · 5 comments


None yet

2 participants

mholt commented Feb 10, 2017 edited

A recent paper, The Security Impact of HTTPS Interception published by Zakir Durumeric, Richard Barnes, Nick Sullivan, J. Alex Halderman, and others demonstrates the use of heuristics for detecting active MITM attacks/proxies on TLS connections:

First, we show that web servers can detect interception by identifying a mismatch between the HTTP User-Agent header and TLS client behavior. We characterize the TLS handshakes of major browsers and popular interception products, which we use to build a set of heuristics to detect interception and identify the responsible product.

The tl;dr of the heuristics described in the paper is to capture the information in the ClientHello of TLS handshakes and then capture the User-Agent value from the subsequent HTTP request headers. Since the TLS configuration of the major user agents is known and is mostly predictable (see paper for caveats), the paper suggests that by comparing the User-Agent header field to the actual client inferred from the characteristics of the TLS ClientHello is a way to detect active MITM attacks/proxies.

Despite benevolent intentions of some TLS proxies, they actually do more harm than good, and end users are not always able to know when their "trusted" proxy is helping or hurting them.

Because of the adverse effects on user privacy and the technical problems of TLS proxies of all kinds, I propose we give site owners the ability to handle clients who are being MITM'ed in the way that seems best to them.

I propose these actions should be possible:

  • Close the connection entirely. This would involve a new directive or a special property in the TLS directive that would allow the site owner to specify base paths (maybe?) which are considered sensitive enough to not even send a response in the case of a MITM.
  • Perform rewrites, redirects, or log when a connection is thought to be MITM'ed. This would involve a new request placeholder, perhaps {mitm} that contains a yes/no, 1/0, or true/false. This could also be used to set headers on the request for upstream services to be aware of the attack.
  • Warn the client in HTML or other kinds of responses of the attack. This would require a new template action such as {{.IsMITM}} (returns true/false or nonempty/empty) so that the site owner could inject custom HTML or scripts to help warn the client. (Yes, MITM proxies can of course try to detect these and strip them out, however, that is unlikely with the volume of Caddy sites at this point and would be difficult to generalize across all sites anyway.)

Possible challenges:

  • Maintaining a list of major browser TLS configurations. Maybe this won't change often, but it will change.
  • Mapping connection addresses to ClientHellos (map[string]*tls.ClientHelloInfo) may be inefficient, since the map will have to be protected with a RWMutex. We'll have to do some benchmarking to see if the impact is negligible under load, or if this feature will have to be turned on by the site owner before it can be used. Also, this requires Go 1.8.
  • We need to use GetConfigForClient since GetCertificate is not always called (for example, I've seen requests with curl --insecure that don't invoke GetCertificate). We don't need this callback at all.
  • Reading TLS Heartbeat support and other certain raw pieces from the ClientHello will be tricky because the ClientHelloInfo does not check for this (understandably so).

Feedback welcome. I will be starting on this as soon as I get a chance amid the other drastic changes that Caddy is undergoing right now (build server infrastructure, new website, etc).

Update: I have a PoC started. I can map requests to their ClientHelloInfos. wrk indicates no significant overhead in doing this. I will invite others to verify when I have something to show. Now all that's left is the ability to detect the browser from the ClientHelloInfo and expose the results of the detection to templates and configuration.

kyhwana commented Feb 11, 2017

Being able to just log when a MITM is happening along with the browser user agent/info + remote IP would be good, as this would have less severe consequences on a false positive.

mholt commented Feb 11, 2017 edited

@kyhwana Yes, if you look at the original proposed possible actions, logging is one of them. There's definitely no one-size-fits-all on how to handle this.

mholt commented Feb 12, 2017

I have to more or less parse the raw ClientHello message manually since the standard lib even in Go 1.8 still doesn't expose all the needed information (which is fine... most people won't need the raw Client Hello like this requires).

Nevertheless, I can now extract the raw list of cipher suites, point formats, extensions, and compression methods that the client sends, which makes it possible to implement the heuristics.

Next challenge: figure out exactly what those heuristics are. The paper is pretty clear about Safari and Edge, and Firefox sounds simple enough (I think), but the paragraph about Chrome is a little more fuzzy. Does anyone know which ciphers Chrome does not support?

mholt commented Feb 12, 2017 edited

Okay, well, I did some trials and think I have a decent first draft of this working. I will be contacting the authors to try to verify the correctness of my approach. Then I'll clean up the code, write some tests, and put this into a branch for everyone to try (maybe not in that order, haha).

@mholt mholt referenced this issue Feb 13, 2017

Detect HTTPS interception #1430

5 of 5 tasks complete
@mholt mholt added deferred and removed in progress labels Feb 17, 2017
mholt commented Feb 17, 2017

This will be merged soon. I'll probably want to revisit this when the authors release their fingerprint information but I won't let that stop us for now.

@mholt mholt closed this in #1430 Feb 17, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment