IKEv1 Fuzzer 0.2 [sig]
Paper for people who are not the target audience of this paper (security professionals or those who have an interest in IPsec).
Security Advisory for Libreswan
Security Advisory for strongSwan
Security Advisory for IPsec Tools
Network service fuzzing is not very exciting news. The number of public smart network service fuzzers is a pretty serious problem, though [Metasploit] [Sutton] [Tsankov]. IPsec uses a protocol called IKE or ISAKMP to exchange keys [Piper] [Maughan]. Without this service, the keys are static and are not secure [Piper 12] [Bellovin 4]. IKE is not a difficult protocol to implement, but the number of failure modes makes it difficult to get full coverage. IPsec has hundreds of insecure modes and any minor glitch could be the difference between leaking private keys and pretty good security. What makes IKE difficult to fuzz is the system of payloads. Each payload is described in the previous payload using a "Next Payload" field. Not all payloads must be decoded for the message to be parsed, [Maughan 22] which means that broken fuzzers will not produce correct results. Each packet has a couple payloads in order to be valid and can have many payloads technically; the spec is so flexible that a naïve parser that attempts to implement a large part of IKEv1 will almost certainly have vulnerabilities. Bruce Schneier and Niels Ferguson wrote a cryptographic analysis of IPsec which came up with many faults [Schneier]. While some have pointed out that the paper says that IPsec is the best we have, I rebut with this quote:
... we do not believe that it will ever result in a secure operational system. It is far too complex, and the complexity has lead to a large number of ambiguities, contradictions, inefficiencies, and weaknesses. It has been very hard work to perform any kind of security analysis; we do not feel that we fully understand the system, let alone have fully analyzed it. [Schneier 26]
If that doesn't convince you that Bruce Schneier and Niels Ferguson have given IPsec a failing grade then I will not attempt to sway you any further.
Peach 2.3 doesn't deal with conditional logic very well. It balloons in memory and takes forever to crack. This makes Peach 2.3 a very bad fuzzer for IPsec because of the above "Next Payload" problem. Peach 2.3 works very well for many types of file formats and network protocols, but most of the important ones will never be possible to fuzz with Peach 2.3. I don't know if Peach 3 has the same problems, but if it doesn't, you should port this fuzzer to Peach 3 and improve it so that it implements IKEv1 and IKEv2. Since I don't use Peach 3 (I refuse to upgrade), I dealt with the limitation and wrote a simple fuzzer that only fuzzed the top header and then fuzzed the payload as a binary blob. I understand how awful this is and I understand that the fuzzer is not good enough to find serious flaws in IKE servers. I want to improve it, but I have met the limitations of my fuzzer. I plan to write a fuzzer from scratch (work in progress) which implements IKEv1 and IKEv2 and deals with the problem of payloads. I spent one day writing this fuzzer and one day running the fuzzer and filing the four bugs it found. The writing of the fuzzer was the easy part. Setting up virtual machines, installing the IKE servers from source, configuring them, and sending bug reports was the hard part. Improving upon this fuzzer would actually be pretty easy if Peach 2.3 didn't have serious issues with conditional logic. If it worked, you would simply need to add XML elements according to the RFCs in such a way that it improves the coverage of the fuzzer.
My method was pretty efficient after a bit of setup. First I needed to capture real IKE packets sent by an IKE client. It is fairly difficult to set up an IKE system, but once you've figured out the right configuration, you're in good shape. Once I had captured packets, I used Wireshark and Peach 2.3's Wireshark Analyzer to generate a Peach Pit. I could have implemented the protocol easily using the RFC, but the PeachShark method can create Peach Pits for many different binary network protocols. This is an incredibly valuable tool. Once I had generated a Peach Pit, I fixed all the bugs I found in the file so that the fuzzer produced a valid IKE packet when I ran the fuzzer. Then I tested mutation of a large number of IKEv1 packets I had captured. I made modifications to the Peach Pit to improve Peach's mutation of values. Then I ran the fuzzer. Then I modified the Peach Pit. Then I ran the fuzzer again. I repeated this until I was satisfied that I was getting good coverage. When I had run a large number of tests, I changed the strategy of the fuzzer from Default to Random. The Random strategy will run forever, which is good for a complex protocol which has a very bad fuzzer. Remember that the intention is not full coverage (Peach 2.3 doesn't even attempt this when you've got a perfect Peach Pit and a simple protocol) but instead to find a reasonable number of vulnerabilities after approximately 16 hours of effort.
cp -i /etc/ssl/openssl.cnf . patch -p0 < openssl_ipsec_ca.conf.patch openssl req -config openssl.cnf -new -x509 -newkey rsa:2048 -days 3650 -nodes -keyout ipsec_ca.key -out ipsec_ca.pem touch index.txt echo '01' > serial openssl req -config openssl.cnf -newkey rsa:2048 -nodes -keyout peter.key -out peter.req openssl ca -config openssl.cnf -in peter.req -out peter.pem
sudo tcpdump -i tap3 -s 0 -w /home/cap/racoonx13.cap -Z nobody
sudo racoon -F -v -f client_racoon.conf & sudo racoonctl vpn-connect 169.254.44.43
wireshark /home/cap/racoonx13.capfilter: udp
sudo gdb /usr/sbin/racoon run -F -ddd -f server_racoon.conf
python /path/to/Peach2.3/peach.py --analyzer=shark.WireSharkAnalyzer in packet.pdml proto udp out packet.xml
At this point there will be a very buggy Peach pit which you can use to create a working Peach pit.
If you can deal with these, PeachShark is an incredibly powerful tool to fuzz network protocols. It may be possible to fuzz USB using PeachShark.
#!/bin/bash # Fuzzing IKEv1 using Peach 2.3 # by Javantea # May 14, 2015 # Based on my previous work fuzzing with Peach, but clearly written from # scratch today. # Create a ton of bin files. python3 pcap2bin.py racoonx14.cap # Sort out first packets from second packets and responses. mkdir IKEv1_packet2_bins for file in IKEv1_bins/*; do X=$(hexdump -C "$file" |head -n 1 |cut -c 36-58); if [ "$X" != "00 00 00 00 00 00 00 00" ]; then mv -i "$file" IKEv1_packet2_bins/; echo "$X" "$file"; fi; done # The agent is bad news because it causes remote code execution. # Firewall your system completely (IPv4 and IPv6) before using the agent! # You can run this fuzzer without the agent. # See the XML file for the Agent description. # python ~/src/Peach2.3/peach.py -a 9001 insecure >ikev1agent1.txt 2>&1 & # Run the fuzzer python ~/src/Peach2.3/peach.py ikev1.xml >ikev1a.txt 2>&1 & cat << ONTHEREMOTE On the remote system, run: sudo valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes /usr/sbin/racoon -F -f server_racoon.conf >valgrind_racoon3.txt 2>&1 ONTHEREMOTE; #root 17275 8.2 42.3 291848 212724 tty1 S+ 11:01 0:36 valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes /usr/sbin/racoon -F -f server_racoon.conf
As you can see, the above script tells you to run racoon with valgrind. This helps find interesting memory errors that do not result in crashes. Another way to find memory errors is to use Address Sanitizer (ASAN) [ASan]. It is very easy to use and only requires compiling from source (which most open source projects can do).
This fuzzer does not deal with crashes at all. All crash analysis and reproduction must be done manually. For example, if you notice that your IKE daemon crashes you must stop your fuzzer, find out what possible range caused the crash and use a binary tree to find the actual test case that crashed the daemon. An example of a binary tree: if you know that the crash occurred between 1 and 100000, run the fuzzer on tests 1-50000. If it crashes, test 1-25000. If it doesn't crash, test the other half of the range. This method takes time and effort which is quite unfortunate if you have a large number of unique bugs. It also makes testing very difficult because the crashing daemon will miss a large number of tests and cannot be restarted lest it crash again. An automated system of testing would certainly benefit someone who was improving the fuzzer.
If you find an elegant way to deal with crashes please cite this paper. Many people have written agents that use SSH and GDB or ps to check whether the server has crashed. These slow down Peach by a factor of 10-1000 which is only acceptable for small fuzzing runs. Monitors that use ICMP or UDP might be reasonable, but I await a person actually claiming success.
Modify the ikev1.xml file to have the correct IP address for your IKE server. Use packet capturing to ensure that you are sending semi-valid packets.
python ~/src/Peach2.3/peach.py ikev1.xml >ikev1a.txt 2>&1 &
If you have any troubles with Peach 2.3, remember that it is no longer supported and that you should consider upgrading to Peach 3. This means that you will have to make changes to the ikev1.xml file to make it compatible with Peach 3. No, I will not help you.
This fuzzer found four denial of service vulnerabilities in two good implementations of IKE. It is a mutation fuzzer, which means that it can improve with better data. Does that mean that the fuzzer is smart? It is technically smart. It is not a beautiful or elegant fuzzer. It is poorly implemented, but it has enough of the protocol implemented to prove the concept. Using a different framework, this fuzzer could possibly become the standard for IKEv1 testing. Takanen, et al calculated that an open source fuzzer would find four individual flaws and would cost $64,000 and take three weeks to write and run [Takanen 112]. This fuzzer took two two days to write and run and found four individual flaws and cost nothing but my time. I consider this a win for the open source community and I look forward to seeing someone improve or rewrite my fuzzer and find more bugs.