15

I'd like to determine if an SSL webpage is being debugged through Fiddler, or if it's going through an SSL Proxy.

So some people may ask

What is the point of re-validating SSL using javascript?

My goal is to know when a connection is subject to 3rd party interception as mentioned in this answer. The vulnerability is that passwords may be exposed, and user sessions are exposed as well. All of this is possible when malicious software, or corporate IT policy dictates SSL interception and monitoring.

What can be done if a SSL connection is being intercepted?

Depending on the sensitivity of the application, and if two-factor authentication is being used, I may programatically block the connection or limit access to certain parts of the website. I may also place a banner notification indicating the security risk of using that kiosk. ...Or I may allow the user to add an "exception", granted they understand the risks.

My Question:

Can Javascript check the current SSL certificate details, including CA chain?

I think the right way to approach this is to look at the certificate's issuer, and look at the rest of the certificate chain. The next step would be to list through each cert in the chain and see if any of those CA's are equal to what's root CA's are publicly trusted. I want to specifically exclude what additional certificates that user may have added themselves to their local computer.

I'm hoping people on security.stackexchange.com will offer ideas on how to approach this.

If Javascript can't validate the current SSL connection, what are the alternatives?

Since this may, or may not be possible in a pure JavaScript solution, I tagged this question with Flash since it should be able to accomplish this, and send a response back to Javascript.

If anyone has Java ME experience, please mention if this is possible. Same goes for any other widely deployed plug in.

Source code for the relevant technology is appreciated.

makerofthings7
  • 50,090
  • 54
  • 250
  • 536
  • 2
    The proxy can manipulate any javascript, flash, java, silverlight files you sent to the client, so it can remove the check. – Hendrik Brummermann Dec 11 '10 at 22:57
  • 1
    True; also I don't think most proxies currently do that. A more paranoid approach may be to obfuscuate, encode, hide the check; then encrypt the result using a session key to the server. Once a valid encrypted result is sent to the server, the next page is issued. – makerofthings7 Dec 12 '10 at 17:12
  • @HendrikBrummermann, Practically no, because proxies that do that don't selectively hijack targets. So if your particular site uses such defense mechanism, you would be ahead of the other 99%. – Pacerier Dec 28 '16 at 07:57

6 Answers6

6

You asked about alternatives. Quite frankly, this is a tough one: if someone is playing man-in-the-middle on your SSL session, and the user hasn't noticed or has allowed it to proceed, you're in a really tough spot. However, I'll try to brainstorm some alternatives that you could consider, if Javascript isn't able to check the cert the server provided on this HTTPS connection. Both of these ideas are far from perfect, at best, but I'll pass them along in case they help.

Idea 1. Don't trust the browser. One possible alternative is to use two-factor authentication and confirmation, so that you are not 100% reliant upon the browser session. For instance, for online banking applications, if the user performs a sensitive operation, the server could send the user's cellphone a SMS message listing the transaction information ("pay $100 to AT&T? to approve, enter this PIN: 2781"), and then require the user to respond with their approval or enter the PIN into their browser session. However, I realize this is annoying and inconvenient for users.

Idea 2. Raw sockets. Another possibility you could explore: use Flash or Java to open a raw socket to some TCP port on the server. If this is not intercepted/man-in-the-middled by the proxy, you now have a number of options to detect the proxy. One simple detection strategy: if the server notices that the source IP address associated with the raw socket is different from the source IP address associated with this HTTPS connection. (However this might generate false alarms...) You might also be able to bypass the proxy without Flash or Java by using some other protocol handler that the browser recognizes but the proxy doesn't intercept, such as ftp:// or somesuch.

D.W.
  • 98,420
  • 30
  • 267
  • 572
  • 2
    As per #1, my bank has been doing this (authenticating with "something you have") for a decade now, and while slightly inconvenient, it's definitely a huge step up from just "something you know" - most people happen to have their phones on them, so the inconvenience is barely noticeable. *Pairing* the phone number with the account was inconvenient, though - I had to physically show up at the bank and prove that I was me. As for #2, all the attacker needs to do is to disallow any outgoing connections except through the proxy (which in itself is not uncommon in corporate environments). – Piskvor left the building May 22 '11 at 16:51
5

No - the DOM does not expose access to the SSL certificate for the current page, all you get access to is location.protocol which allows you to check if you are being delivered over HTTPS

blowdart
  • 859
  • 4
  • 5
4

In the Web browser context, there are two kinds of SSL connections: the ones that the browser manages, and the ones that your code (be it Java, Javascript...) manages itself.

For the first kind, you are mostly out of luck, because the browser will not give you details about the server certificate chain. The browser tells you "this is all dandy" but gives you no way to check that the browser is not being led astray.

For the second kind, well, this means that your code will open the connection to the server and run the complete SSL handshake itself. At that point, of course, the code will see the certificate chain from the server, and will be able to validate it in arbitrary ways, which includes "direct trust" (the client code already "knows" the server public key) or at least using a specific, expected root CA. This approach has several practical issues which can be dealt with at a cost:

  • You have to embed a complete SSL implementation. This is not necessarily huge, but it can be tricky. You can make it smaller since you control both client and server code, so you can concentrate on the exact protocol version and algorithms that you intend to use.
  • Performance can be an issue if using an interpreter without a JIT compiler.
  • All of this makes sense only if you can make sure that the client code has not been altered. It is useless to check anything with Javascript about the SSL connection through which the Javascript code itself has been downloaded: a Man-in-the-Middle can change the Javascript code to remove the check.
  • Opening a raw connection to the server from the client code is tricky in some networks, especially with regards to proxies.

For performance, you will want to use Java ME. Most Java ME implementation use basic interpreters so this will not be faster than Javascript or Flash, except that the Java ME standard library includes java.math.BigInteger, an implementation of arithmetics on arbitrarily large integers, which will be typically implemented as native code, thus very fast. You will need this for the RSA or DH computations involved by the SSL handshake.

For make sure that the right code is running on the client, there again Java ME can come to the rescue, because Java ME applets can be signed. This does not really solves your problem, because an attacker who can run Fiddler is an attacker who could insert his own fake CA in the local trust store; the same attacker could have added his own fake CA to the other local trust store, the one for validating applet-signing certificates. Yet this adds a nice twist: if the client connection is intercepted, then, after-the-fact forensics examinations may uncover the cached signed applet, and then it will be made evident that the applet is fake and you, as the server maintainer, is not the bad guy. You cannot have that kind of legal protection from authentication, but signatures can help. This, of course, depends a lot on the context.

The problem with proxies is serious. A lot of local networks, especially corporate, don't do NAT; instead, all external traffic must go through some proxies. The user's Web browser knows where the proxies are, but not your Javascript or Java code. Moreover, the proxies may require some authentication, which may be linked with the local session credentials; there again, the browser gets through transparently, not your code. To cope with that kind of problem, you might envision tunnelling your SSL traffic through HTTP requests, which will be handed over to the HTTP code provided by the framework. This is possible (I have done it about one decade ago) but not easy.


Yet, this all smells bad. MitM attacks of the kind you are talking about work only if the attacker could pierce through the X.509 trust model, e.g. by installing his own rogue CA as a trusted CA in the client's system. Since OS software updates also use this trust model, it must be assumed that the client system is, at that time, under complete control of the attacker, at least potentially. In a way, Fiddler is not something which is used by evil people, because the conditions which allow Fiddler to operate also allow the aforementioned evil people to enact evilness of a much larger and more thorough scale.

Which can be summarized as: checking things on SSL connections from Javascript or Java ME client-side code is as useless as a nice note on your living-room table, requesting potential burglars to kindly phone the Police themselves.

(Might work in Canada, though.)

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
  • Re "For the first kind, you are mostly out of luck", I believe this **can be done** with Chrome extensions/plugins. – Pacerier Dec 28 '16 at 08:00
3

Given your threat model (detect a proxy that proxies SSL but doesn't try to tamper with your checking code), you could embed Javascript code in all of your pages that checksums the content and compares it to a hardcoded checksum computed by the server, to determine whether the page that reached the client matches what the server sent. However, I suspect there are probably some non-trivial technical challenges here, and I'm not convinced it buys you much (keep in mind a malicious proxy can always remove your checking code).

You might be interested in learning about Switzerland and work at the University of Washington on "web tripwires".

D.W.
  • 98,420
  • 30
  • 267
  • 572
1

This is not currently support (as far as I can tell) by any of the browsers.

There is an outstanding bug on Firefox to introduce some kind of support for this but it has not been resolved.

You can support this in Javascript by using OpenSSL compiled with Emscripten although that link only provides the bones, you will need to build the JS linkage to your app.

You can support this in Flash by using OpenSSL compiled with Adobe Alchemy (search for it) but you would need to redo the work for the newer Flash engine and OpenSSL.

Jens Erat
  • 23,446
  • 12
  • 72
  • 96
Joe Steele
  • 111
  • 2
  • How would the certificate store work with regards to openssl compiled to emscripten running inside a browser? Would the openssl running inside the browser be able to access the browser's store of CA certificates? If not you'd then need to statically compile the certificates into the resulting js file. – CMCDragonkai Sep 03 '17 at 08:40
  • @CMCDragonkai You are correct. You would need to compile in the list of CA certs you trust. For this use case, it may not be an issue though, since you likely know the CA cert you **should** be seeing and can treat any others as failure. – Joe Steele Sep 22 '17 at 23:35
0

As far a Silverlight & .NET go, I would typically use the ServicePointManager to intercept calls to validate the SSL certificate, however it appears that that is not possible in the SL4.

There is a post at Microsoft Connect regarding this, however Microsoft says this is by design. I'll encourage anyone who thinks this feature should be available to Silverlight developers to post a response there.

makerofthings7
  • 50,090
  • 54
  • 250
  • 536