|
|
Subscribe / Log in / New account

Rooting your own phone: android security

From:  Pavel Machek <pavel-AT-ucw.cz>
To:  security-AT-android.com, bugtraq-AT-securityfocus.com
Subject:  rooting your own phone: android security
Date:  Sun, 8 Feb 2009 11:22:44 +0100
Message-ID:  <20090208102244.GA32124@elf.ucw.cz>

Hi!

Note that I'm not giving google much advance warning: I mentioned few
of those issues on irc, but they seemed not welcome there. And purpose
of security system of t-mobile g1 is not to protect owner from evil
attacker; rather it prevents owner from using his phone. g1, as
shipped, will not for example allow connecting your notebook to the
internet.

(I have czech version of g1; you can't simply downgrade it to
rc8/rc29, as it is prevented by CID check).

Yes, I want to get root on my shiny new t-mobile g1. I tried
exploiting dnotify hole that was fixed in 2.6.25.1... only to find out
that CONFIG_DNOTIFY is off in g1 kernel. So I made sure that
CONFIG_INOTIFY is on, and tried exploiting
6ee5a399d6a92a52646836a6e10faf255c16393e. It triggers very
reliably... with SLAB debugging on. With debugging off, it took 2+
hours to reproduce on PC. Given that I'd have to manually
insert/remove SD card for each try, that is not an option. I thought
that rooting 2.6.25 would be easy, but it turns out it is lot harder
than I expected.

I discovered few problems (see below), most are security-relevant, but
none of them is enough to root the phone.

If you have any ideas how to get root on 2.6.25 running on ARM, or
where weak spots in android security are, let me know. (Perhaps by
private email).
								Pavel

Security problems in dynamic linker
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Hmmm, linker fails to check for setgid, and fails to close descriptors
in such cases. It should be possible to write arbitrary files with gid
3003/3004 permissions.

diff --git a/linker/linker.c b/linker/linker.c
index 8f15f62..5e963b4 100644
--- a/linker/linker.c
+++ b/linker/linker.c
@@ -1563,13 +1563,13 @@ static int link_image(soinfo *si, unsigned wr_offset)
     }
 #endif
 
-    /* If this is a SETUID programme, dup /dev/null to openned stdin,
+    /* If this is a SET?ID program, dup /dev/null to openned stdin,
        stdout and stderr to close a security hole described in:
 
     ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD...
 
      */
-    if (getuid() != geteuid())
+    if (getuid() != geteuid() || getgid() != getegid())
         nullify_closed_stdio ();
     call_constructors(si);
     notify_gdb_of_load(si);

Unfortunately, their linker does not support LD_PRELOAD or
LD_LIBRARY_PATH, so nothing to play with there. Interestingly, their
linker they still set it LD_LIBRARY_PATH on system startup.

Integer overflows in *calloc
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

chk_calloc is vulnerable to integer overflows. dlcalloc() _is_
protected. It is controlled by
system_property_get("libc.debug.malloc"). Unfortunately, AFAICT debug
version is not used on production G1.

diff --git a/libc/bionic/malloc_leak.c b/libc/bionic/malloc_leak.c
index 5ddc913..dd42fe3 100644
--- a/libc/bionic/malloc_leak.c
+++ b/libc/bionic/malloc_leak.c
@@ -608,6 +608,7 @@ void  chk_free(void* mem)
 
 void* chk_calloc(size_t n_elements, size_t elem_size)
 {
+	/* FIXME: fails to check overflow -> security hole */
     size_t size = n_elements * elem_size;
     void* ptr = chk_malloc(size);
     if (ptr != NULL) {
@@ -763,6 +764,7 @@ void leak_free(void* mem)
 
 void* leak_calloc(size_t n_elements, size_t elem_size)
 {
+	/* FIXME: fails to check overflow -> security hole */
     size_t size = n_elements * elem_size;
     void* ptr = leak_malloc(size);
     if (ptr != NULL) {

integer overflow in libcutils/strdup8to16()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

(Header files probably should not be executable.)

diff --git a/adb/history.h b/adb/history.h
old mode 100755
new mode 100644

strdup8to16 contains integer overflow. Unfortunately, strdup8to16 does
not seem to be used in security-relevant context.

diff --git a/libcutils/strdup8to16.c b/libcutils/strdup8to16.c
index 8654b04..13a6430 100644
--- a/libcutils/strdup8to16.c
+++ b/libcutils/strdup8to16.c
@@ -49,6 +49,7 @@ extern char16_t * strdup8to16 (const char* s, size_t *out_len)
     len = strlen8to16(s);
 
     // no plus-one here. UTF-16 strings are not null terminated
+    /* Integer overflow here; pass 2.1GB string here and see .... */
     ret = (char16_t *) malloc (sizeof(char16_t) * len);
 
     return strcpy8to16 (ret, s, out_len);

Integer overflow in liblog/showLog()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

showLog() fails to check for integer overflow. If too many lines are
sent to it, it will overflow its buffers. I'm not sure if this code is
used on G1, or if it is only used on emulator.

diff --git a/liblog/fake_log_device.c b/liblog/fake_log_device.c
index d9d67b4..e6775a4 100644
--- a/liblog/fake_log_device.c
+++ b/liblog/fake_log_device.c
@@ -343,6 +343,8 @@ static ssize_t fake_writev(int fd, const struct iovec *iov, int iovcnt) {
  *
  * Log format parsing taken from the long-dead utils/Log.cpp.
  */
+
+/* If we can call this with too many lines of input, it will buffer overrun its buffers...*/
 static void showLog(LogState *state,
         int logPrio, const char* tag, const char* msg)
 {
@@ -449,6 +451,7 @@ static void showLog(LogState *state,
     
     numLines *= 3;  // 3 iovecs per line.
     if (numLines > INLINE_VECS) {
+	    /* Integer overflow here, use 2G lines to exploit... */
         vec = (struct iovec*)malloc(sizeof(struct iovec)*numLines);
         if (vec == NULL) {
             msg = "LOG: write failed, no memory";
@@ -670,6 +673,7 @@ int fakeLogClose(int fd)
     return redirectClose(fd);
 }
 
+/* logWritev is vulnerable to buffer overflow */
 ssize_t fakeLogWritev(int fd, const struct iovec* vector, int count)
 {
     /* Assume that open() was called first. */

(Sidenote; passing arrays by value is probably not good idea).

diff --git a/vold/ProcessKiller.c b/vold/ProcessKiller.c
index eeaae04..b8856ac 100644
--- a/vold/ProcessKiller.c
+++ b/vold/ProcessKiller.c
@@ -66,6 +66,7 @@ static boolean PathMatchesMountPoint(const char* path, const char* mountPoint)
     return false;
 }
 
+/* Ouch, this si going to eat a lot of stack. Does it work at all? */
 static void GetProcessName(int pid, char buffer[PATH_MAX])
 {
     int fd;

Buffer overflow in vold
~~~~~~~~~~~~~~~~~~~~~~~

Unfortunately you can only exploit it by putting overrly long
filenames to /dev/block.

diff --git a/vold/inotify.c b/vold/inotify.c
index a7b789c..db0a0f7 100644
--- a/vold/inotify.c
+++ b/vold/inotify.c
@@ -85,6 +85,7 @@ int inotify_bootstrap(void)
         if (de->d_name[0] == '.')
             continue;
 
+	/* Filename in /dev/block longer than 250-or-so characters, and boom you go */
         sprintf(filename, "%s/%s", DEVPATH, de->d_name);
 
         if (stat(filename, &sbuf) < 0) {


(sidenote: drop_caches does not do what you expect it to. It is debug
interface, and racy. And it takes '3', not 3, to do cache flushing).

static void DropSystemCaches(void)
{
    int fd;

    LOG_MOUNT("Dropping system caches\n");
    fd = open("/proc/sys/vm/drop_caches", O_WRONLY);

    if (fd > 0) {
        char ch = 3;
        int rc;

        rc = write(fd, &ch, 1);


-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blo...




to post comments

dev phone

Posted Feb 10, 2009 1:23 UTC (Tue) by tialaramex (subscriber, #21167) [Link] (2 responses)

Google does sell essentially the same phone but without the tampering by mobile telephone operators (of course this phone is not subsidised by the afore-mentioned operators and so it's expensive). Presumably the actual phones from Google give the owner root ?

dev phone

Posted Feb 10, 2009 2:28 UTC (Tue) by corvus (guest, #82) [Link] (1 responses)

Yes, you have root, and more importantly, the engineering bootloader which will let you flash any system image on to the device.

Unfortunately, buying an ADP1 is not ideal for everyone because:

1) The ADP1 was announced after the G1 was released, so early adopters never had the choice between the two.

2) Shipping (and handling) on the ADP1 outside of the US is enormously expensive. 200 USD to Canada for instance. The author is in the Czech Republic, so an ADP1 would probably cost him at least 600 USD, probably more.

So you can see the motivation for trying to get access to the "Open Source" phone he already has.

dev phone

Posted Feb 10, 2009 10:24 UTC (Tue) by fb (guest, #53265) [Link]

I don't know the __exact__ figures, but an Android dev phone would cost between 450 and 500 Euros in The Netherlands.

While here the total cost difference of a "sim-only contract" to a "2yr contract + G1" is 204 euros.

So, if you were already outside a contract, the "price" of an unlocked phone is about ~2.5x more expensive.

harder than you'd expect?

Posted Feb 10, 2009 1:34 UTC (Tue) by tialaramex (subscriber, #21167) [Link]

I accidentally PXE booted a few servers some months ago against a PXE server with a very, very old OS install image. So old that I had no idea what the root password was on the images it installed, and the servers were in a server room in another city. Without root privileges I could reboot them (remote power switch) but not wipe the disks so they'd re-install (the management chip annoyingly won't force a PXE boot on that model...)

I figured that since the OS image was ancient and I had a non-root local user on them, I'd be able to download a program that'd break into them and get me a root shell (and from there I'd wipe the disk and reboot, forcing a newer OS to be installed)

But I never found a working exploit. Admittedly I only had a short amount of time to spend on the problem before it made sense to send someone on a motorcycle to ride over and forcibly re-install them, but still they held up to a local attacker running a variety of exploits against a 2-3 year old kernel. Typically I'd get a segfault in userspace, or an Ooops in the kernel, but no root prompt. So this sort of "rooting your own box" isn't trivial.

Rooting your own phone: android security

Posted Feb 10, 2009 4:26 UTC (Tue) by jamesh (guest, #1159) [Link] (1 responses)

A number of the bugs seem to rely on creating 2GB long strings or arrays. I wonder how exploitable that is in real life if your attack vector is just the software already on the device and java programs downloaded onto the device?

I doubt it'd let you malloc() such a large string, and do you have enough control to mmap() files to produce a string that large?

Rooting your own phone: android security

Posted Feb 11, 2009 21:26 UTC (Wed) by ibukanov (subscriber, #3942) [Link]

> if your attack vector is just the software already on the device and java programs downloaded onto the device?

Any complex software has bugs. I would not be surprised if it would be easier to subvert a browser or JVM to execute arbitrary code than to get a root access from that code.

Rooting your own phone: android security

Posted Feb 10, 2009 8:24 UTC (Tue) by nix (subscriber, #2304) [Link]

GetProcessName() isn't passing an array by value: you can't do that in C,
as arrays decay to pointers in all situations (save sizeof). So this is
passing 'buffer' by reference, and noting for passing humans the maximum
size expected. (The compiler won't check this.)

Rooting your own phone: android security

Posted Feb 10, 2009 11:26 UTC (Tue) by csamuel (✭ supporter ✭, #2624) [Link] (1 responses)

On a more prosaic note the title of this article has rather a different meaning here in Australia and probably wouldn't result in the desired result.. :-)

Rooting your own phone: android security

Posted Feb 10, 2009 14:05 UTC (Tue) by clugstj (subscriber, #4020) [Link]

It does give a whole new meaning to the title, though!

Rooting your own phone: android security

Posted Feb 10, 2009 18:27 UTC (Tue) by hppnq (guest, #14462) [Link]

In the good old days this model allowed its users to become root through telnet. I suppose this particular vulnerability has been closed, but my guess would still be that userspace is easier to hack than the kernel.

Rooting your own phone: android security

Posted Aug 28, 2009 17:55 UTC (Fri) by Naguz (guest, #60500) [Link]

I assume the writer has found a solution by now, but for anyone that stumbles across this page, the solution is here. Note: I have not tried this myself (as I imported a UK G1), but know of very many who has tried and succeeded. And none that have failed.


Copyright © 2009, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds