Broadcom: Stack buffer overflow when handling 802.11r (FT) authentication response CVE-2017-6975 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. In order to allow fast roaming between access points in a wireless network, the Broadcom firmware supports the Fast BSS Transition feature (IEEE 802.11r-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 ID (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 FT roaming is handled by 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 IEEE 802.11r-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 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. This bug is subject to a 90 day disclosure deadline. If 90 days elapse without a broadly available patch, then the bug report will automatically become visible to the public. Found by: laginimaineb