Monorail Project: project-zero Issues People Development process History Sign in
New issue
Advanced search Search tips
Starred by 9 users
Status: Fixed
Owner:
Closed: Sep 25
Cc:

Restricted
  • Only users with EditIssue permission may comment.


Show other hotlists

Hotlists containing this issue:
Hotlist-1
Hotlist-1


Sign in to add a comment
Broadcom: OOB write when handling 802.11k Neighbor Report Response
Project Member Reported by laginimaineb@google.com, Jun 12 Back to list
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) as well as the Radio Resource Management standard (IEEE 802.11k-2008 RRM). Much of the information related to RRM is transferred by means of Wi-Fi Action Frames, using the RRM category (5).

One such frame which is handled by Broadcom's firmware is the "RRM Neighbor Report Response" frame, which has following general structure:

  -----------------------------------------------------------------------
  | Category (5) | Action (5) | Dialog Token | Neighbor Report Elements |
  -----------------------------------------------------------------------
  0              1            2              3                          X

(See 802.11-2016, 9.6.7.7, 9.4.2.37 for more information).

On the BCM4355C0 SoC with firmware version 9.44.78.27.0.1.56 the RRM Neighbor Report Response frame is handled by RAM function 0x1B0FE8 (which delegates to ROM function 0xABBBC). This function verifies the dialog token (although that is a single byte field, so it can be easily brute-forced by an attacker if they do not know it in advance). Then, the function copies over the contents of the Neighbor Report Response frame into a heap-allocated buffer and subsequently calls an internal ROM function at 0xAC0A8 to store the number of neighbors for each given "Operating Class" (see 9.4.2.37).

Here is the approximate high-level logic for this function:

int function_AC0A8(..., uint8_t* nrrep_buffer, ...) {
  ...
  //Find and increment neighbor in given channel for given OP-Class
  int res = function_AC07C(..., nrrep_buffer, ...);

  //If there's no entry for the given OP-Class, create and populate it
  if (!res) {
    uint8_t* buffer = malloc(456);
    if ( !buffer ) {
      ...
    }
    else {
      buffer[4] = nrrep_buffer[16];              //Operational Class
      uint8_t channel_number = nrrep_buffer[17]; //Channel Number
      uint16_t* chan_neighbor_count_arr = (uint16_t*)(buffer + 6);
      chan_neighbor_count_arr[channel_number]++;      
      ...
    }
  }
  ...
}

As shown in the snippet above, the firmware keeps a linked list of buffers, one per "Operational Class". Each buffer is 456 byte long, and keeps the array holding the number of neighbors per channel. The entries have the following structure:

  -----------------------------------------------------------------------
  | Next Pointer | Operational Channel | Padding | Neighbor Count Array |
  -----------------------------------------------------------------------
  0              4                     5         6                      456

However, since the "Channel Number" field is not validated, an attacker can arbitrarily provide a large value. While the maximal allowed channel number is 0xE0, by providing a larger value (such as 0xFF), the function above will increment a 16-bit word beyond the bounds of the heap-allocated buffer, thereby performing an OOB write. Note that the same insufficient validation is also present in the internal function 0xAC07C.

I've been able to verify that this code path exists on various different firmware versions, including those present on the iPhone 7 and Galaxy S7 Edge.

This bug is subject to a 90 day disclosure deadline. After 90 days elapse
or a patch has been made broadly available, the bug report will become
visible to the public.
 
Project Member Comment 1 by laginimaineb@google.com, Jun 12
Broadcom assigned V2017061204
Comment 2 Deleted
Project Member Comment 3 by laginimaineb@google.com, Aug 23
Attaching exploit for this issue. The exploit gains code execution on the Wi-Fi firmware on the iPhone 7. The password for the archive is "rrm_exploit".

The exploit has been tested against the Wi-Fi firmware as present on iOS 10.2 (14C92), but should work on all versions of iOS up to 10.3.3 (included). However, some symbols might need to be adjusted for different versions of iOS, see "exploit/symbols.py" for more information.

Upon successful execution of the exploit, a backdoor is inserted into the firmware, allowing remote read/write commands to be issued to the firmware via crafted action frames (thus allowing easy remote control over the Wi-Fi chip). 

The attached archive contains the following directories:
  -hostapd-2.6 - A modified version of hostapd utilised in the exploit. This version of hostapd is configured to
                 support 802.11k RRM, and in particular Neighbor Reports. Moreover, this version of hostapd is
                 instrumented to add various commands, allowing injection and reception of crafted action frames
                 used throughout the exploit.
  -exploit     - The exploit itself.

To run the exploit, you must execute the following steps:
  -Connect (and enable) a SoftMAC Wi-Fi dongle to your machine (such as the TL-WN722N)
  -Compile the provided version of hostapd
  -Modify the "interface" setting under "hostapd-2.6/hostapd/hostapd.conf" to match your interface's name
  -Configure the following settings under "exploit/conf.py":
    -HOSTAPD_DIR - The directory of the hostapd binary compiled above
    -TARGET_MAC  - The MAC address of the device being exploited
    -AP_MAC      - The MAC address of your wireless dongle
    -INTERFACE   - The name of the wireless dongle's interface
  -Assemble the backdoor shellcode by running "exploit/assemble_backdoor.sh"
  -Run hostapd with the configuration file provided above, broadcasting a Wi-Fi network ("test80211k")
  -Connect the target device to the network
  -Run "exploit/attack.py"

Following the steps above should result in installation of a simple backdoor allowing read/write access to the firmware. You can interact with the backdoor to gain R/W access to the firmware by calling the "read_dword" and "write_dword" functions, respectively.

RRM.zip
2.0 MB Download
Project Member Comment 4 by laginimaineb@google.com, Aug 28
Labels: CVE-2017-11120
Project Member Comment 5 by laginimaineb@google.com, Aug 29
Labels: Deadline-Grace
Project Member Comment 6 by laginimaineb@google.com, Sep 25
Labels: -Restrict-View-Commit
Status: Fixed
Comment 7 Deleted
File load error, pass : rrm_exploit -> Archiver
Is BCM4355C0 the *only* SoC affected by this? 
File load error, pass : rrm_exploit -> Archiver
Project Member Comment 11 by laginimaineb@google.com, Sep 27
Labels: Restrict-AddIssueComment-EditIssue
This is not a discussion forum, I'm closing additional comments.
Project Member Comment 12 by laginimaineb@google.com, Sep 28
Adding a version of Ian Beer's extra_recipe exploit, with a server stub.
extra_recipe.zip
30.8 KB Download
Sign in to add a comment