Google Android - IOMX 'getConfig'/'getParameter' Information Disclosure








Android: Information Disclosure in IOMX getConfig/getParameter
Platform: Verified on google/razor/flo:6.0.1/MMB29O/2459718:user/release-keys
Class: Information Disclosure

The GET_CONFIG and GET_PARAMETER calls on IOMX are vulnerable to an information disclosure of uninitialized heap memory. This could be used by an attacker to break ASLR in the media server process by reading out heap memory which contains useful address information.

The relevant code in frameworks/av/media/libmedia/IOMX.cpp is:

node_id node = (node_id)data.readInt32();
OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());

size_t size = data.readInt64();

void *params = malloc(size);, size); <- Read in the buffer from the parcel to initialize

// SNIP - getParameter etc.

if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) {
  reply->write(params, size); <- Write back entire buffer to caller

The vulnerability stems from the fact that Parcel::read(void* outData, size_t len) fails quickly if it doesn’t have sufficient data in the parcel to satisfy the request leaving the outData buffer untouched. As long as the call to getParameter or getConfig succeed then the entire, mostly uninitialized buffer will be returned. For example if the parameter is only 8 bytes in size but the caller passes a size field of 128 bytes (but doesn’t write those 128 bytes into the parcel) then the 120 bytes following in the heap will be returned uninitialized. 

Arguably there’s also a potential NULL pointer dereference here depending on the implementation as the call to malloc can fail with an arbitrary size value. But I think later functions handle the NULL case. 
I’d suggest that the result of should be checked to ensure all the data has been read correctly.

Proof of Concept:
I’ve provided a PoC which exploits the issue and prints a 64 byte buffer (with 56 bytes uninitialized) to logcat. It uses the component. I’ve only tested this on a Nexus 5 and Nexus 7 devices, but I’m guessing that decoder should be everywhere. You should be able to create default Android Studio project and call OMXInfoDisclosurePoC.testOMX
from the Main Activity. When run you should see a line in logcat similar to:

E/MyClass: allocateNode Error: 0
E/MyClass: Allocate Node: 42
E/MyClass: Result: 040000000101000XXXXXXXXXX

Where XXXXXX should be uninitialized memory from the heap.

Proof of Concept: