31

When browsing to a website over HTTPS, the web browser typically does a lot of work in the background - negotiating a secure channel, validating the site's certificate, verifying the trust chain, etc.

If your browser is configured to use a web proxy, the current HTTP protocol supports a CONNECT method - this enables your browser to setup the TLS tunnel to the website, without revealing any of the request contents to the proxy (other than the name of the site, of course).

What does the browser do regarding the identity of the proxy server?
If the proxy does not have a certificate, then potentially it could be impersonated by a MitM.
Even if the proxy does have a certificate, if it's not checked, it might still be possible to impersonate it.

Does the protocol (or any companion RFC) define how this should be handled? How do common web browsers typically handle this?
If the proxy does not have a certificate, is there any feedback to the user? If the proxy does have a certificate, but it is invalid, is there feedback then?


Additionally, is there a provision for securely authenticating the web proxy, even when the request is plain HTTP?
For example, connecting to the proxy over HTTPS even though the request to the website is over HTTP...


NOTE that I am not asking how to identify the website, whether tunnelled through the proxy or having it intercept the SSL chain.
Rather, I want to verify the identity of the proxy itself, to make sure no unauthorized server is MitMing me...

AviD
  • 72,138
  • 22
  • 136
  • 218

3 Answers3

28

As is customary, let's first answer the exact question which was asked.

Right now, using HTTPS to connect to the proxy is not widely supported. The squid documentation has some information on the subject; to sum things up:

  • Chrome supports it, but it must be configured through a proxy auto-configuration script because there is no GUI support. This also means not using the "system-wide proxy configuration".

  • Firefox does not support it, although the feature has been marked as requested since 2007. (UPDATE: Supported in FF 33+)

  • No indication on other browsers, which can be surmised to mean "no support whatsoever".

What Chrome does when encountering a "somewhat invalid" certificate for the proxy should be tested, but it is likely to depend on the exact browser version (which changes all the time, often transparently), the operating system (since certificate handling tends to be delegated to the OS), and in what ways the certificate is not valid (expired, bad server name, unknown trust anchor,...). Also, there is an inherent chicken-and-egg issue here: full certificate validation, as is mandated by X.509, includes checking revocation, i.e. download of CRL for all certificates in the path. URL for CRL download are usually located in the certificates themselves. But if you are using a proxy for your HTTP traffic, then the CRL download will need to go through that proxy... and you have not yet validated the proxy certificate. No chicken, no egg.

We may also note that the proxy auto-configuration file format does not really support HTTPS proxying. There is no formal standard for this file, but custom is to follow an old Netscape draft which says that a PAC file defines a Javascript function which can return proxy hostnames and ports, but not protocol. So, no HTTPS. For its HTTPS-proxy support, Chrome implicitly uses an extension to this de facto convention by stuffing an HTTPS URL where it has no right to be, and hoping for the browser to make some sense out of it.


As is customary, let's see what alternate proposals can be made.

To ensure protected communication between the client and the proxy, the two following solutions may be applicable:

  • Use a VPN. This is highly generic, and since it operates at OS level, it will apply to all browsers. Of course, it requires that whoever installs the thing on the client machine has administrative rights on that machine (you cannot do this as a simple unprivileged user).

  • Use a SSH-based SOCKS proxy. On your client system, run: ssh -N -D 5000 theproxy ; then set your browser to use localhost:5000 as SOCKS proxy. This solution requires that you have the proxy server (theproxy) is also a SSH server, and that you have an account on it, and that the SSH port is not blocked by some ill-tempered firewall.

The SOCKS proxy solution will ensure that the traffic goes through the proxy machine, but does not include caching, which is one of the reasons we usually want to use a proxy in the first place. It can be altered by using some additional tools, though. SOCKS proxying is about redirecting all TCP/IP traffic (generically) through a custom tunnel. Generic support for applications is possible, by "replacing" the normal OS-level network calls with versions which use SOCKS. In practice, this uses a specific DLL which is pushed over the standard OS libraries; this is supported in Unix-based systems with LD_PRELOAD, and I suppose this can be done with Windows too. So the complete solution would be:

  • You use a SSH-based SOCKS tunnel from your client to the proxy machine.
  • The SOCKS client DLL is applied on the browser, and configured to use localhost:5000 as SOCKS proxy.
  • The browser just wants to use theproxy:3128 as plain HTTP proxy.

Then, when the browser wants to browse, it opens a connection to theproxy:3128, which the DLL intercepts and redirects to a SOCKS tunnel that it opens to localhost:5000. At that point, SSH grabs the data and sends it to theproxy under the protection of the SSH tunnel. The data exits on theproxy, at which point the connection to port 3128 is purely local (thus immune from network-based attackers).

Another way to add caching on the SSH-SOCKS setup is to apply a transparent proxy. Squid can do that (under the name "interception caching").

Yet another way to do caching with SSH protection is to use SSH to build a generic tunnel from your machine to the proxy. Run this:

ssh -N -L 5000:localhost:3128 theproxy

and then set your browser to use localhost:5000 as an HTTP proxy (not SOCKS). This will not apply proxying on alternate protocols such as FTP or Gopher, but who uses them anyway ?


As is customary, let's now question the question.

You say that you want to protect against a man-in-the-middle attack. But, really, the proxy is a MitM. What you really want is that the proxy is the only entity doing a MitM. HTTPS between the browser and the proxy (or SSH-SOCKS or a VPN) can protect only the link between the client and the proxy, and not at all between the proxy and the target Web server. It would be presumptuous to claim that MitM attacks are reliably thwarted without taking into account what happens on the Wide Internet, which is known to be a harsh place.

For end-to-end protection against MitM, use SSL, i.e. browse HTTPS Web servers. But if you do that, then extra protection for the browser-to-proxy link is superfluous.

Protecting traffic between browser and proxy makes sense if you consider proxy authentication. Some proxies require explicit authentication before granting access to their services; this is (was ?) common in big organizations, which wanted to reserve "unlimited Internet access" to some happy few (usually, the Boss and his favourite underlings). If you send a password to the proxy, then you do not want the password to be spied upon, hence SSL. However, an attacker who can eavesdrop on the local network necessarily controls one local machine with administrator privileges (possibly, a laptop he brought himself). His nuisance powers are already quite beyond simple leeching on the Internet bandwidth. Also, limiting Internet access on a per user basis maps rather poorly to modern operating systems, which tend to rely on Internet access for many tasks, including software updates. Internet access is more efficiently controlled on a per usage basis.

Therefore, I think that protecting access to a HTTP proxy has some merits, but only in rather uncommon scenarios. In particular, it has very little to do with defeating most MitM attacks.

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
  • Thank you Thomas! A few follow-on point: The first part is not overly surprising, but very disappointing - and, I believe, possibly a bigger issue than you let on. The second part, with SSH and SOCKS and etc, is very interesting, but not always applicable, or even very straightforward (as much as it should be). Moreover, I'm looking at this from the proxy PoV, not the user PoV... I didn't think it was pertinent to the question. – AviD Nov 04 '12 at 18:43
  • As for your third - and most important part - as you say, it is usually not relevant, though my question was about preventing *unauthorized* MitM (i.e. besides the proxy). There are a few edge cases where this is important, such as proxy authentication as you mention. Proxy authentication *is* still relevant in many situations, both in corporate proxy scenarios (e.g. not about bandwidth, but about acceptable use policy - e.g. no Facebook from work computers), and in reverse proxy scenario (also usually for corporate internal use...). – AviD Nov 04 '12 at 18:47
  • The attacker also does not need to be a network admin, take into account various roaming scenarios. Sure, a VPN could solve that, but it's not always the case. A conceptual SSL-VPN via the proxy might be interesting here, but not really feasible. Further, as I noted in the question, there are also valid scenarios where the even though browsing itself can be over HTTP, I still want to know that I'm talking to *my* proxy. – AviD Nov 04 '12 at 18:50
  • Bottom line, I agree with your conclusion - protecting access to a HTTP proxy has some merits, but only in rather uncommon scenarios. However, I think these uncommon scenarios are still extant enough that they should be handled by default within the existing protocols; moreover, the fact that they aren't, and *very few professionals are aware of this*, is potentially a Very Big Deal. – AviD Nov 04 '12 at 18:52
  • 1
    Very comprehensive answer on an insightful question. Thanks! I would tend to agree that the risk is small (it's a lot of work to get your rogue proxy in there), but the harm is significant if someone can pull it off. – scuzzy-delta Nov 04 '12 at 21:19
  • Or you can use a local stunnel instance as a localhost HTTP proxy (connected to a HTTP/TLS proxy server). You can use the same thing for ROCKS proxy. – ysdx Mar 05 '15 at 13:26
  • This answer is good, but at least somewhat out of date. There is now a way to explicitly specify HTTPS proxy in a PAC file by using "HTTPS" instead of "PROXY" directive. https://developer.mozilla.org/en-US/docs/Web/HTTP/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_PAC_file – ykaganovich Dec 19 '21 at 02:50
3

Chrome on client side, and Squid on proxy side can work via https. See Secure Web Proxy for more details.

I hope that Chrome will warn you on invalid proxy certificate, but have no experience with this setup so can't confirm.

lubas
  • 367
  • 1
  • 2
0

As an alternative to using @Thomas Pornin's answer (where he suggested to use SSH) you can use the service bus to maintain a transparent connection from a local port to a remote server.

The "authentication" occurs when the proxy client software connects to the service bus... the endpoint of this service bus can be anything, such as an intranet, corporate proxy, etc. Once the client software authenticates you, a mini-vpn is created (just like SSH).

How to get started

This .Net client is installed locally, and the target is a proxy or some other device you need to trust.

Install Port Bridge

Note: Mentally replace SQL Client and 1433 with a port of your choosing... it's all the same with this TCP based proxy

This project allows several NAT'ed servers to access several NAT'ed clients across the internet over a single service bus connection.

alt text

It's a pretty smart implementation that will really get you thinking. Below is the source

Link

... and another explanation of the same.

http://brentdacodemonkey.wordpress.com/2010/05/05/azure-appfabric-%e2%80%93-a-bridge-going-anywhere/

Also, there is a related project called "SocketShifter" on codeplex: http://socketshifter.codeplex.com/ Although the codeplex site advises using portbridge, I do see check ins as of (Aug 2010) and not sure which one is more up-to-date. It may be worth investigating.

Glorfindel
  • 2,235
  • 6
  • 18
  • 30
makerofthings7
  • 50,090
  • 54
  • 250
  • 536
  • 1
    I'm not sure I understand, or maybe you missed the point of the question. Using standard HTTP, how would this help verify the identity of the proxy? – AviD Nov 29 '12 at 08:53
  • @AviD Just as the SSH solution takes on the responsibility of identifying the proxy, this would do the same. Just point the client to a local port, and the data is secured and managed by the service bus until it reaches the destination (your proxy). – makerofthings7 Nov 29 '12 at 13:36