For the impatient, you can skip directly to the video of the crash.
The vulnerability is in Bluedroid's BLE (Bluetooth Smart) packet parsing code. In order to exercise this vulnerability, an attacker must force a user to connect to a malicious BLE device. Upon connection, the malicious device will issue a malformed GATT notification packet that causes the stack to crash.
It may sound a bit far-fetched that an attacker could force a user to connect to a device, but consider the fact that many BLE apps for Android opportunistically connect to any advertising device in order to determine if it is the device associated with that app. The app need only connect for this attack to succeed.
This vulnerability is not exploitable: the crash is caused by a
FORTIFY_SOURCE
check failure. Additionally, the vulnerability has been fixed since Android 4.4.Show me the code
The code in question can be found in stack/gatt/gatt_cl.c, in gatt_process_notification (line 614). This is code for parsing notification packets, which are messages that a BLE device can periodically send to a BLE master. On line 626 you see the following code:STREAM_TO_UINT16 (value.handle, p);
value.len = len - 2;
memcpy (value.value, p, value.len);
value.len
is uint16_t
. Both p
and len
are controlled by the attacker, though in this case we're only interested in len
. p
is the content of the packet sent by the attacker and len
is the number of bytes in the packet.The code expects a packet with a length of at least two bytes. If an attacker sends a malformed single byte packet, the calculation
value.len = len - 2
will underflow to 65534. The memcpy
will attempt to copy nearly 64k of data from p
.Demonstration
I've made a demonstration video of the remote Android Bluetooth stack crash.I built an attack platform using a modified version of BlueZ, the Linux Bluetooth stack. BlueZ is configured to act as a BLE device running a GATT server. Whenever a BLE master connects to it, it automatically sends a malformed notification packet that is one byte long.
In the video, I demonstrate the vulnerability using a BLE heart rate monitor app. For the purpose of demonstration, I manually connect the app to the evil BlueZ. The stack crashes when the music stops playing.
The output of
adb logcat
contains lines similar to the following:
F/libc (19174): FORTIFY_SOURCE: memcpy buffer overflow. Calling abort().
F/libc (19174): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 19956 (BTU)
Again I note that this attack is not exploitable due to
FORTIFY_SOURCE
runtime checks. The code is instrumented at compile time where the length of the target buffer is known. At runtime, the code checks to see if the memcpy length is larger than the target buffer length and if so calls abort()
.Timeline
This is the timeline following discovery of the bug:- 2013-09-30: Vulnerability disclosed to Google
- 2013-10-07: Fix committed
- 2013-10-30: Android 4.4 r0.9 tagged
- 2013-10-31: Android 4.4 released with fix
Google did not issue a fix for this on Android 4.3, the rationale being that all users should upgrade to 4.4.