Matasano
December 2nd, 2007, 17:40
I was recently working on a Java-based application that communicated exclusively over SSL. This is a good thing for the application, buta bad thing for someone trying to test it. I naively thought that I could edit a couple of files and boom, be on my way. Alas, what followsis what I had to do to get in between and start understanding the application:
My initial take was that I would use two instances of stunnel (I use 3.x because I am old, crusty, and like the simplicity of the 3.x command line interface), with Blackbag’s replug in between so I can view the traffic.
So, here is my simple setup (monitoring a connection to www.amazon.com as an example):
http://www.matasano.com/log/wp-content/uploads/2007/04/stunnel-replug.png
All I do is test it with another instance of stunnel and we see that trafficis passing through our rat’s nest of proxying.
Of course, the first wrinkle is that I need to actually test from Windows.
So we load up Parallels and get the application pointing at ourtunnels. Easiest way to do this is to just edit the hosts file, locatedat \WINDOWS\System32\Drivers\etc. Looks just like /etc/hosts, so we just add:
192.168.2.2 alas.we.cant.share.this.com
Which should work as long as IP addresses aren’t hardcoded into the application. Thankfully, they weren’t. Now I just run the app, and everything works.
Except that it doesn’t work at all. Turns out that the JVM does certificate validation. When web browsers encounter certificate problems, they let the user decide if they want to continue to connect. When just about any other kind of application encounters validation problems, they will just fail.
There are two basic validation steps it will perform:
http://www.matasano.com/log/wp-content/uploads/2007/04/stunnel-makepem.png
The most important parameter you are setting is the Common Name. It must match the server that our application thinks that it is going to communicate with.
Then I cheat and use InstallCert, a Java app written by Andreas Sterbenz who also beat his head against Java certificate validation issues. The neat thing about InstallCert is that you just give it a URL and it will grab the cert and create a keystore you can use. You just copy over your old cacerts file with the newly created one, and your cert will now be accepted for future use. We just point InstallCert at our stunnel instance:
http://www.matasano.com/log/wp-content/uploads/2007/04/InstallCert-start.png
You can safely ignore the SSLHandshake errors. You should really run InstallCert on the machine you intend to test from (in my case the Windows box), but it was faster for me to create screencaps in OS X. Then InstallCert will ask you to if you want to accept the cert:
http://www.matasano.com/log/wp-content/uploads/2007/04/InstallCert-confirm.png
InstallCert will create a file called jssecacerts in the current working directory. You will want to copy that file over the actual keystore usually located in JAVAPATH/lib/security/cacerts.
Note: Backup the cacerts file before overwriting it.
This is where someone comments, “but all you had to do was edit java.security to say XXX and you could have disabled certificate validation”, and where I wish there was a phrase that meant both Thank You and I Hate You. If it turns out that I am correct, then I have to ask: Why on Earth isn’t this a configuration file option?
http://www.matasano.com/log/843/mitming-an-sslized-java-app/
My initial take was that I would use two instances of stunnel (I use 3.x because I am old, crusty, and like the simplicity of the 3.x command line interface), with Blackbag’s replug in between so I can view the traffic.
So, here is my simple setup (monitoring a connection to www.amazon.com as an example):
http://www.matasano.com/log/wp-content/uploads/2007/04/stunnel-replug.png
All I do is test it with another instance of stunnel and we see that trafficis passing through our rat’s nest of proxying.
Of course, the first wrinkle is that I need to actually test from Windows.
So we load up Parallels and get the application pointing at ourtunnels. Easiest way to do this is to just edit the hosts file, locatedat \WINDOWS\System32\Drivers\etc. Looks just like /etc/hosts, so we just add:
192.168.2.2 alas.we.cant.share.this.com
Which should work as long as IP addresses aren’t hardcoded into the application. Thankfully, they weren’t. Now I just run the app, and everything works.
Except that it doesn’t work at all. Turns out that the JVM does certificate validation. When web browsers encounter certificate problems, they let the user decide if they want to continue to connect. When just about any other kind of application encounters validation problems, they will just fail.
There are two basic validation steps it will perform:
This is where I feel like I must have missed something. I can’t find anywhere inside of the Java documentation where I can disable this using JVM configuration files. After poking around for a bit, and using google, I see two options.
Valid Certificate: Is this signed by someone that we trust (e.g. Verisign)?
Hostname: Does the hostname inside of the certificate match the hostname we are trying to connect?
So, I go with Option #1. I start by generating a new certificate using the stunnel Makefile (you can just use OpenSSL):
Install a new certificate into the instance of Java I am using
Decompile, edit and recompile (you can turn off certificate validation programmatically)
http://www.matasano.com/log/wp-content/uploads/2007/04/stunnel-makepem.png
The most important parameter you are setting is the Common Name. It must match the server that our application thinks that it is going to communicate with.
Then I cheat and use InstallCert, a Java app written by Andreas Sterbenz who also beat his head against Java certificate validation issues. The neat thing about InstallCert is that you just give it a URL and it will grab the cert and create a keystore you can use. You just copy over your old cacerts file with the newly created one, and your cert will now be accepted for future use. We just point InstallCert at our stunnel instance:
http://www.matasano.com/log/wp-content/uploads/2007/04/InstallCert-start.png
You can safely ignore the SSLHandshake errors. You should really run InstallCert on the machine you intend to test from (in my case the Windows box), but it was faster for me to create screencaps in OS X. Then InstallCert will ask you to if you want to accept the cert:
http://www.matasano.com/log/wp-content/uploads/2007/04/InstallCert-confirm.png
InstallCert will create a file called jssecacerts in the current working directory. You will want to copy that file over the actual keystore usually located in JAVAPATH/lib/security/cacerts.
Note: Backup the cacerts file before overwriting it.
This is where someone comments, “but all you had to do was edit java.security to say XXX and you could have disabled certificate validation”, and where I wish there was a phrase that meant both Thank You and I Hate You. If it turns out that I am correct, then I have to ask: Why on Earth isn’t this a configuration file option?
http://www.matasano.com/log/843/mitming-an-sslized-java-app/