Lately I have been doing some pentesting of android apps and I'm doing this blogpost mainly for documenting purposes, since there are quite a lot of pitfalls which made me utter an exotic variety of swearing words. A) Decompiling the source (luke) This was probably the easiest part. Android apps are written in Java and Java 'decompilers' have been around for a while. In fact, some of them seem to have disappeared (jad?). Anyway, Android apps come in .apk packages which can be unzipped. So, how do we get the .apk file? If we cannot download it via some site, we can use a regular android phone, install the app, and then back it up using an app called ASTRO file manager: http://www.androidtapp.com/astro-file-manager/ . In de tools section of ASTRO there is an option to backup apps, which are subsequently saved in /mnt/sdcard/backups/apps . From there we can copy it over to our computer. I assume you know how to unzip a file, so after the apk is unzipped, there's a couple fo files which are of interest. First there's the manifest file, which we can view using
java -jar AXMLPrinter2.jar AndroidManifest.xml
The other files are the so-called .dex (Dalvik Executable)files which contain the source-code. To be able to decompile dex files we need to convert them first. There's a tool for that called dex2jar : http://code.google.com/p/dex2jar/. It will convert our dex file to...hmmm...you guessed it, a jar file, which is also just a collection (java archive) of files. Now there are a couple of options to decompile this. I tried JDGUI which has a GUI and JAD (which seems to be a bit harder to find) which is a command-line tool. For JAD, you first need to unpack the archive. You can use something like
find ./ -name *.class | xargs -n1 -P1 ./jad -sjava
to decompile everything at once. Next, it's time to read the code, but this is not a java course...
B) Intercepting HTTP(S) with BurpSuite
This second part is much more interesting. We want to test our app with BURP, so we need to intercept traffic with our favorite intercepting proxy,. For our purposes we will be using the Android SDK. I will not elaborate on how to install the SDK, I assume that you will be able to do this. We simply create a new device by starting the emulator: ($SDKDIR/tools/android)
After we created the device, we stop the emulator. We need to do some stuff to make sure changes which we will perform won't get lost. We just created a device with API level 10. We need to copy the .img files over to the directory of the device we just created:
android-sdk-linux_x86$ cp platforms/android-10/images/* ~/.android/avd/android2.3.3./
Now we start up the device, using the emulator command and increasing the memory so the /system folder has enough place to write to:
tools$ ./emulator -avd android2.3.3 -partition-size 512
After we start the device, we can use the adb command to install our application .apk.
[email protected]:~/Downloads/android-sdk-linux_x86$ adb start-server [email protected]:~/Downloads/android-sdk-linux_x86$ adb devices List of devices attached emulator-5554 device [email protected]:~/Downloads/android-sdk-linux_x86/platform-tools$ adb install mesand.apk 1488 KB/s (485184 bytes in 0.318s) pkg: /data/local/tmp/mesand.apk SUCCESS [email protected]:~/Downloads/android-sdk-linux_x86$
We can verify if the installation succeeded by accessing the app in the applications on the emulator.
So how do we intercept http with BURP? To do this, we need to start the android virtual device with an extra option:
[email protected]:~/Downloads/android-sdk-linux_x86/tools$ ./emulator -avd android2.3.3 -partition-size 512 -http-proxy http://localhost:8080
Burp , we can just run it with default options. This is quite easy, but now it becomes interesting: We can intercept HTTPS traffic if we ignore the SSL popups. Burp is inserting it's own certificates and the browser alerts us that the certs are not valid. Most apps which use SSL however (apart from browsers), will verify the server cert and just fail if the cert is not correct. The solution is to add the PortSwigger CA to the list of trusted CA's inside the device's certificate store. I found some document by Mcafee security about pentesting android apps which goes into great detail explaining that this is not possible and then they proceed into injecting/changing the android API. Clearly they have more time than me: http://www.mcafee.com/au/resources/white-papers/foundstone/wp-pen-testin... As it happens, it is possible to change the cacerts.bks file and to add the PortSwigger cert. At first I found a description to do it manually, with keytool etc... but in fact it's way easier using the tools that I found here: http://intrepidusgroup.com/insight/2011/05/androidaudittools/ If you read this post, you will see why it was necessary to copy the img files. My initial problem was that, while I had no problem inserting the cacerts.bks, the file got overwritten after each reboot. Copying the img files solved that problem. We can extract the PortSwigger CA as described on the PortSwigger blog somewhere (google). Instead of extracting cacerts.bks from the device and modifying it manually with keytool, I used the tools I found on the above mentioned blog:(remember to install bouncycastle etc...) Adding the burp CACERT was as simple as:
./installcer.rb -c PortSwiggerCA.crt
(use the gem install command to install missing ruby libs) I could verify after a reboot that the file didn't get overwritten:
[email protected]:~/Downloads/android-sdk-linux_x86$ adb shell # ls -l /system/etc/security/cacerts.bks -rw-r--r-- root root 114621 2011-10-05 13:03 cacerts.bks
Now, I was slightly shocked when this didn't work:
At first I couldn't figure out what the problem was. Until I started looking closer at the certificate:
It seems that the device is issuing a HTTP CONNECT IPADDRESS for https instead of a CONNECT FQDN . This causes Burp to issue a certificate for IPADDRESS which then causes the browser to fail because it expects a certificate for FQDN. WTF? Yup: confirmed by a Android-dev blogpost: http://android-developers.blogspot.com/2011/09/androids-http-clients.html "We also made several improvements to HTTPS in Gingerbread. HttpsURLConnection attempts to connect with Server Name Indication (SNI) which allows multiple HTTPS hosts to share an IP address. It also enables compression and session tickets. Should the connection fail, it is automatically retried without these features. This makes HttpsURLConnection efficient when connecting to up-to-date servers, without breaking compatibility with older ones." Is this for real?? Ok, so how do we solve this? Well, luckily BURP has the option to use a fixed certificate for SSL.
Now it works.Bingo.
Sometimes it's possible to use wildcard certs as well ; e.g.: *.google.com
Hope this helps some people. This surely was a PITA.
Sorry if the url's are not linked; It's some WP bug.