FORUMS
Remove All Ads from XDA

Evaluating CVE-2015-1474 to escalate to system privileges

22 posts
Thanks Meter: 23
 
By Phate123, Junior Member on 3rd March 2015, 03:07 PM
Post Reply Email Thread
I hope that with this thread we are able to gain system privileges with the help of CVE-2015-1474.

To begin with I try to write down what I have found. This is just a compilation of information so they might look mixed up.

The class GraphicBuffer is utilized by the system service SurfaceFlinger. My current understanding is that the vulnerable method "unflatten" is used to create a GraphicBuffer object from raw data that is sent to the service by IPC using Binder. A forged message might be easiest supplied via adb shell using this commando
Code:
[email protected]:/ $ service call SurfaceFlinger ...
I am not sure yet how the parcel get's eventually to the GraphicBuffer. It is a lot of code and I do not understand the low level graphics system of Android yet. The IGraphicBufferConsumer interface has a sub class BufferItem which has also an unflatten method which will call unflatten on GraphicBuffer. My gut tells me that the Parcel class is also involved in that process, but I'm not sure how yet.

One important piece of information that I'm still missing is how the unflattened data is used in the further processing of SurfaceFlinger. I don't think it is possible to freely write in the memory of SurfaceFlinger with this bug. There are still a lot of sanity checks to come by.

This could also effect on how we have to implement the communication with SurfaceFlinger. Maybe it's also possible with some forged objects and a SurfaceView.

Maybe together we are able to bring some light into this. A little bump in the right direction might help.
The Following 5 Users Say Thank You to Phate123 For This Useful Post: [ View ] Gift Phate123 Ad-Free
 
 
3rd March 2015, 10:22 PM |#2  
Junior Member
Thanks Meter: 9
 
More
Quote:
Originally Posted by Phate123

I hope that with this thread we are able to gain system privileges with the help of CVE-2015-1474.

Take a look at the thread below, It looks like there is already some research begin done but I can't quite get my head around whether they are on the right track. This might help us get going in the right direction though.

http://forum.xda-developers.com/note...t3042045/page6
5th March 2015, 02:30 PM |#3  
Member
Thanks Meter: 97
 
More
Quote:
Originally Posted by awinston

Take a look at the thread below, It looks like there is already some research begin done but I can't quite get my head around whether they are on the right track. This might help us get going in the right direction though.

http://forum.xda-developers.com/note...t3042045/page6

Good news ( @Phate123, @awinston )! I have managed to crash the surfaceflinger on 4.5.2 (should also work on 4.5.3).

I'll upload the code on github, but first I want to briefly explain how I did it.
In Android everything that is a graphical element is represented by an GraphicBuffer.
GraphicBuffers are wrapped in BufferItems and managed by BufferQueues.
Each Queue has two sites, a producer side (IGraphicBufferProducer) and a consumer side (IGraphicBufferConsumer). In the basic scenario an app is the producer and the surfaceflinger is the consumer. These are obviously two different processes, but both must use the same BufferQueue.
BufferQueues are always created and owned by the consumers and consequently live in the same address space as the consumer. Producers must go through Binder to access their side of the queue.

As with everything in Android, the BufferQueue provides the same interface for both native (in the same process) and remote usage. The remote interface is implemented by a proxy that communicates through Binder with the other side.
In android KK BufferQueue implements the native side of the interface for both the producer (BnGraphicBufferProducer) and the consumer (BnGraphicBufferConsumer). These native implementations must provide a handler (onTransact) for requests that come from the remote proxies.

You can read more at https://source.android.com/devices/g...hitecture.html.

Naturally, the first idea that comes into mind is to attack the native implementations of the BufferQueue that reside in the surfaceflinger. As the bug is in the unflatten routine of GraphicBuffer, we would like to craft a rogue parcel that represents a GraphicBuffer and then wait for the surfaceflinger to choke with it.
Unfortunately, from my findings, the bugged unflatten method is not called from the onTransact handler in the native implementations.

Only the proxy implementations seem to be a valid target, through BpGraphicBufferProducer::requestBuffer and BpGraphicBufferConsumer::aquireBuffer. Now we have a problem: as the BufferQueue resides in the surfaceflinger, there is no proxy implementation to attack.

Our only hope is to somehow create the BufferQueue in our process, so that we are the consumers, and use the surfaceflinger as the producer. This way the surfaceflinger would be accessing the BufferQueue through the bugged proxy (BpGraphicBufferProducer::requestBuffer). One way to use the surfaceflinger as a producer is to make screen captures.

I found the screencap command to be a very nice starting point to tinker with the idea as it does exactly what we wanted - it uses the surfaceflinger as a producer and pulls screen captures from it. Next I only had to hook the vtable entry of BpGraphicBufferProducer:: onTransact.

Now we have to control the overflow in GraphicsBuffer::unflatten.
The Following 7 Users Say Thank You to p1gl3t For This Useful Post: [ View ] Gift p1gl3t Ad-Free
5th March 2015, 04:07 PM |#4  
Junior Member
Thanks Meter: 9
 
More
Quote:
Originally Posted by p1gl3t

Good news ( @Phate123, @awinston )! I have managed to crash the surfaceflinger on 4.5.2 (should also work on 4.5.3).

Wow you are really good! I had started to piece some of this together and wanted to document it for good measure even though you are going to clearly beat the rest of us to this exploit. Arguably I could never figure it out, but never hurts to try. At least I am learning.

https://charleszblog.wordpress.com/2...hics-basics-i/
http://translate.google.com/translat...76&prev=search
http://4.bp.blogspot.com/-qQxyvr2Vc8...ection_043.png
https://android.googlesource.com/pla...rface_test.cpp

The screenshot test is where I was focusing but wasn't really getting very far.
5th March 2015, 11:26 PM |#5  
Junior Member
Thanks Meter: 9
 
More
Crashed unflatten as well
Okay so I crashed unflatten as well. Trying to figure out where to go from here. I am a little confused though because I did it natively by calling unflatten directly from a cpp program I wrote with a few lines of code. When you crash it like this how do I know it was the buffer overflow? Sorry, still trying to learn as I go.

03-05 17:06:47.380 2652-2652/? A/libc﹕ Fatal signal 11 (SIGSEGV) at 0x52464247 (code=1), thread 2652 (screenshot)
03-05 17:06:47.490 258-258/? I/DEBUG﹕ *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
03-05 17:06:47.490 258-258/? I/DEBUG﹕ AM write failure (32 / Broken pipe)
03-05 17:06:47.490 258-258/? I/DEBUG﹕ Build fingerprint: 'Amazon/thor/thor:4.4.3/KTU84M/13.4.5.2_user_452004220:user/release-keys'
03-05 17:06:47.490 258-258/? I/DEBUG﹕ Revision: '0'
03-05 17:06:47.490 258-258/? I/DEBUG﹕ pid: 2652, tid: 2652, name: screenshot >>> ./screenshot <<<
03-05 17:06:47.490 258-258/? I/DEBUG﹕ signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 52464247
03-05 17:06:47.490 955-1055/? W/NativeCrashListener﹕ Couldn't find ProcessRecord for pid 2652
03-05 17:06:47.500 258-258/? I/DEBUG﹕ r0 b723dfb8 r1 47424652 r2 be94a600 r3 00000020
03-05 17:06:47.500 258-258/? I/DEBUG﹕ r4 b723dfb8 r5 be94a618 r6 52464247 r7 be94a604
03-05 17:06:47.500 258-258/? I/DEBUG﹕ r8 be94a600 r9 00000000 sl be94a618 fp be94a6ec
03-05 17:06:47.500 258-258/? I/DEBUG﹕ ip b6f08f44 sp be94a590 lr b6f04f4b pc b6e34b94 cpsr 200b0030
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d0 0000000000000000 d1 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d2 0000000000000000 d3 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d4 0000000000000000 d5 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d6 0000000000000000 d7 55ab5f0000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d8 0000000000000000 d9 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d10 0000000000000000 d11 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d12 0000000000000000 d13 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d14 0000000000000000 d15 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d16 0000002000000001 d17 0000000000000020
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d18 b723a630b723a618 d19 b723a658b723a648
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d20 b723a678b723a668 d21 b723a698b723a688
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d22 b723aaf8b723a6a8 d23 b723af58b723af48
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d24 0000000000000000 d25 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d26 0000000000000000 d27 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d28 0000000000000000 d29 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d30 0000000000000000 d31 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ scr 00000010
03-05 17:06:47.510 258-258/? I/DEBUG﹕ backtrace:
03-05 17:06:47.510 258-258/? I/DEBUG﹕ #00 pc 00005b94 /system/lib/libui.so (android::GraphicBuffer::unflatten(void const*&, unsigned int&, int const*&, unsigned int&)+23)
03-05 17:06:47.510 258-258/? I/DEBUG﹕ #01 pc 00002f47 /data/local/tmp/screenshot
03-05 17:06:47.510 258-258/? I/DEBUG﹕ #02 pc 0000e4db /system/lib/libc.so (__libc_init+50)
03-05 17:06:47.510 258-258/? I/DEBUG﹕ #03 pc 0000308c /data/local/tmp/screenshot
03-05 17:06:47.510 258-258/? I/DEBUG﹕ stack:
03-05 17:06:47.510 258-258/? I/DEBUG﹕ be94a550 00000000
03-05 17:06:47.510 258-258/? I/DEBUG﹕ be94a554 b6010001
03-05 17:06:47.510 258-258/? I/DEBUG﹕ be94a558 00000000
03-05 17:06:47.510 258-258/? I/DEBUG﹕ be94a55c b6e0d44b /system/lib/libgui.so

---------- Post added at 12:26 AM ---------- Previous post was at 12:12 AM ----------

Quote:
Originally Posted by awinston

Okay so I crashed unflatten as well.

Is the trick to do it through the surfaceflinger process because it is running with escalated privileges?
The Following User Says Thank You to awinston For This Useful Post: [ View ] Gift awinston Ad-Free
6th March 2015, 02:35 PM |#6  
Member
Thanks Meter: 97
 
More
Quote:
Originally Posted by awinston

Okay so I crashed unflatten as well. Trying to figure out where to go from here. I am a little confused though because I did it natively by calling unflatten directly from a cpp program I wrote with a few lines of code. When you crash it like this how do I know it was the buffer overflow? Sorry, still trying to learn as I go.

03-05 17:06:47.380 2652-2652/? A/libc﹕ Fatal signal 11 (SIGSEGV) at 0x52464247 (code=1), thread 2652 (screenshot)
03-05 17:06:47.490 258-258/? I/DEBUG﹕ *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
03-05 17:06:47.490 258-258/? I/DEBUG﹕ AM write failure (32 / Broken pipe)
03-05 17:06:47.490 258-258/? I/DEBUG﹕ Build fingerprint: 'Amazon/thor/thor:4.4.3/KTU84M/13.4.5.2_user_452004220:user/release-keys'
03-05 17:06:47.490 258-258/? I/DEBUG﹕ Revision: '0'
03-05 17:06:47.490 258-258/? I/DEBUG﹕ pid: 2652, tid: 2652, name: screenshot >>> ./screenshot <<<
03-05 17:06:47.490 258-258/? I/DEBUG﹕ signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 52464247
03-05 17:06:47.490 955-1055/? W/NativeCrashListener﹕ Couldn't find ProcessRecord for pid 2652
03-05 17:06:47.500 258-258/? I/DEBUG﹕ r0 b723dfb8 r1 47424652 r2 be94a600 r3 00000020
03-05 17:06:47.500 258-258/? I/DEBUG﹕ r4 b723dfb8 r5 be94a618 r6 52464247 r7 be94a604
03-05 17:06:47.500 258-258/? I/DEBUG﹕ r8 be94a600 r9 00000000 sl be94a618 fp be94a6ec
03-05 17:06:47.500 258-258/? I/DEBUG﹕ ip b6f08f44 sp be94a590 lr b6f04f4b pc b6e34b94 cpsr 200b0030
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d0 0000000000000000 d1 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d2 0000000000000000 d3 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d4 0000000000000000 d5 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d6 0000000000000000 d7 55ab5f0000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d8 0000000000000000 d9 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d10 0000000000000000 d11 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d12 0000000000000000 d13 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d14 0000000000000000 d15 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d16 0000002000000001 d17 0000000000000020
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d18 b723a630b723a618 d19 b723a658b723a648
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d20 b723a678b723a668 d21 b723a698b723a688
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d22 b723aaf8b723a6a8 d23 b723af58b723af48
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d24 0000000000000000 d25 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d26 0000000000000000 d27 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d28 0000000000000000 d29 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ d30 0000000000000000 d31 0000000000000000
03-05 17:06:47.500 258-258/? I/DEBUG﹕ scr 00000010
03-05 17:06:47.510 258-258/? I/DEBUG﹕ backtrace:
03-05 17:06:47.510 258-258/? I/DEBUG﹕ #00 pc 00005b94 /system/lib/libui.so (android::GraphicBuffer::unflatten(void const*&, unsigned int&, int const*&, unsigned int&)+23)
03-05 17:06:47.510 258-258/? I/DEBUG﹕ #01 pc 00002f47 /data/local/tmp/screenshot
03-05 17:06:47.510 258-258/? I/DEBUG﹕ #02 pc 0000e4db /system/lib/libc.so (__libc_init+50)
03-05 17:06:47.510 258-258/? I/DEBUG﹕ #03 pc 0000308c /data/local/tmp/screenshot
03-05 17:06:47.510 258-258/? I/DEBUG﹕ stack:
03-05 17:06:47.510 258-258/? I/DEBUG﹕ be94a550 00000000
03-05 17:06:47.510 258-258/? I/DEBUG﹕ be94a554 b6010001
03-05 17:06:47.510 258-258/? I/DEBUG﹕ be94a558 00000000
03-05 17:06:47.510 258-258/? I/DEBUG﹕ be94a55c b6e0d44b /system/lib/libgui.so

---------- Post added at 12:26 AM ---------- Previous post was at 12:12 AM ----------



Is the trick to do it through the surfaceflinger process because it is running with escalated privileges?

Surfaceflinger runs under the system user (+drmrpc group) and should have access to /dev/qseecom, through which we can get root using CVE-2014-4322.
The problem is that the heap buffer overflow triggered by unflatten seems very difficult to exploit.

We must consider the following to achieve a controlled memory write:
  • sizeof(native_handle_t) + sizeof(int)*(numFds+numInts) must overflow 32 bits and remain small enough that the malloc succeeds and returns a valid heap address in h->data. If the malloc were to fail, we would memcpy to address 0 and get a seg fault.
  • as even after the malloc, numInts and numFds are used only after being multiplied by 4 (sizeof(int)), we can ignore the 2 most significant bits from both of them. This means that the only way to get any kind of bof is to generate transport from bit 29 to bit 30 on the sum numFds+numInts. Consequently, at least one of numInts or numFds must have bit 29 set. This doesn't sound very good because next we will do a memcpy of numFds * 4 bytes and next a memcpy of numInts * 4 bytes, meaning that at least one of the two memcpy calls will try to copy at least (1<<31) bytes. This will certainly lead to a segfault before we can trigger something from another thread...
  • the executable code is position independent so we would need to leak an address to be able to use rop.

Things don't look good at all... I really hope that I have made a mistake or that there is another approach to the problem.
I'm afraid that the pros would have already implemented an exploit by now, if it could have been done.
The Following User Says Thank You to p1gl3t For This Useful Post: [ View ] Gift p1gl3t Ad-Free
6th March 2015, 02:54 PM |#7  
OP Junior Member
Thanks Meter: 23
 
More
Quote:
Originally Posted by p1gl3t

We must consider the following to obtain a controlled memory write:

  • sizeof(native_handle_t) + sizeof(int)*(numFds+numInts) must overflow 32 bits and remain small enough that the malloc succeeds and returns a valid heap address in h->data. If the malloc were to fail, we would memcpy to address 0 and get a seg fault.
  • as even after the malloc, numInts and numFds are used only after being multiplied by 4 (sizeof(int)), we can ignore the 2 most significant bits from both of them. This means that the only way to get any kind of bof is to generate transport from bit 29 to bit 30 on the sum numFds+numInts. Consequently, at least one of numInts or numFds must have bit 29 set. This doesn't sound very good because next we will do a memcpy of numFds * 4 bytes and next a memcpy of numInts * 4 bytes, meaning that at least one of the two memcpy calls will try to copy at least (1<<31) bytes. This will certainly lead to a segfault before we can trigger something from another thread...
  • the executable code is position independent so we would need to leak an address to be able to use rop.

Things don't look good at all... I really hope that I have made a mistake or that there is another approach to the problem.
I'm afraid that the exploit pros would have already implemented an exploit if it could have been done.

That have been my thoughts too. There is a memory corruption but it is difficult to use and it is not on areas that could be used to manipulate the return stack or a vtable entry. Or I just can't see the way. I have experience in this area,but it is kinda limited.

BTW: These drivers are not used by the Fire HDX by chance? https://www.codeaurora.org/projects/...-cve-2014-4324

Sadly I cannot find enough time to spend hours on digging. I hope there are some to be find this weekend though.
The Following User Says Thank You to Phate123 For This Useful Post: [ View ] Gift Phate123 Ad-Free
6th March 2015, 03:45 PM |#8  
Member
Thanks Meter: 97
 
More
Quote:
Originally Posted by Phate123

That have been my thoughts too. There is a memory corruption but it is difficult to use and it is not on areas that could be used to manipulate the return stack or a vtable entry. Or I just can't see the way. I have experience in this area,but it is kinda limited.

BTW: These drivers are not used by the Fire HDX by chance? https://www.codeaurora.org/projects/...-cve-2014-4324

Sadly I cannot find enough time to spend hours on digging. I hope there are some to be find this weekend though.

I don't think a stack attack would have been feasible at all as the code should be compiled with stack protector on and we can't do a brute force on the canary value. Hijacking a vtable pointer or a got entry would have been the way to go, but we still wouldn't know what to write as everything is aslr'd.

Regarding those camera drivers, I think someone over at the Samsung section also mentioned them. I'll look into them and report back.
6th March 2015, 04:35 PM |#9  
Junior Member
Thanks Meter: 9
 
More
Quote:
Originally Posted by p1gl3t

I don't think a stack attack would have been feasible at all as the code should be compiled with stack protector on and we can't do a brute force on the canary value. Hijacking a vtable pointer or a got entry would have been the way to go, but we still wouldn't know what to write as everything is aslr'd.

Would you mind sharing your code even though it doesn't look like you will be able to exploit this overflow? I am still trying to get my head around the basic attack through surface flinger and it would help me greatly to better understand how at least in theory this works. No worries if you don't want to.
6th March 2015, 05:25 PM |#10  
Member
Thanks Meter: 97
 
More
Quote:
Originally Posted by awinston

Would you mind sharing your code even though it doesn't look like you will be able to exploit this overflow? I am still trying to get my head around the basic attack through surface flinger and it would help me greatly to better understand how at least in theory this works. No worries if you don't want to.

Here you go: https://github.com/p1gl3t/CVE-2015-1474_poc.
The Following 6 Users Say Thank You to p1gl3t For This Useful Post: [ View ] Gift p1gl3t Ad-Free
6th March 2015, 07:51 PM |#11  
zxz0O0's Avatar
Senior Member
Thanks Meter: 5,133
 
Donate to Me
More
p1gl3t, great job on creating a poc of the exploit
The Following User Says Thank You to zxz0O0 For This Useful Post: [ View ] Gift zxz0O0 Ad-Free
Post Reply Subscribe to Thread

Guest Quick Reply (no urls or BBcode)
Message:
Previous Thread Next Thread
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes