Sorry, once again I have been too busy to work on my blog, notably with a prolific Paris Air Show last month, but I finally found some time here over the clouds somewhere between Vilnius and Copenhagen :-)
For new readers, this is the follow-up to a first part entitled "Internet By All Means" in which I was describing how to maximize your chances to get a full & secure Internet access almost anywhere.
In order to achieve this goal we had to achieve maximum reachability on the Internet for various networking services and thus, maximum exposure to remote attacks... making this an interesting case study for discussing the implementation of a maximum of security measures.
First of all, let's assume that at least one of these networking service WILL get hacked. What do we have at stake? What mustn't the hacker be able to do from there?
- read, alter or delete data that might be stored on the stepping stone
- record or tamper with traffic in the network the stepping stone resides in (think ARP cache poisoning etc)
- record or tamper with traffic going through the stepping stone
- escalate privileges inside the stepping stone
- hack other computers in your private network
- use your stepping stone as a relay to hide behind your IP address
1. Protect your valuables
The first two issues can simply be addressed by a common best practice: run the stepping stone on a dedicated (virtual) machine and isolate it from the rest of the network by placing it inside a DMZ. This is an easy way to physically contain an intrusion, but not sufficient as we still want to avoid it.
2. Ensure system integrity
As the stepping stone OS is somewhat static once it is configured, why not make it into a liveCD or read-only VM disk image? This would prevent a hacker from applying any permanent changes to the system, and by having the system regularly reboot you will erase whatever RAM-resident stuff the hacker might have, driving him nuts :-)
3. Relinquish privileges
Many network services require privileges so that they can for example bind to a port under 1024 or create virtual network interfaces. The thing is: they usually need these privileges only during startup, so why have them still available afterwards? A hacker could find profit in that, especially since full (root) privileges are often given to such services instead of just a selection of the privileges they require.
Therefore, these network services must be made to drop their privileges as soon as possible. Problem is: since only they know when it becomes indeed possible, this security feature has to be built in each of them. Fortunately, most of them already have it (see the "-u" flag in Iodine, "user" and "group" options in OpenVPN, etc) and when they don't, the beauty of open source software is that you can add the feature yourself like I did for PingTunnel.
In effect, what you have now is software running with a (preferably dedicated) least-privileged user account, which is a huge improvement compared to letting software run with administrative privileges but still not sufficient:
4. Restrict filesystem access
With a complex filesystem tree you can never be so sure as to have all the file access rights covered: with incorrect read access control on a pseudo terminal device for example a hacker could manage to perform keylogging, and with incorrect write access control in some place or the setuid-bit set on the wrong binary a hacker could perform a privilege escalation.
But thanks to filesystem isolation security features available in modern operating systems, it is possible to convince a program that the filesystem tree starts in a directory of your choice; that way, you can simply forbid any file operation to a process by just "chroot'ing" it in an empty directory with no write permission.
5. Restrict network access
The same principle of least privilege can and should be applied to network access. For example, if you use HttpTunnel to access the OpenSSH service over HTTP tunneling, the HttpTunnel server (hts) should not be given the possibility to connect to anything else than TCP port 22 on the loopback interface:
iptables -N HTS
iptables -A OUTPUT -m owner --uid-owner hts -j HTS
iptables -A HTS -o lo -p tcp --dport 22 -j ACCEPT
iptables -A HTS -j LOG
iptables -A HTS -j REJECT --reject-with icmp-admin-prohibited
6. Protect the kernel
Many sysadmins and even security engineers stop at step #4, if not less... It's a huge mistake! Why? Because of kernel exploits: if a hacker can make one of your processes perform a vulnerable system call, he can obtain kernel privileges (the highest privileges possible) and all of a sudden it's game over!
So, in order to prevent that from happening, we want to forbid each process from performing system calls it does not need. Since kernel exploits are usually found in lesser used system calls like vmsplice, and since the stepping stone related processes once initialized will need little more than network I/O related system calls which can now be considered hardened, we can safely assume that with this technique we zero out the likelyhood of this scenario.
As it is often the case in the UNIX world, there are many alternatives for that: Security-Enhanced Linux (SELinux), GRSecurity, RSBAC, AppArmor, the Linux Intrusion Detection System (LIDS), etc... each having its own advantages and disadvantages.
Personally I use SELinux, probably the most cumbersome one but the most production-ready one in my opinion. Yes, NSA SELinux... If you think I'm crazy for recommending software from a spy agency, I've got a question for you: which one is the most endangering, a closed-source operating system like Windows or a completely open source Linux Security Module?
Most SELinux policies (like the ones found in the Reference Policy project) are applied on programs at the moment they are launched, which makes for over-complicated and coarse-grained policies. The one for OpenVPN for example deals with far much more than just network I/O: notably it deals with (and permanently allows) modifying network interface properties and routing table, something OpenVPN only needs to do at startup; this adds for one unnecessary complexity, but also, importantly, insecurity as letting a hacker play with your routing table is definitely not something you want to do.
As explained above in the paragraph on relinquishing privileges, it often makes much more sense to have each software apply security policies to itself as only it knows the best moment for that is. Therefore I added SELinux support to Iodine, PingTunnel and both 2.0 & 2.1 branches of OpenVPN. In the case of HttpTunnel it is not necessary as it needs only network I/O from the start.
At this point, a successful hacker should only be able to use the networking capabilities of your stepping stone, which is far better than average but still: we don't want anyone to be able to use our stepping stone as a relay for hacking or illegal downloading (especially with the new Internet access suspending laws like HADOPI in France), do we?
But if you consider your tunneling software compromised, how do you differentiate between legitimate traffic (the traffic that was tunneled) and illegitimate traffic (traffic generated by the hacker inside the compromised tunneling software)?
For that you need to authenticate the legitimate traffic, and this is exactly what IPsec's Authentication Headers are for. Note that even though IEEE 802.1X is a network authentication mechanism too, it won't do here as basically once a network cable is authenticated it allows whatever traffic coming through it.
So the idea is to have something like this:
As you can see, the stepping stone is separated from the rest of the LAN by being both a DMZ (in the proper sense of the term) and a DMZ host in order to receive all traffic from the Internet (except for the NAT-related one in my case since it belongs to other computers in my home network).
Speaking of my home network, for the sake of clarity I put nothing more than an icon, but for the ones willing to play Catch 22, I have two words: Intrusion Detection.
Now, since what's underneath whatever encapsulation we used to reach the stepping stone by all means is actually IPsec traffic, providing us with authentication and encryption capabilities, we can have a completely compromized stepping stone that is neither able to send any other traffic than the one it is meant to forward nor able to sniff said traffic.
Indeed: the firewall, acting as an IPsec gateway (agreed it is tunneling software like OpenVPN etc, but it is simple enough that it can be considered hardened) will allow only:
- any traffic from the Internet to the stepping stone
- return traffic from the stepping stone to the Internet, which was established by the latter
- new traffic to the Internet if it is correct IPsec, which can only have been generated by the laptop
It should be sufficient, but if like me you are the kind to wince at the first bullet, this last paragraph should be of interest:
8. Cherry on top: two-factor network access control
Our biggest problem is being able to reach the stepping stone at any moment from anywhere on the Internet, but it doesn't mean everybody should be able to! :-D
People suggested that I use port knocking which is a nifty idea in general, but not possible in our case as we won't always have a direct connection to our stepping stone: it is likely that we'll have to route our DNS tunneling through other servers, our HTTP(S) tunneling through proxies, etc.
However, when you want to use your stepping stone you are most likely to have a second means of telecommunications at your disposal: the phone! Combining it with the firewall allows us to solve the problem, by performing something that I like to call two-factor Network Access Control.
Personally my landline phone service includes a free SIP (VoIP) account, which makes it very easy to trigger a script on the firewall by just making the phone ring: no need to have the script pick up, that way it costs absolutely nothing even when calling from abroad! Here's an example of such a script.
The idea is to allow traffic to the stepping stone only from a selection of trusted Internet sources (wherever you successfully used it from), and every time you move to a new place, just make the phone ring to lower the firewall for a short period of time, have it learn from where you are connecting, and raise again.
Another method (for people won't do have a VoIP account) would be using Twitter: you could have your firewall monitoring a Twitter feed, and whenever you would want your firewall to lower, you could send a message to this Twitter feed via SMS, but this costs money...
So here you are... I hope I haven't forgotten anything as I just finished writing this in a hurry to finally get it over with. Some day I might explain how to generate the stepping stone liveCD with Debian Live... In the meantime: questions, suggestions, comments etc are welcome :-)