There are a lot of benefits to the Android ecosystem for mobile app development but some of those most relevant to bug bounty hunters are the information security protections that Android provides. Developers and hardware manufacturers leverage these platform-level capabilities to provide the security features that users have come to expect, without having to reinvent the wheel in the process. A few of the key Android platform security features are:
While one advantage of leveraging the Android platform-level security features is that developers don’t have to dig into the nitty-gritty details of implementing these features, this can be a double-edged sword. As with many things in the security field, a lack of familiarity can quickly open the door to implementation mistakes and, subsequently, vulnerabilities.
At a high level, most vulnerabilities can be distilled down to:
So, as bug bounty hunters, our goal is to identify the assumptions being made by application and system creators and then craft conditions that undermine these assumptions to achieve a security impact. With that in mind, it’s helpful to start by considering how developers’ use of Android platform-level security features can lead to assumptions that we might be able to undermine. A few examples that we’ll look at today include:
Let’s take a quick look at how we can invalidate some of these common developer assumptions.
Tools and techniques for stripping certificate pinning from Android mobile apps have been around for quite some time. However, the process has historically been manual, cumbersome, and error prone. Typically, this involved unpacking the APK, searching the smali code for hooks that perform certificate pinning, manually editing the smali code to bypass these code paths, and the repackage the APK to side-load on the mobile device.
Now-a-days, thanks to a significant contribution to the community by shroudedcode, we have a new tool to add to our Android hacking toolbox that greatly simplifies the process of stripping certificate pinning from Android apps. In fact, with the apk-mitm NodeJS package, this process is now reduced to a one-liner. The apk-mitm GitHub page details the perquisites necessary to get the tool setup, which essentially just consists of installing Node and then running:
Once it’s installed, we can strip certificate pinning from any APK using the one-liner depicted below. Once completed, we can then sideload the patch APK by running:
While the Android platform-level per-app isolations security features are effective at preventing one malicious app from accessing the private data of other apps on a user’s mobile device in the field, as bug bounty hunters we can still bypass these features to gain insight into a target app’s internal workings and potential use and/or disclosure of sensitive information. In many cases, bug bounty hunters are challenged with testing black boxes, where limited information about the target’s internal operations are known to the hacker. In these instances, we can apply deductive reasoning to glean information about what the device might be doing internally, but such hunches are still mostly guess work.
Wouldn’t it be nice if we had a way to peek behind the veil and see how the app is actually working behind the scenes? That’s exactly what we’ll achieve in the steps below. Let’s presume we have downloaded and installed a release build mobile app from the Google Play store and we’re tasked with performing a mobile app penetration test against the app.
We’ll start by listing the packages installed on the mobile device using the command
adb shell pm list packages -f | grep -i app-name
And here we can see I’ve installed a demo app called nerdwell.levelupx.demo
Next, we copy the target app’s APK from the mobile device using the command
adb pull /data/app/path-from-pm-list-packages-output
Next, we uninstall the release build of the target app from our mobile device because in the end, we’re going to side load a debuggable version and we’ll encounter namespace problems if we don’t first uninstall the existing version.
adb uninstall nerdwell.levelupx.demo
We then unpackage the APK copied from the mobile device using the below command, which extracts the contents of the base.apk file into a new folder named “extracted_apk.”
java -jar ./apktool.jar d -o extracted_apk ./base.apk
Now we edit the AndroidManifest.xml file in the extracted_apk folder and set the android:debuggable=”true” flag.
NOTE: In most release build apps, the AndroidManifest.xml will not include android:debuggable=”false” as is depicted below. If this flag is present, we can just change false to true; otherwise, we must add the entire android:debuggable=”true” flag.
Change
to
Next, we will repackage the APK for deployment to our test mobile device, which requires us to generate a Java keystore using the command: keytool -genkey -v -keystore resign.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
We then use the apktool.jar tool to rebuild our debuggable APK using the command, which creates a new APK called nerdwell.levelupx.demo–debuggable.apk from the contents of the “extracted_apk” folder.
java -jar apktool.jar b -o nerdwell.levelupx.demo–debuggable.apk ./extracted_apk/
Next, we sign the new APK and prepare it for deployment to our test mobile device using the command, which produces an APK named nerdwell.levelupx.demo–debuggable-aligned-signed.apk.
java -jar ./uber-apk-signer.jar -a ./nerdwell.levelupx.demo–debuggable.apk -ks resign.keystore -ksAlias alias_name
Lastly, we’re now ready to side load our debuggable version of the target APK to our test mobile device using the command: adb install ./nerdwell.levelupx.demo—debuggable-aligned-signed.apk
Once this has been completed, we can access the app’s private data from “adb shell” by using the “runas nerdwell.levelupx.demo” command.
As demonstrated in the below screenshot, this can help us to identify everything from hardcoded API keys to localStorage of sensitive session tokens.
Picking up where the prior demo leaves off, we might find that it would be helpful to pull the target app’s private data folder over to our Mac or Linux PC to take advantage of our full suite of hacking tools. However, in attempting to do so, you will find that once you switch contexts to the mobile app user (via the “runas” command), you’re unable to write to the external storage (/sdcard/), even if the app has the WRITE_EXTERNAL_STORAGE permission.
Fortunately, we can use tar and a feature of the xxd tool to extract the mobile app’s private data folder as a .tar file onto our Mac or Linux PC. The command to do so is adb shell “run-as nerdwell.levelupx.demo xxd /data/user/0/nerdwell.levelupx.demo/private_data.tar” | xxd -r >private_data.tar
Nerdwell is a systems and security engineer with a passion for bug bounty and vulnerability research. He currently works in critical infrastructure protection and has experience supporting technology in a variety of industries, ranging from manufacturing to healthcare. With over 20 years’ experiences, Nerdwell understands firsthand the challenges of building and supporting complex technology solutions securely. In addition to finding bugs and performing security research, Nerdwell enjoys networking and sharing knowledge with fellow hackers.
Every minute that goes by, your unknown vulnerabilities leave you more exposed to cyber attacks.