Android Pentest Guide

Android Checklist:

Extract Manifest and Data from the apk:
  • aapt l -a target.apk
  • aapt dump permissions target.apk // Read permissions
  • aapt dump badging target.apk // Read version code
  • aapt list target.apk //The 'list' command shows the contents of the package
  • aapt list -v target.apk //the -v option is just like 'unzip -l -v'
Note: AAPT allows you to view, create, and update ZIP-compatible archives (ZIP, JAR, and APK). It can also compile resources into binary assets. It is the base builder for Android applications.

References:
Get the USB Android devices (Assumes USB debug enabled):
  • sudo apt-get install android-tools-adb android-tools-fastboot // Install adb tools
  • adb devices //list devices
  • adb -s <device> command //execute command over a specific device
  • adb shell // Get shell on device
  • adb root // Get root access - Not always
Log activity using adb logcat
  •  adb logcat ActivityManager:I com.app.dev.app_nam:D *:S
Note: As of Build Tools 21.0.3 this will no longer work as TAGS are restricted to 23 characters or less.

Drozer exploit lis tPull APK packaged from the emulator/device
  • adb shell pm list packages // Get package list
  • adb shell pm path com.example.someapp // Get app path
  • adb pull /data/app/com.example.someapp-2.apk path/to/desired/destination // package
Get system info (adb derived shell):
  • shell@android:/ $ getprop //get system properties
  • shell@android:/ $ dumpsys //dump status of all system information and services
  • shell@android:/ $ service list //List services
Note: Android Debug Bridge (adb) is a versatile command-line tool that lets you communicate with a device. The adb command facilitates a variety of device actions, such as installing and debugging apps, and it provides access to a Unix shell that you can use to run a variety of commands on a device.

Set system proxy (with adb reverse keyword):
  • adb reverse tcp:7777 tcp:8080 // Sends 7777 traffic to 8080
  • adb reverse remove tcp:7777 // Remove proxy
  • adb reverse remove --all // Remove all proxies
This sets up a reverse port forward on your phone, tablet, emulator, development device of choice, etc. Any request sent to port 7777 on your phone is forwarded over the USB cable to port 8080 of your development machcom.android.service
ine. The 7777 is the port number on your phone that you want to use. You can use any number you like as long as
  • it's anything from 1024 to 65536
  • it's not already in use by another app
Note: If you get the response "error: cannot bind to socket" try a different number.

Get the current SDK version:
  • adb shell grep ro.build.version.sdk= system/build.propro.build.version.sdk=25
Install Drozer Agent/Start Console USB mode:
  • adb forward tcp:31415 tcp:31415 // Setup port forwarding for Drozer
  • adb install /usr/lib/python2.7/dist-packages/drozer/lib/standard-agent.apk
  • drozer console connect
Start Console Infra mode:
  • drozer server start // infra mode
  • drozer console connect 768bcc409d0a0188 --server 0.0.0.0:31415
Note: Drozer allows you to search for security vulnerabilities in apps and devices by assuming the role of an app and interacting with the Dalvik VM, other apps’ IPC endpoints and the underlying OS.

Get info from Drozer:
  • run app.package.list -f target app // Find your target app
  • run app.package.info -a <package name> // Get package info
  • run app.package.manifest <package name> // Get manifest to check permissions
  • run app.package.attacksurface <package name> // Check attack surface
  • run app.activity.info -a <package name>  // Check activity info
  • run app.activity.start --component <package name> .ViewStatement // Test access control for activities
  • run app.package.list -p android.permission.READ_SMS // search for applications that requested an specific permission
  • run app.provider.finduri <package name> //find query paths of Content Providers of an APP
Get attack surface:
  • run app.package.attacksurface <package>
ADB alternatives to Drozer:
  •  adb shell am start -n <package>.LoginActivity // Start activity
Removing secrurity packages from the phone:

  • adb shell pm uninstall -k --user 0 com.android.service
  • adb shell pm uninstall --user 0 com.android.service
  • adb uninstall com.android.service

To Query content providers (file system):
  • run app.provider.read content://<package>.FileBackupProvider/etc/hosts
  • run app.provider.download content://<package>.FileBackupProvider/data
To Query content providers (inject path traversal):
  • run scanner.provider.traversal -a <package>
To Query content providers (inject SQL):
  •  run scanner.provider.injection -a <package> 
Inserting into Content providers:
  • run app.provider.insert content://<package name>.TrackUserContentProvider/trackerusers/ --integer id 2 --string name n3k
  • run app.provider.insert content://<package name>.DBContentProvider/Passwords  --integer _id 3 --string service Facebook --string username test --string password zA76WR9m --string email test@gmail.com 
Note1: Fragment Injection: All exported activities that extend PreferenceActivity and are running on Android 4.3 or prior are vulnerable. This attack was mitigated by Android in versions 4.4 onward by providing a new method in the PreferenceActivity class named isValidFragment() to allow developers to override it and validate which fragments can be loaded inside the activity. Performing poor validation on the fragment name supplied to this method or simply returning true in this method without performing any checks would still result in fragment injection attacks being possible.

Note2: Content providers were the only application component that was exported by default on Android, but this situation has since been amended in API version 17. Note that the default behavior is still to export a content provider if the android:targetSdkVersion is set to a value smaller than 17, and so these issues are still prevalent.

SQLmap Fuzzing content providers:
  • run use auxiliary.webcontentresolver
  • sqlpmap -u localhost

List applications sharing that UID
  • run app.package.shareduid -u 10005  
Auditing the whole application set:
  • run app.package.backup //looks for what applications allow to do backups of their data
Remote Loading of Code: 
- DexClassLoader (String dexPath, String dexOutputDir, String libPath, ClassLoader parent)

Find pre-installed applications that allow to install new packages:
  • run app.package.list -p android.permission.INSTALL_PACKAGES
Unprotected broadcast receivers
  • run app.broadcast.send --component <package>
Note: Applications can make use of the sendBroadcast()method and send broadcasts whose impact is determined completely by what code is run in the onReceive()method of the broadcast receivers that receive the sent intent. This applies in exactly the same way for broadcast receivers that have been registered at runtime using the registerReceiver()method. To discover broadcast receivers that have been registered at runtime you must search through the code of the application; drozer will not find them using the app .broadcast.info module.

Intent Sniffing

Intent sniffing is when a broadcast receiver can register to receive broadcasts that may have been intended for other applications. This is possible because some applications broadcast intents and do not define a required permission that a broadcast receiver must hold in order to receive the intent or do not provide a destination package for the intent.

Drozer exploits:
  • drozer exploit list
Drozer modules search:

  •  module search <module name>
Drozer modules install:
  •  module install <module name>
Note: The official drozer module repository is hosted alongside the main project on Github. This is automatically set up in your copy of drozer.

Editing APK packages:
  • Download Linux wrapper script (Right click, Save Link As apktool)
  • Download apktool-2 (find newest here)
  • Rename downloaded jar to apktool.jar
  • Move both files (apktool.jar & apktool) to /usr/local/bin (root needed)
  • Make sure both files are executable (chmod +x)
Decode apk: 
  • apktool d target.apk
Note: Backup AndroidManifesto.xml 

Search for content:
  • Search for URL(s): grep -r "http://"
  • Search for URL(s): grep -r "https://"
  • Search for URL(s): grep http ./st3.txt | sed 's/http/\nhttp/g' | grep ^http | sed 's/\(^http[^ <]*\)\(.*\)/\1/g' | grep IWANTthis | sort -u
  • grep -oE '\b(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]*[-A-Za-z0-9+&@#/%=~_|]'
  • Search for SSL Context: grep -r "SSL"
  • Search for Pinning: grep -r "pinning"
  • Search for Username: grep -r "username"
  • Search for Passwords: grep -r "password"
  • Search for Passwords: grep -r "tamper"
Load your APK to Bytecode app: http://www.java2s.com/Code/Jar/b/Downloadbytecode181jar.htm , then go Plugins Show all strings and search for usernames and passwords.

Edit/Encode apk:
  • apktool b target.apk -o out.apk // No troubleshooting
  • apktool -p empty_dir b target.apk -o out.apk 
  • zipalign apktool -p empty --use-aapt2 b  out patchd.apk  //When you get W: invalid resource directory name: 

Searching for certificate pinning

grep -r  "pinning" apk_decoded folder

Signing the apk with your Self-Signed Certificate
  • Open and remove the folder META-INF
  • Change the extension to .apk
  • Use the jarsigner and zipalign with your new keystore.
Extracting the certificate from the apk
  • Rename traget.apk to target.zip
  • Do grep -r CERT.RSA
  • Run openssl pkcs7 -in CERT.RSA -inform DER -print_certs -out cert.pem 
This is going to give you an idea how to create you own certificate so as the server to accept the fake one.

Extracted certificate:



Generate using open ssl your *.ks file

Using this guide: https://blogs.oracle.com/blogbypuneeth/steps-to-create-a-self-signed-certificate-using-openssl

Use apksigner to sign and verify the apk file

apksigner sign --ks keystore.jks app-name.apk

Certificate Pinning Way (Android 6 <) 

If the application we’re trying to MITM targets Android 6.0 or lower, we can simply add our CA to the user-added CA store. When the application validates the trust chain for our custom certificate, it will find our custom CA in the trust store and our certificate will be trusted. If the application targets Android versions later than 6.0, however, it won’t trust the user-added CA store. To get around this, we can edit the application’s manifest and force it to target Android 6.0. The targeted API level is specified in the ‘platformBuildVersionCode’ attribute of the ‘manifest’ element in the AndroidManifest.xml file.

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.test.app" platformBuildVersionCode="25" platformBuildVersionName="7.1.1">
The above manifest element targets ‘platformBuildVersionCode=25’, we need to change that to 23.

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.test.app" platformBuildVersionCode="23" platformBuildVersionName="6.0">
When the application is repackaged with this updated manifest, it will trust the user-added CA store.

Certificate Pinning Way (Android 7 > ) 

With the release of Android Nougat (Android 7) came a new security feature called Network Security Configuration.

This new feature arrived with the intention of allowing developers to customise their network security settings without modifying app code. Additional modification was also included in the default configuration for connections to SSL/TLS services; if the application targets an SDK higher or equal to 24, only the system certificates are trusted.

All of the above has an impact in the way an Android mobile application assessment is performed. If the HTTPS traffic needs to be intercepted, then a proxy certificate must be installed, but it is going to be installed in the ‘user certificates’ container, which is not trusted by default.


To modify the default configuration, an XML file that specifies the custom configuration has to be created on the resources directory. The piece of code below shows an example of a configuration file that uses the user certificates container for all HTTPS connections made by the application.

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config>
        <trust-anchors>
            <certificates src="system"/>
            <certificates src="user"/>
        </trust-anchors>
    </base-config>
</network-security-config>  

Additionally, the file has to be referenced from the Android Manifest file, which introduces the key android:networkSecurityConfig on the application tag, as shown here:

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application android:networkSecurityConfig="@xml/network_security_config"
                    ... >
        ...
    </application>
</manifest>
Certificate Pinning Other Resources

https://omespino.com/tutorial-universal-android-ssl-pinning-in-10-minutes-with-frida/
https://github.com/iSECPartners/Android-SSL-TrustKiller/releases/
https://cooltrickshome.blogspot.com/2018/11/ssl-pinning-bypass-on-android-emulator.html?spref=tw
http://www.security-assessment.com/files/documents/whitepapers/Bypassing%20SSL%20Pinning%20on%20Android%20via%20Reverse%20Engineering.pdf
https://blog.netspi.com/four-ways-bypass-android-ssl-verification-certificate-pinning/

References 

  • https://serializethoughts.com/2016/09/10/905/
  • https://warroom.securestate.com/android-7-intercepting-app-traffic/
  • https://www.nowsecure.com/blog/2017/06/15/certificate-pinning-for-android-and-ios-mobile-man-in-the-middle-attack-prevention/
  • https://android-developers.googleblog.com/2016/07/changes-to-trusted-certificate.html
  • https://www.nccgroup.trust/uk/about-us/newsroom-and-events/blogs/2017/november/bypassing-androids-network-security-configuration/
  • https://sensepost.com/blog/2018/tip-toeing-past-android-7s-network-security-configuration/
  • https://medium.com/@ved_wayal/hail-frida-the-universal-ssl-pinning-bypass-for-android-e9e1d733d29