Linux's answer to MS-PPTP ------------------------- Peter Gutmann September 2003 Introduction ============ The following writeup was originally posted to the cryptography mailing list, and was intended as a quick note on a few protocol weaknesses for a crypto audience. Following that, it ended up on slashdot, where it was seen as an analysis of Linux VPN software by a (mostly) non-crypto audience. The main purpose of the writeup was to point out that it's just as easy to create insecure "security" software with open source as with closed source, thus the title of the article (it refers to the security problems with PPTP, not that PPTP is a good example of VPN software). Microsoft took a fair bit of flak over their insecure PPTP implementation, but there are open-source alternatives that are just as bad. The article wasn't meant to be an exhaustive survey of Linux (or any OS in general) VPN software, since there's way too much of this around to cover it all. As with X window managers a few years ago, there are probably enough VPN packages around for every user to have their own personal one without much overlap. Just as with WMs, there will presumably be a general shakeout leading to a smaller number of widely-used ones, driven by a particular environment (kwm driven by KDE, Sawfish driven by Gnome) and a large number of lesser-used alternatives driven by user preference. The problematic ones will still continue to be used for some time, for example Ed Gerck pointed out a Linux Journal article published only last month (Linux Journal, August 2003, p.84, http://www.linuxjournal.com/article.php?sid=6675) that recommends the use of vtun, the least secure of the three that I looked at, but hopefully the better ones will come to predominate. Just as with window managers, a similar move towards a small number of standardised VPN apps will probably occur over time in the open-source community. Although I deliberately omitted mentioning them in the original writeup because specifically pointing to one particular implementation would be seen to implicitly exclude anything else and because predicting the future is always a dicey proposition, I'm guessing that the two major players will probably be Free S/WAN (http://www.freeswan.org/) and OpenVPN (http://openvpn.sourceforge.net/) or something very much like it, with Free S/WAN representing the IPsec approach and OpenVPN representing the SSL-based approach that I described in the article (to paraphrase Winston Churchill, "SSL is the worst way to build a VPN, except for all the others"). Free S/WAN, being an IPsec implementation, inherits all of the IPsec complexity that seems to have been the inspiration for the creation of several of the non-IPsec VPN applications. There are quite a number of complaints from users that Free S/WAN is excessively difficult to use if you want anything more sophisticated than a straightforward setup using pre-shared static keys, more so than most normal IPsec implementations (please, no flamewars over this, I'm just reporting user comments and experience). There also exists an IKE-less IPsec implementation called ipsec_tunnel (http://ringstrom.mine.nu/ipsec_tunnel/) that uses the Linux (not Microsoft) CryptoAPI and that was also inspired by the difficulty in using Free S/WAN ("it was hard to understand and hard to configure"). In addition the moving of Kame-derived IPsec functionality into newer Linux kernels may help the situation with IPsec somewhat. OpenVPN is the "IPsec is too complex" alternative, running a TLS-protected dual control/data channel session over either TCP or UDP, with a reliability layer added for the control chanel if it's running over UDP. The software seems to be fairly straightforward to set up and use. In terms of security, Free S/WAN is an implementation of the IPsec design and so should be as secure as any other IPsec implementation. OpenVPN uses OpenSSL's SSL/TLS for its control channel, and so should be as secure as SSL/TLS in general. For the data channel it uses something based on IPsec's ESP, with IPsec-style sliding window replay detection. The key management step (that is, how to get from the SSL control channel to the data channel) is documented only in the source code, which I don't feel like reverse- engineering, but a quick look through it indicates that the author knows what he's doing. One thing that would be nice here is an RFC documenting a standard way to do this, to allow compatible implementations to be created by others doing SSL-based VPN work. Something based on experience with OpenVPN and other tunnelling implementations that may be around would be useful here (I'm currently bugging various people about this). My focusing on those two imlementations should not be taken to mean that everything else not mentioned above is insecure. I'm was aware of a number of other VPN implementations, but had no idea just how many there really were until people pointed a great many of them out to me in email, and I really don't have time to go through them all. The analysis that follows covers the three VPN packages that I originally looked at. The first one was CIPE, a Linux VPN tool that a friend of mine pointed me to, with the comment that it was widely used, but that no-one else I know seems to have heard of (Red Hat includes it by default, so I guess it depends on your distro). Anyway, I had a quick look at it while I was at his place. It has some problems. CIPE lead me to another program, vtun, which is even worse. Someone else then told me about another one, tinc, which apparently at one time was just as bad as CIPE and vtun, but has been partially fixed after flaws were pointed out (it still has some problems, see below). The following writeup covers some of the problems, with conclusions drawn at the end. As you'll note from reading this, as I went down the list of VPN software I got less and less interested in writing up lengthy analyses, so CIPE (the first one I looked at) has the most detail. CIPE ==== The following comments on CIPE apply to the protocol described at http://sites.inka.de/sites/bigred/devel/CIPE-Protocol.txt (the CIPE home page). Section 2, Packet Encryption: - CIPE uses a CRC-32 for integrity-protection. The use of a weak checksum under CFB or CBC has been known to be insecure for quite some time, providing no (or at least inadequate) integrity protection for the encrypted data. This first gained widespread attention in 1998 with the Core SDI paper "An attack on CRC-32 integrity checks of encrypted channels using CBC and CFB modes" by Ariel Futoransky, Emiliano Kargieman, and Ariel M. Pacetti of CORE SDI S.A, which lead to the SSHv1 insertion attacks and the more or less complete abandonment of SSHv1. To quote the Core SDI work: The use of these algorithms in CBC (Cipher Block Chaining) or CFB (Cipher Feedback 64 bits) modes with the CRC-32 integrity check allows to perform a known plaintext attack (with as few as 16 bytes of known plaintext) that permits the insertion of encrypted packets with any choosen plaintext in the client to server stream that will subvert the integrity checks on the server and decrypt to the given plaintext, thus allowing an attacker to execute arbitrary commands on the server. In other words this provides no real integrity protection for data. Although it first gained widespread publicity in the SSHv1 attacks, the fact that this mechanism is insecure and shouldn't be used goes back to (at least) Kerberos v4 dating from the 1980s (the des-cbc-crc mechanism was deprecated in Kerberos v5, the now ten-year-old RFC 1510). - The padding length is limited to 3 bits, making it unusable with any recent 128-bit block cipher. In particular, AES can't be used. In addition, the inability to pad to more than one (64-bit) cipher block length makes it impossible to disguise message lengths by padding messages to a fixed size (there are further SSHv1 attacks that arose from similar problems there). This weakness is particularly problematic when applied to section 3. - There is no protection against message insertion or deletion. In particular an attacker can delete or replay any message, and in combination with the weak checksum problem can replay modified messages. Consider for example what would happen if an attacker can replay database transactions where money is involved. This issue is also particularly problematic when applied to section 3. Recommendation to fix: This portion of the protocol has a number of flaws, but can be fixed with a more or less complete overhaul of the message format: - Replace the weak checksum with a MAC like HMAC-SHA1. If size is a concern, use a truncated HMAC (but not to a mere 32 bits, which is unconvincing). IPsec cargo-cult protocol design practice would seem to require a MAC size of at least 96 bits (IPsec truncated the MAC to 96 bits because that makes the AH header a nice size, with a payload length of exactly 128 bits (4 32- bit words); everyone else assumed that the number 96 had some magic significance and copied it into their own designs). - Replace the padding with standard PKCS #5 padding, allowing both the use of ciphers with block sizes > 64 bits and padding of messages to hide plaintext size. - Either provide protection against insertion/deletion via message sequence numbers, or make it very explicit in the documentation that CIPE should not be used where insertion/deletion can be a problem, i.e. in situations where the higher-level protocol being tunnelled doesn't provide its own mechanism for detecting missing, inserted, or out-of-sequence messages. A quick fix would be to take the SSL (or SSH) format, strip out the SSL headers and encapsulation, and use what's left (the padding, MAC'ing, etc etc). SSL/SSH also provides message-sequence handling if you want this. Section 3, Key exchange: - The lack of integrity protection means that it's possible to modify keys in transit. As an extreme example, if 3DES keys were used it'd be possible to flip the necessary bits to force the use of weak keys, so that both sides would end up sending plaintext. CIPE doesn't appear to use 3DES, but does use IDEA, which also has weak keys. In any case having an attacker able to set key bits in arbitrary ways is never a good thing (they could presumably force the use of an all-zero or otherwise known key, which is only marginally better than sending in plaintext). - The lack of replay protection means messages containing instructions to switch to old keys can be replayed. In particular, re-use of a compromised key can be forced in this way. - Since packets are ignored if the checksum is bad, it's possible to no-op out key-change messages (forcing continued use of a compromised key) by flipping a bit or two. - The lack of ability to mask the content length allows key management packets to be quickly identified by an attacker, and the above attacks applied. For example it looks like keyex packets will always be 24 bytes long, while tunnelled TCP packets will never be that short. In any case keyex packets are ID'd by the (plaintext) flag that indicates which key type is being used. I'm sure I could find more problems if I thought about it a bit more, but I think that's about enough - see below for more. Recommendation to fix: Basically, this part of the protocol is beyond repair. Any active attacker can cause about the same level of havoc that Schneier et al managed for Microsoft's original PPTP implementation. The fix for this is to scrap the key exchange portion completely and replace it with an SSH or SSL management tunnel, which provides the necessary confidentiality, integrity protection, authentication, message insertion/deletion protection, etc etc. Since control messages are rarely sent, there's no performance penalty to using a TCP channel for this portion of the protocol. The alternative would be to more or less reinvent SSH/SSL using CIPE, which doesn't seem like a useful exercise. (Some time after I did this writeup I came across a post by Zygo Blaxell from February 2001 that pointed out several of these weaknesses, none of which have been fixed since then. Author contacted, no response). vtun ==== While googling for more CIPE info, I found another Linux encrypted tunnel package, vtun. Ugh, this makes CIPE look like a paragon of good crypto design in comparison. Although the format is undocumented, from a quick look at the source code it appears that vtun uses Blowfish in ECB mode with no integrity protection, and as for CIPE no protection against message insertion or deletion, replay attacks, etc etc. Eeek! Then there are code fragments like: void encrypt_chal(char *chal, char *pwd) { char * xor_msk = pwd; register int i, xor_len = strlen(xor_msk); for(i=0; i < VTUN_CHAL_SIZE; i++) chal[i] ^= xor_msk[i%xor_len]; } [...] void gen_chal(char *buf) { register int i; srand(time(NULL)); for(i=0; i < VTUN_CHAL_SIZE; i++) buf[i] = (unsigned int)(255.0 * rand()/RAND_MAX); } which sort of speak for themselves. Furthermore, the key is just a straight hash of the password (no salt, iterated hashing, or other standard precautions are used). I feel somewhat bad for the author(s) of vtun because it looks like there's been a fair bit of work put into it, but honestly my best recommendation for this in terms of security is to scrap it and start again. (Some more googling for vtun info found a post by Jerome Etienne from January 2002 pointing out these exact same problems, so the fact that it has horrible security problems has been known for quite some time. Nothing appears to have been fixed in the nearly two years since the problems were pointed out, so I didn't bother trying to contact the author. At least two people later tried to defend vtun by claiming that it used SSL because it linked in the Blowfish and MD5 algorithm code from OpenSSL (!!!)). tinc ==== So I sent a rough set of notes out for comment and someone pointed me to tinc. tinc uses a completely predictable 32-bit IV in combination with CBC encryption, which makes the first encrypted block vulnerable, but isn't quite as bad as the ECB used in vtun (actually it isn't an IV in the true sense, it prepends a 32-bit sequence number to the encrypted data, but it works the same way). Packets are protected with a 32-bit (very) truncated HMAC using encrypt-then-MAC. tinc's real problem though is the handshake protocol, in which the client and server exchange random RSA-encrypted strings. That's raw bit strings, there's no PKCS #1 or OAEP padding, and the server is happy to act as an oracle for you too. This is a terrible way to use RSA, and usually compromises the key. There is a significant body of literature on this (too much to cite) going back to the early 1980s and continuing through to the current day, with probably the most recent publication in this area being the attack published at Usenix Security '03 only a few weeks ago (in that case it was a timing oracle). Beyond that, the protocol writeup (http://tinc.nl.linux.org/documentation/tinc_6.html#SEC61) points out that: the server sends exactly the same kind of messages over the wire as the client In case the problem isn't obvious yet, note that what's being exchanged is purely a random bit string, with no binding of client or server roles or identities into any part of the exchange. Again, there are way too many references to cite on these issues, although my favourite coverage of a lot of the things you need to think about is in "Network Security: Private Communication in a Public World" by Kaufman, Perlman, and Speciner. As an example, here's a simple attack. The documentation (section 6.3.1) is rather vague about the message flow and key handling, but assuming I've understood it correctly, the message flow is: client server rsa( random_key ) --> random_key( challenge ) --> <-- random_key( sha1( challenge ) ) Simplifying things a bit so that the entire exchange can be abstracted down to "challenge" and "response" (with implied RSA decryption, etc etc taking place as part of that), let's say that Mallet wants to mess with Alice and Bob. So Mallet sends a challenge to Bob (claiming to be Alice) and gets back a response. Mallet gets Bob's encrypted key and challenge back and forwards it to Alice, who returns a response, which Mallet in turn forwards to Bob, a classic chess grandmaster attack. Bob now thinks he's talking to Alice, when in fact Mallet controls one of the two channels. If the exchange is something like rcp (where all traffic is one-way, you write the entire file and close the connection), that's all that's needed, Mallet just sits there sucking down the data that Bob thinks is going to Alice. If not, Mallet does the same thing to Alice, who thinks she's talking to Bob. Again, Mallet now has a one-way channel to Alice. Mallet can then splice the two channels that he controls, so he has a channel in both directions. Again, depending on the protocol being tunnelled, it may be possible for Mallet to use the write channel he controls to get data sent on the read channel he controls. As an extension of the handshake problem, tinc relies heavily on an administrator at both ends of the link configuring the software identically for the handling of the handshake phase, replacing the authenticated parameter negotiation performed by protocols like SSL/TLS, SSH, and IPsec (during the data transfer phase there are ways of negotiating parameters, I haven't looked at this too much). Overall, tinc isn't anywhere near as bad as CIPE or vtun, but like CIPE it should have the handshake/control channel replaced with an SSH or SSL tunnel, and the data-transfer portion could be improved as well. The tinc handshake protocol would also make a nice homework exercise for students in computer security courses, since it's not trivially broken but does exhibits various textbook handshake-protocol flaws, violating a great many of the general principles of secure protocol design: - Don't use the same key for encryption and authentication. - Don't have the key chosen entirely by one side (even if it's only Alice and Bob on the line rather than Mallet, if one of the two has a poor RNG, all communications from them are compromised). - Provide message freshness guarantees (and, if possible, some form of PFS). - Bind the identity of the principals to the authentication. - Don't use the same messages in both directions. - Don't act as an oracle for an attacker. As it stands the handshake protocol only narrowly avoids a variety of basic attacks, making it quite brittle in that the most trivial change (or someone thinking about possible attacks a bit further :-) would probably kill it. (Following on from the footnote at the end of the vtun bit, the same Jerome Etienne who pointed out problems in vtun also picked apart an earlier version of tinc, which looks to have been at about the same level as CIPE when he looked at it. A lot of it appears to have been fixed since then. Authors contacted, their response was that the problems were not that serious, and that a main goal of tinc was to get the opportunity to experiment with secure tunnelling protocols and mechanisms (other design goals are at http://tinc.nl.linux.org/goals). The cryptography mailing list archives contain a long discussion of tinc that ensued after this writeup appeared). Thoughts ======== Several points arise from this writeup: - These programs have been around for years (CIPE goes back to 1996 and vtun to 1998) and (apparently) have quite sizeable user communities without anyone having noticed (or caring, after flaws were pointed out) that they have security problems. I only heard of CIPE when a friend of mine mentioned it to me in passing, and came across vtun by coincidence when I was looking for more info on CIPE. Who knows how many more insecure Linux crypto-tunnel products there may be floating around out there. - It's possible to create insecure "security" products just as readily with open-source as with closed-source software. CIPE and vtun must be the OSS community's answer to Microsoft's PPTP implementation. What's even worse is that some of the flaws were pointed out two to three years ago, but despite the hype about open-source products being quicker with security fixes, some of the protocols still haven't been fixed. At least Microsoft eventually tries to fix their stuff, given sufficient public embarrassment and the odd hundred thousand or so computers being taken out by attackers. - For all of these VPN apps, the authors state that they were motivated to create them as a reaction to the perceived complexity of protocols like SSL, SSH, and IPsec. The means of reducing the complexity was to strip out all those nasty security features that made the protocols complex (and secure). Now if you're Bruce Schneier or Niels Ferguson, you're allowed to reinvent SSL ("Practical Cryptography", John Wiley & Sons, 2003). Unfortunately the people who created these programs are no Bruce or Niels. The results are predictable. - Whenever someone thinks that they can replace SSL/SSH with something much better that they designed this morning over coffee, their computer speakers should generate some sort of penis-shaped sound wave and plunge it repeatedly into their skulls until they achieve enlightenment. Replacing the SSL/SSH data channel is marginally justifiable, although usually just running SSL/SSH over UDP would be sufficient. Replacing the SSL/SSH control channel is never justifiable - even the WAP guys, with strong non-SSL/SSH requirements, simply adapted SSL rather than trying to invent their own protocol. Thanks to Greg Rose for checking a draft copy, and Matt Robinson for inspiring the sound-wave comment.