Broadcom Wi-Fi SoC - Heap Overflow 'wlc_tdls_cal_mic_chk' Due to Large RSN IE in TDLS Setup Confirm Frame

EDB-ID:

41806




Platform:

Hardware

Date:

2017-04-04


Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1047

Broadcom produces Wi-Fi HardMAC SoCs which are used to handle the PHY and MAC layer processing. These chips are present in both mobile devices and Wi-Fi routers, and are capable of handling many Wi-Fi related events without delegating to the host OS.

One of the events handled by the BCM firmware is the processing of TDLS connections (802.11z). TDLS connections allow clients to exchange data between one another without passing it through the AP (thus preventing congestion at the AP).

In order to verify the integrity of TDLS messages, each message exchanged between the TDLS peers includes a message integrity code (MIC). The MIC is calculated using AES-CMAC with a key derived during the setup process (TPK-KCK).

When a TDLS Setup Request frame is sent by either one of the peers in an established TDLS connection, the receiving client must verify the MIC before processing the request. The MIC for TDLS Setup Request and TDLS Setup Confirm frames is calculated as follows:

AES-CMAC(TPK-KCK, InitiatorMAC       ||
                  ResponderMAC       ||
                  TransactionSeq     ||
                  LinkID-IE          ||
                  RSN-IE             ||
                  TimeoutInterval-IE ||
                  FastTransition-IE)

(see "wpa_tdls_ftie_mic" under https://w1.fi/cgit/hostap/plain/src/rsn_supp/tdls.c)

All TDLS connections are accepted automatically from any peer and are handled solely by the BCM firmware (meaning there is no need for user interaction or involvement in any way - once a TDLS Setup Request is received by the firmware, it will proceed with the TDLS handshake and subsequently create a TDLS connection with the requesting peer).

When the BCM firmware receives a TDLS Setup request frame, it verifies the MIC and responds with a TDLS Setup Response frame. The initiator then sends a TDLS Setup confirm frame in order to establish the connection. The BCM firmware uses the "wlc_tdls_cal_mic_chk" function to calculate the MIC of the received frames (both for the setup and the confirm). When processing the TDLS Setup Request frame, the RSN IE is verified and parsed in order to proceed with the derivation of the TPK. This verification also makes sure that the length of the RSN IE is valid for the chosen encryption type. However, when a TDLS Setup Confirm (M3) message is received, the firmware fails to verify the RSN IE, before calling the "wlc_tdls_cal_mic_chk" function in order to verify the MIC of the incoming frame.

The "wlc_tdls_cal_mic_chk" function allocates a buffer of size 256 on the heap, into which the needed information elements are gathered in order to calculate the AES-CMAC. However, the function does not sufficiently verify the length of the RSN IE included in the Setup Confirm frame. This allows an attacker to include an abnormally large RSN IE, causing a heap-overflow in "wlc_tdls_cal_mic_chk".

Here is the approximate simplified high-level code for the function:

1.  uint8_t* buffer = malloc(256);
2.  uint8_t* pos = buffer;
3.  
4.  //Copying the initial (static) information
5.  uint8_t* linkid_ie = bcm_parse_tlvs(..., 101);
6.  memcpy(pos, linkid_ie + 0x8, 0x6);  pos += 0x6;            //Initiator MAC
7.  memcpy(pos, linkid_ie + 0xE, 0x6);  pos += 0x6;            //Responder MAC
8.  *pos = transaction_seq;             pos++;                 //TransactionSeq
9.  memcpy(pos, linkid_ie, 0x14);       pos += 0x14;           //LinkID-IE
10. 
11. //Copying the RSN IE
12. uint8_t* rsn_ie = bcm_parse_tlvs(..., 48);
13. if (rsn_ie[1] + 2 + (pos - buffer) > 0xFF) {
14.     ... //Handle overflow
15. }
16. memcpy(pos, rsn_ie, rsn_ie[1] + 2); pos += rsn_ie[1] + 2;  //RSN-IE
17. 
18. //Copying the remaining IEs
19. uint8_t* timeout_ie = bcm_parse_tlvs(..., 56);
20. uint8_t* ft_ie      = bcm_parse_tlvs(..., 55);
21. memcpy(pos, timeout_ie, 0x7);       pos += 0x7;            //Timeout Interval IE
22. memcpy(pos, ft_ie, 0x54);           pos += 0x54;           //Fast-Transition IE

As can be seen above, although the function verifies that the RSN IE's length does not exceed the allocated buffer (line 13), it fails to verify that the subsequent IEs also do not overflow the buffer. As such, setting the RSN IE's length to a large value (i.e., such that rsn_ie[1] + 2 + (pos - buffer) == 0xFF) will cause the Timeout Interval and Fast Transition IEs to be copied out-of-bounds, overflowing the buffer.

It should be noted that prior to calculating the MIC, the function in charge of processing the TDLS Setup Confirm frame calls a helper function in order to verify the nonce values in the FTIE (to make sure they match the nonces in the TDLS Setup Request and TDLS Setup Response frames, M1 & M2). However, since the attacker is the initiator of the TDLS connection, they may choose the value of Snonce (bytes [52-84) of the FTIE) arbitrarily. This leaves only the Anonce (bytes [20-52) of the FTIE) as uncontrolled bytes during the overflow, since they are chosen by the responder.

It should also be noted that the heap implementation used in the BCM firmware does not perform safe unlinking or include heap header cookies, allowing heap overflows such as the one described above to be exploited more reliably.

I'm attaching a patch to wpa_supplicant 2.6 which modifies the TDLS Setup Confirm frame sent by the supplicant in order to trigger the heap overflow. You can reproduce the issue by following these steps:

  1. Download wpa_supplicant 2.6 from https://w1.fi/releases/wpa_supplicant-2.6.tar.gz
  2. Apply the included patch file
  3. Build wpa_supplicant (with TDLS support)
  4. Use wpa_supplicant to connect to a network
  5. Connect to wpa_cli:
    5.1. Setup a TDLS connection to the BCM peer using "TDLS_SETUP <MAC_ADDRESS_OF_PEER>"

(Where MAC_ADDRESS_OF_PEER is the MAC address of a peer with a BCM SoC which is associated to the same network).

At this point the heap overflow will be triggered. The code in the patch will corrupt the heap, causing the remote BCM SoC to reset after a while.

I've been able to verify this vulnerability on the BCM4339 chip, running version 6.37.34.40 (as present on the Nexus 5). However, I believe this vulnerability's scope includes a wider range of Broadcom SoCs and versions.


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/41806.zip