Broadcom: Stack buffer overflow when handling 802.11r (FT) authentication response (CVE-2017-6975)

2017-04-05T00:00:00
ID SSV:92896
Type seebug
Reporter Root
Modified 2017-04-05T00:00:00

Description

Detailed analysis of reference : the

  • https://googleprojectzero.blogspot.tw/2017/04/over-air-exploiting-broadcoms-wi-fi_4.html the first part
  • https://googleprojectzero.blogspot.tw/2017/04/over-air-exploiting-broadcoms-wi-fi_11.html Part II

Broadcom produces the 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.

In order to allow fast roaming between access points in a wireless network, the Broadcom firmware supports the Fast BSS Transition feature (the IEEE 802.11 r-2008 FT), allowing a client to roam between APs in the same mobility domain.

When a client decides to roam to a different AP in an FT network (in the same mobility domain), they first send an authentication request frame. This frame is either sent to the new AP (in over-the-air FT) or to the original AP (in over-the-DS FT). The authentication request frame includes the Fast BSS Transition Information Element (FT-IE) specifying the R0 key holder IDS (R0KH-ID) corresponding to the roam request.

In response, the AP send back an authentication response frame, also containing an FT-IE. This FT-IE contains the regular fields (Anonce, Snonce, etc.) but also includes the R0KH-ID and R1KH-ID. This is done by encoding the additional fields as TLVs immediately after the structure of the FT-IE (but still within the bounds of the IE), like so: ``


| FT-IE Tag (55) | FT-IE Length | ... FT-IE Contents ... | Additional TLVs |


0 1 2 84 2 + FT-IE Length ``

On the BCM4339 SoC with firmware version 6.37.34.40 the authentication response frame for the FT roaming is handled by the ROM function 0x7B6A4. This function first retrieves the FT-IE. Then, it allocates a heap buffer for it, using the size specified in the IE's length field. The FT-IE is then stored in the allocated buffer, which is subsequently used to extract the R0KH-ID and R1KH-ID fields.

Here is the high-level logic for this function:

`` void function_7B6A4(...) {

//Copying in the FT-IE
char* ft_ie = bcm_parse_tlvs(auth_frame, auth_frame_len, 55);
unsigned short ft_ie_len = ft_ie[1] + 2;
char* ft_ie_buffer = malloc(ft_ie_len);
memcpy(ft_ie_buffer, ft_ie, ft_ie_len);

//Extracting the embedded IEs in the FT-IE. The size of The
//FT-IE's fields without the embedded IEs is 84.
char* ies = ft_ie_buffer + 84;
int ies_length = ft_ie_len - 84;
char* r0kh_id = bcm_parse_tlvs(ies, ies_length, 1);
char* r1kh_id = bcm_parse_tlvs(ies, ies_length, 3);
memcpy(..., ft_ie + 20, 0x20); //Copying the Anonce
...

} ``

First, it should be noted that the function erroneously assumes the size of the FT-IE is at least 84. An attacker could include a shorter FT-IE, causing the function to copy 0x20 bytes from (ft_ie + 20), which are stored as the AP's Anonce.

Second, after extracting the R0KH-ID and R1KH-ID fields, the function proceeds to calculate the PTK. To do so, the value of PMK-R0 must first be derived. According to the IEEE 802.11 r-2008 - 8.5.1.5.3, the PMK-R0 is derived as follows:

R0-Key-Data = KDF-384(XXKey, "FT-R0", SSIDlength || SSID || MDID || R0KHlength || R0KH-ID || S0KH-ID) PMK-R0 = L(R0-Key-Data, 0, 256) PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)

(see also "wpa_derive_pmk_r0" under https://w1.fi/cgit/hostap/plain/src/common/wpa_common.c)

This calculation is performed by the ROM function 0x13C94, which uses the R0KH-ID that was parsed earlier from the FT-IE in the authentication response frame. The function has approximately the following logic:

void function_13C94(...) { char buffer[128]; ... memcpy(buffer, "FT-R0", strlen("FT-R0")); buffer += strlen("FT-R0"); memcpy(buffer, &ssid_length, 1); buffer += 1; memcpy(buffer, ssid, ssid_length); buffer += ssid_length; memcpy(buffer, &mdid, 2); buffer += 2; memcpy(buffer, r0kh_id, r0kh_id_len); buffer += rokh_id_len; ... }

Where "r0kh_id" is the contents of the R0KH-ID field that was extracted from the FT-IE, and "r0kh_id_len" is the length of the extracted field.

Since the R0KH-ID field's length is not validated, an attacker can include an extremely long field within a crafted FT-IE (specifically, the R0KH-ID's length can be at most MAX_IE_SIZE + IE_HEADER_SIZE - FT_IE_SIZE = 255 + 2 - 84 = 173). This would cause the stack-allocated buffer to be overflown, corrupting the stack with attacker-controlled data.