660 likes | 868 Views
Pulling a John Connor: Defeating Android. Charlie Miller Independent Security Evaluators cmiller@securityevaluators.com. About me. Former National Security Agency First to hack the iPhone and Android G1 phone Won MacBook Air at Pwn2Own competition with Safari 0-day
E N D
Pulling a John Connor:Defeating Android • Charlie Miller • Independent Security Evaluators • cmiller@securityevaluators.com
About me • Former National Security Agency • First to hack the iPhone and Android G1 phone • Won MacBook Air at Pwn2Own competition with Safari 0-day • Author of “Fuzzing for Software Security Testing and Quality Assurance” • Author of “The Mac Hackers Handbook” • Due out in a few weeks
Outline • Phone hacking • Android security model • Attack surface • Bug hunting • Exploit dev • After access is achieved
Smart phone hacking is fun! • Small but capable computers • Always on • Always connected to the Internet (Wi-Fi, EDGE, 3G) • Cellular capabilities
Personal information • Contacts • Voicemail • Pictures and movies • Web credentials and cookies • Email and text messages • Calendar and events • GPS information
Good hacker asset • “Smart phone DOS” • Instant financial gain • 1-900 numbers, text messages, etc • GPS (contrast with random compromised box on Internet) • Listening device • Circumvent network security protections
Issues for defense • Typically no AV on phones • NIDS can be avoided with SMS • Hard to determine phone has been compromised • Tricky forensics • Phones go to Starbucks for a break
Android basics • Open source, free, mobile platform • One production phone runs it, T-Mobile G1 • Consists of OS, middleware, some applications • Linux kernel • Webkit based browser
Smart phone • 3G / WiFi / Bluetooth • Web browser • SMS/MMS messaging • Audio/video player • AOL IM client • GPS, integration with google maps... • etc
Security Architecture • Linux - traditional user id • Fine grained access controls
Linux based controls • Each application gets its own UID (unless specifically shared) • Application data is stored such that it is user readable/writable only (unless specifically shared) # ps ... radio 81 23 101936 19552 ffffffff afe0c534 S com.android.phoneapp_4 85 23 98352 19120 ffffffff afe0c534 S android.process.acoreapp_8 106 23 93732 14564 ffffffff afe0c534 S com.google.process.gappsapp_11 119 23 100048 14992 ffffffff afe0c534 S com.android.mmsapp_0 131 23 90540 14232 ffffffff afe0c534 S com.android.alarmclockapp_3 139 23 91668 15076 ffffffff afe0c534 S android.process.mediaapp_1 164 23 117732 25984 ffffffff afe0b23c R com.android.browserapp_18 308 23 93496 16016 ffffffff afe0c534 S net.gimite.nativeexeapp_19 701 23 91388 14448 ffffffff afe0c534 S charlie.mygpsmedia 4908 1 17280 4064 ffffffff afe0b45c S /system/bin/mediaserver
Access controls • Applications have install-time permissions associated with them • User is informed what permissions it will require and may accept or reject • “pm list permissions” • Otherwise SecurityException is (typically) thrown
Browser permissions $ ./adb pull /system/app/Browser.apk . $ ./aapt dump xmltree Browser.apk AndroidManifest.xml | grep 'permission\.' | cut -f2 -d\"com.google.android.googleapps.permission.GOOGLE_AUTHandroid.permission.ACCESS_COARSE_LOCATIONandroid.permission.ACCESS_DOWNLOAD_MANAGERandroid.permission.ACCESS_FINE_LOCATIONandroid.permission.ACCESS_NETWORK_STATEandroid.permission.ACCESS_WIFI_STATEcom.android.launcher.permission.INSTALL_SHORTCUTandroid.permission.INTERNETandroid.permission.WAKE_LOCK
Permissions in action • After browser exploit iduid=10001(app_1) gid=10001(app_1) groups=3003(inet) ls /dataopendir failed, Permission denied ls /data/data/com.android.providers.telephony/databases/opendir failed, Permission denied logcatUnable to open log device '/dev/log/main': Permission denied
Application Development • SDK with emulator freely available • All development done in Java • Only signed .apk (Java apps) may be run • May use self-signed certificate • Apps may run in the background
C and Android • Can write C/C++ apps with a gcc ARM cross-compiler • Some issues with non-standard libc (bionic) • Can’t do this in a Google supported way • Debugging sucks, SDK “debugger” is a Java debugger $ ./arm-2007q3/bin/arm-none-linux-gnueabi-gcc -static -o hello hello.c $ file hello hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), for GNU/Linux 2.6.14, statically linked, for GNU/Linux 2.6.14, not stripped # chmod 700 /data/busybox/hello# /data/busybox/helloHello world
Dynamically linking is harder • Download and build android source code (including bionic) • Use the prebuilt toolchain (for Linux or Mac OS X) • Use “agcc” wrapper to set all the flags you need • Get it from: http://plausible.org/andy/agcc $ ./arm-2007q3/bin/arm-none-linux-gnueabi-gcc -o hello hello.c # /data/busybox/hello/data/busybox/hello: not found $ ./agcc.pl -o hello hello.c # /data/busybox/hello hi
Tale of firmwares • RC19 - Original factory install (old Webkit bug) • RC28 - a few people got this before RC29 rolled out • RC29 - Fixed Webkit bug, had local root bug • RC30 - No more root • 1.1/RC33 - Feature upgrade, all bugs fixed ;) • RC7 - UK version of RC29 • RC8 - UK version of RC30 • ADP1 - Android Dev Phone 1.0 ~ RC28?
Flashing • Download firmware • https://android.clients.google.com/updates/signed-kila-ota-115247-prereq.TC4-RC19+RC28.zip • https://android.clients.google.com/updates/signed-RC30-from-RC29-fat.1582cace.zip • Put firmware on SD card as update.zip • Hold Home+End keys to enter system recovery • Alt-S to start installing firmware • http://forum.xda-developers.com/showthread.php?t=466455 • Found by DarkRift (January 2009)
Rooting your own phone • Flash the phone with RC29 • Exploit local privilege escalation bug • init.rc: • Upgrade to modified latest firmware • See: http://android-dls.com/wiki/index.php for details service console /system/bin/shconsole
Attack surface • Server side • Client side
Server side • Bluetooth, wireless, network stack, etc • Nothing listening on TCP/UDP :( • Sometimes you’ll see port 5555 - Android Debug Bridge (adb) # /data/busybox/netstat -anActive Internet connections (servers and established)Proto Recv-Q Send-Q Local Address Foreign Address Statetcp 0 0 127.0.0.1:5037 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:5555 0.0.0.0:* LISTEN tcp 0 0 10.0.2.15:5555 10.0.2.2:50587 ESTABLISHED
Client side - much nicer • Web browser • Email client • IM client • SMS/MMS • Multimedia player • Android Market apps • etc
Java - safety? • In theory these are all Java applications - and thus should be immune to memory corruption • However the JVM is built on top of many C/C++ libraries • Some API functions pass data to C/C++ daemons for processing
Android libraries • Bionic - custom libc implementation • openCore - multimedia functionality • SGL - image rendering • WebKit - HTML, JS rendering • All this is open source and C/C++
Bug hunting • Static analysis • Dynamic analysis
Static Analysis • Source code freely available • http://source.android.com/download • Can build, read, run through tools, etc
Browser File Formats • libsgl code is interesting (and buggy) • From external/skia/libsgl/ports/SkImageDecoder_Factory.cpp static const CodecFormat gPairs[] = { { SkImageDecoder_GIF_Factory, SkImageDecoder::kGIF_Format }, { SkImageDecoder_PNG_Factory, SkImageDecoder::kPNG_Format }, { SkImageDecoder_ICO_Factory, SkImageDecoder::kICO_Format }, { SkImageDecoder_WBMP_Factory, SkImageDecoder::kWBMP_Format }, { SkImageDecoder_BMP_Factory, SkImageDecoder::kBMP_Format }, { SkImageDecoder_JPEG_Factory, SkImageDecoder::kJPEG_Format }};
Read the source • Here is an indication of the code quality • from external/skia/libsgl/images/SkImageDecoder_libico.cpp bool SkICOImageDecoder::onDecode(SkStream* stream, SkBitmap* bm, SkBitmap::Config pref, Mode mode)... if (stream->read((void*)buf, length) != length) { return false; }... int offset = read4Bytes(buf, 18 + i*16); int bitCount = read2Bytes(buf, offset+14);
Fuzzing • The Android comes with an Emulator • QEMU-based, ARM processor emulated • Full Android stack • Not updated as frequently as devices • The WebKit bug still crashes the emulator • Can fuzz emulator or device
Emulator • Fuzzing the emulator is convenient • Don’t need device • Can stick it in VMware and snapshot it • Can even do exploit dev on it - to a point • If things get hosed do: ./emulator -wipe-data
ADB • Android debugging bridge • Allows to push files on off emulator/device • Gives shell on emulator/device • Gives root on emulator, “shell” on device • Can watch system logs
ADB in action >adb devicesList of devices attachedHT845GZ52307 device >adb shell$ iduid=2000(shell) gid=2000(shell) groups=1003(graphics),1004(input),1007(log),1011(adb),3003(inet) >adb logcatD/KeyguardViewMediator( 52): wakeWhenReadyLocked(82)D/KeyguardViewMediator( 52): handleWakeWhenReady(82)D/KeyguardViewMediator( 52): pokeWakelock(5000)D/SurfaceFlinger( 52): Screen about to return, flinger = 0x14f7e0D/dalvikvm( 52): GC freed 19203 objects / 913184 bytes in 256msV/WifiMonitor( 52): Event [CTRL-EVENT-DRIVER-STATE STARTED]
Fuzzing the browser • Fuzzing HTTP, Java Script, images, etc • Can be done with JavaScript Meta-Refresh action <html><body> <META HTTP-EQUIV="Pragma" CONTENT="no-cache"><meta http-equiv="refresh" content="2"> Image $test_case_number : <img src="/images/" . sprintf("%08d", $test_case_number) . ".$image_type"> </body></html>";
Watching for crashes • Use logcat to watch for crashes • Examples coming
Fuzzing Music Player • Fuzzing other apps requires actually launching them from the command line and directing them to the fuzzed test cases • Remember the apps are Java bytecode • Need to launch inside the virtual machine
Command line • Need action and component for application • Get this from AndroidManifest.xml from the .apk file $ ./aapt dump xmltree Music.apk AndroidManifest.xml | grep 'intent.action' | sort -u A: android:name(0x01010003)="android.intent.action.CREATE_SHORTCUT" (Raw: "android.intent.action.CREATE_SHORTCUT") A: android:name(0x01010003)="android.intent.action.EDIT" (Raw: "android.intent.action.EDIT") A: android:name(0x01010003)="android.intent.action.MAIN" (Raw: "android.intent.action.MAIN") A: android:name(0x01010003)="android.intent.action.MEDIA_BUTTON" (Raw: "android.intent.action.MEDIA_BUTTON") A: android:name(0x01010003)="android.intent.action.PICK" (Raw: "android.intent.action.PICK") A: android:name(0x01010003)="android.intent.action.SEARCH" (Raw: "android.intent.action.SEARCH") A: android:name(0x01010003)="android.intent.action.VIEW" (Raw: "android.intent.action.VIEW") $ ./aapt dump xmltree Music.apk AndroidManifest.xml | grep -B3 VIEW | grep name | grep -v VIEW A: android:name(0x01010003)="StreamStarter" (Raw: "StreamStarter")
Launch the app! #!/usr/bin/env pythonimport sys, os, time, subprocessadb="~/android/android-sdk-mac_x86-1.0_r2/tools/adb"logdump=[adb,"logcat","-d"]cmd=[adb,"shell","am","start","-a","android.intent.action.VIEW","-n","com.android.music/com.android.music.StreamStarter",sys.argv[2]] # Clear system logos.system(adb + " logcat -c") log=""cmdout = subprocess.Popen(cmd, stdout=subprocess.PIPE).stdoutstart=0testtime=int(sys.argv[1])/1000.0while(time.time()-start < testtime or start == 0): log= subprocess.Popen(logdump, stdout=subprocess.PIPE).communicate()[0] if(start==0): start=time.time() time.sleep(1)print log
An exploitable bug in RC33 • Notified Google on Jan 21, 2009 • 17 days ago • Still a 0-day in G1 phones • In libpvplayer.so (openCore) • In pvmp3_huffman_parsing() from pvmp3_huffman_parsing.cpp
The bug ... for (i = 0; (uint32)i < (grInfo->big_values << 1); i += 2)... grBits = part2_start + grInfo->part2_3_length; while ((pMainData->usedBits < grBits) && (i < FILTERBANK_BANDS*SUBBANDS_NUMBER - 4)) { pvmp3_huffman_quad_decoding(h, &is[i], pMainData); i += 4; } if ((pMainData->usedBits < grBits) && (i < FILTERBANK_BANDS*SUBBANDS_NUMBER)) { pvmp3_huffman_quad_decoding(h, &is[i], pMainData); i += 4;...
The bug (cont) • is is a uint array of size FILTERBANK_BANDS*SUBBANDS_NUMBER • pvmp3_huffman_quad_decoding writes dwords to is[i], is[i+1], is[i+2], is[i+3] • grinfo->part2_3_length is controllable • Get 2 dword overflow
Exploitable? I/DEBUG ( 9113): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***I/DEBUG ( 9113): Build fingerprint: 'generic/generic/generic/:1.0/119366/119366:sdk/test-keys'I/DEBUG ( 9113): pid: 9221, tid: 9226 >>> /system/bin/mediaserver <<<I/DEBUG ( 9113): signal 11 (SIGSEGV), fault addr e80e3cd0I/DEBUG ( 9113): r0 00000081 r1 00000003 r2 afe38678 r3 00043460I/DEBUG ( 9113): r4 e80e3cc4 r5 00000001 r6 00000018 r7 afe3863cI/DEBUG ( 9113): r8 40207cfc r9 afe35a88 10 a9d26e8d fp 00000001I/DEBUG ( 9113): ip afd010b0 sp 40307cc8 lr afe0da58 pc afe0a4e6 cpsr 80000030I/DEBUG ( 9113): #00 pc afe0a4e6 /system/lib/libc.soI/DEBUG ( 9113): #01 pc afd0095e /system/lib/libstdc++.soI/DEBUG ( 9113): #02 pc a7172aca /system/lib/libpvplayer.so Fuzzed mp3, crash in mediaserver Crashes while checking safe unlink Corrupt heap meta-data
Fuzzing greatest hits I/DEBUG (15993): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***I/ActivityManager( 51): Displayed activity com.android.music/.StreamStarter: 2173 msI/DEBUG (15993): Build fingerprint: 'generic/generic/generic/:1.0/119366/119366:sdk/test-keys'I/DEBUG (15993): pid: 15994, tid: 16021 >>> /system/bin/mediaserver <<<I/DEBUG (15993): signal 11 (SIGSEGV), fault addr fffd10e6I/DEBUG (15993): r0 00000087 r1 0003ac6c r2 0000021c r3 00000000I/DEBUG (15993): r4 00030740 r5 00000000 r6 fffd10da r7 0001406cI/DEBUG (15993): r8 40207bbc r9 afe35a88 10 a9d26e8d fp 00000001I/DEBUG (15993): ip a7572820 sp 40407e10 lr a7159fa1 pc a7159f68 cpsr 40000030I/DEBUG (15993): #00 pc a7159f68 /system/lib/libpvplayer.soI/DEBUG (15993): #01 pc a7159f9e /system/lib/libpvplayer.soI/DEBUG (15993): #02 pc a715dc40 /system/lib/libpvplayer.soI/DEBUG (15993): #03 pc a715d8ba /system/lib/libpvplayer.so fuzzed mp3, some control over r6
Fuzzing greatest hits r6 (bad - we have some control) - derefed, put in r0 r0 derefed, put into r3 r3 derefed, put into r1 branch (jump) to r1
Fuzzing greatest hits, FTW I/DEBUG ( 20): *** *** *** *** *** *** *** *** *** *** *** *** ****** *** ***I/DEBUG ( 20): Build fingerprint:'generic/generic/generic/:1.0/119366/119366:sdk/test-keys'I/DEBUG ( 20): pid: 365, tid: 365 >>> com.android.browser <<<I/DEBUG ( 20): signal 4 (SIGILL), fault addr 0027fe34I/DEBUG ( 20): r0 0027fdd0 r1 ac125670 r2 0027fe28 r3 001fd4c8I/DEBUG ( 20): r4 0027fdd0 r5 001c8888 r6 001fd44c r7 bed8c524I/DEBUG ( 20): r8 001fd418 r9 4104ad1c 10 4104ad08 fp 00000000I/DEBUG ( 20): ip 001fd44c sp bed8c510 lr ac05d564 pc 0027fe38cpsr 20000010I/DEBUG ( 20): #00 pc 0027fe38 [heap]I/DEBUG ( 20): #01 pc ac05d560 /system/lib/libsgl.so oops, the fuzzing testcase almost got control of the process by accident!
Exploit Dev • From an exploit perspective, the phone runs Linux on ARM • Bionic library uses Doug Lea malloc • Can use standard shellcode (almost) • Limited by application sandbox