I’m gonna tell you a story, based on real events.
Let’s assume a big network, with a highly restrictive policy about who can access the Internet and which sites you can browse. The users can’t access the Internet directly from their workstations (from a layer 3 routing point of view) the only way out is using the corporate browser (an IE6 by the way) which is configured and locked to use a proxy to get access to the world out there.
This proxy is the typical corporate web proxy, I mean, it demands the user to authenticate before it grants access to the requested URL, that previous authentication avoids any anonymous surfing moreover it’s used to track how long the user has been surfing, the requested URL is checked against a set of rules based on regular expressions that allow the proxy admins to filter which URLs or sites are allowed. In practice only a bunch of sites and URLs are allowed by the security policy, so the “interesting” Internet is completely blocked by this ‘fraking’ proxy, no google, no webmail, no access to the server in your home, no pr0n, nothing… just a bunch of bored and only work-related URLs.
Of course, the only protocols allowed by this proxy are HTTP and HTTPS, and as the access to the Internet isn’t network routed from the point of view of the local workstation but proxified at the application level, SSH, the magic-hacker-tool for network tunneling, is useless too :(
Nothing new under the sun so far, we’ve got the typical corporate Internet access scenario based in a HTTP/HTTPS proxy… but there’s more, the foolish-admin-factor works in our favor :)
As an eager mind myself, I wanted to check how these rules were setup by the admin. I managed to get a user account in the proxy server, and of course the first thing that I did was to learn more about the proxy that was installed there finding the config file… and you know what? the file rights were rw-r–r–
I like this admin :) config files readable to everyone in the system. I guess (and now I know for sure) that the admin doesn’t care about these kind things, he should think that everybody is good in this world, that everybody agree with the restrictions and the rules… or maybe he thinks that nobody cares about his servers and his config files… well, he’s wrong!
Be able to read the config file isn’t a big deal if there’s nothing interesting in the file… but if reading the file reveals a bad configuration that creates a hole in the system, then it’s important! I’m talking about how the regular expressions in the filtering rules were coded by our dear admin.
Let’s say you want your users be able to access slashdot.org, a simple and easy way to write a regular expression to permit this could be one like this: http://.*\.slashdot.org/.*
What do you say if someone claims to filter the access with a rule like this one: .*slashdot.org.*
Not so clever, don’t you think? This rule just says: accept any URL that has the string slashdot.org and the dot isn’t really a dot, is any character as it isn’t escaped :)
OK, let’s say you got your own DNS domain, so you can create whatever DNS name you want in it. Let’s say your domain is itsucks.org so you can create the name slashdot.org.itsucks.org so that matches the filtering rule that our “savvy” admin has written in his proxy configuration file.
So, just creating the right name in our DNS pointing at the IP of one of our systems, we got a direct link between the “protected” inside workstation in the “highly restricted” inside network and our external server.
Note that we haven’t cracked, tampered or modified in any way the browser, the proxy or the network. We’ve just took advance of the misconfiguration to reach directly a machine under our control from our internal PC.
Of course, we could use our external server as a forward or reverse proxy to freely browse any site or page, or better than that, we could create a SSH tunnel or any other kind of VPN tunnel being able to connect through the HTTPS proxy to freely get any TCP connection out or even in.
If you have an Apache server running in your server, you can do the trick with a configuration like this:
<VirtualHost *:443> SSLEngine On SSLProtocol All -SSLv2 SSLCertificateFile /etc/apache2/ssl/cert.pem SSLCertificateKeyFile /etc/apache2/ssl/key.pem ServerName slashdot.org.itsucks.org ServerAdmin email@example.com ErrorLog /var/log/apache2/proxy/error.log CustomLog /var/log/apache2/proxy/access.log common ServerSignature On ProxyRequests On ProxyVia On AllowCONNECT 22 <ProxyMatch slashdot.org.itsucks.org> Order deny,allow Deny from all Allow from 184.108.40.206 </ProxyMatch> </VirtualHost>
First of all, I didn’t want to move my SSH server from the 22/tcp to the 80/tcp or 443/tcp, doing that I could avoid the trick and connect directly to the SSH server, but I wanted to keep my HTTP/HTTPS ports for the web services so the connection redirection from Apache turn out to be pretty useful.
How it works:
A SSL virtual host is defined in the standard way on the 443/tcp port. The X.509v3 certificate and the private RSA key are created and defined. The server name is the one that is recognized as a valid and allowed external site by the corporate proxy as it matches the regular-expression filtering rules. This DNS name is resolved by our own DNS server to our own external server IP address. At this point, the HTTPS connection reach our Apache web server from our PC. The forward proxy feature is enabled with the ProxyRequests sentence but the access is denied from all but the IP address that we know is the public address of the corporate proxy that give us access to the Internet from the internal LAN.
The AllowCONNECT sentence is an interesting one, it defines which ports the proxy will be able to connect to when the HTTP CONNECT method is in use. In this case we’re interested in transport the SSH session inside the HTTPS session so when the connection ends in the Apache server and the SSH client sends the CONNECT method to connect to the SSH server, it’ll try to connect to the 22/tcp port so we’ve to permit it.
The last piece of this puzzle is the SSH client. Any client with HTTPS proxy support will do the trick. I got PuTTY in my PC which is perfect to do the trick. You only need to configure the corporate proxy in the Connection/Proxy preferences, try to connect to your server using the funny DNS name that matches the regexp and here you have!
Now, if you configure a tunnel using a local port to go out or a remote port to go in, or even if you use PuTTY as a socks server, you’ll have free rein.