1. Setup and Decompile
2. Verify Signing
3. Check for Hardcoded and URL endpoints
4. Digging into AndroidManifest.xml File
5. Network
6. Storage
7. Analyze the source code thoroughly specially on
8. Reverse Engineering
9. Cryptography
10. Exploiting backup
11. Exploiting Android Debuggable
12. Exploiting Exported Components with drozer
13. Intercepting HTTPS request on Java Based Application
14. Intercepting HTTPS request on Flutter Based Application
15. Testing APIs
16. References
17. More Resources
- Install the application on emulator or physical device
- View the package name of application with ADB
adb shell pm list packages | grep "app-name"
- View the path of the application.
adb shell pm path "package-name"
- Decompile the application with APKTOOL
apktool d app.apk
- Decompile the application with JADX
jadx /path/to/apk -d /path/to/output
- Check if the application has been properly signed.
apksigner verify --verbose app.apk
jarsigner -verify -verbose -certs app.apk- Hardcoded Emails
grep -HnroE '\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b' | awk -F: '{print $3}'
- Hardcoded AWS Keys
gf aws-keys
- Hardcoded IPs
gf ip
- Hardcoded Base64 data
gf base64
- Hardcoded usernames and passwords on the source code
- Hardcoded data on strings.xml ➡️ /res/values/strings.xml
- Hardcode encryption keys and secrets
- Hardcoded data on raw.xml ➡️ /res/values/raw.xml
- Hardcoded URL endpoints
gf urls
- Check if backup is enabled ➡️
android:allowBackup="true" - Check if debug mode is enabled ➡️
android:debuggable="true" - DeepLink ➡️ Check for deeplink schemas
- Permission ➡️ Check if application is asking unnecessary permission.
- Permission ➡️ Check if application is having permission like External Storage, SMS
- Check the exported activites, services, providers and receivers
- Intent Filter also makes components exported by default
- Task Hijacking ➡️ Check if
launchMode=singleTaskdefined - Check the Implicit and Explicit Intents
- Note down the interesting activites on the manifest file
- Check if HTTP is enabled ➡️
cleartextTrafficPermitted="true"
- Check the Network Security config file ➡️
/res/xml/network_security_config.xml - URL with HTTP protocol on the source code
- Find the URLs with
gf urland list the HTTP only - Or, with GREP ➡️
grep -iRn "http://"
- Find the URLs with
- Check if SSL pinning is enabled on the application or not
-
Shared Preferences
- Check if the shared preferences contains sensitive data unecrypted ➡️
/data/data/package-name/sharedprefs - World Writable - Check if the shared preferences is world writable
- World Readable ➡️ Check if the shared preferences is world readable
- MODE_WORLD_READABLE allows all applications to access and read the content of the file
SharedPreferences sharedPref = getSharedPreferences("key", MODE_WORLD_READABLE);
- Check if the shared preferences contains sensitive data unecrypted ➡️
-
SQLite Database
- Check if database contains sensitive information unencrypted ➡️
/data/data/package-name/files/
- Check if database contains sensitive information unencrypted ➡️
-
Firebase
- Check for firebase URL endpoint with
gf urlor on/res/values/strings.xml - Add /.json on the end of the URL
curl -X GET https://subdomain.firebaseio.com/.json- The endpoint will be vulnerable if it does not replies with
"error" : "Permission denied"
- The endpoint will be vulnerable if it does not replies with
- Check for firebase URL endpoint with
-
Internal Storage
- World Writable - Check if the internal storage is world writable
- World Readable - Check if the external storage is world readable
fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
- Analyse the data in internal storage
- Pull the internal storage without using (just after installation)
adb pull /data/data/package-name - Pull the internal storage after using (full feature usage)
adb pull /data/data/package-name - Analyze the difference
- Pull the internal storage without using (just after installation)
-
External Storage
- Application can store data externally on SD card or on internal (non-removal).
- Pull the external storage of the application and look for any sensitive information.
# locate the external storage of the app adb shell ls /sdcard/Android/data # Pull the external directory of the app adb pull /sdcard/Android/data/"package-name"
- File saved to external storage is World Readable which can be accessed by other apps.
File file = new File (Environment.getExternalFilesDir(), "password.txt");
- Search for Classes and Functions such as
MODE_WORLD_READABLEorMODE_WORLD_WRITABLE- the
SharedPreferencesclass (stores key-valu pairs) - the
FileOutPutStreamclass (uses internal or external storage) - the
getExternal*functions(use external storage) - the
getWritableDatabasefunction (returns a SQLiteDatabase for writing) - the
getReadableDatabasefunction (returns a SQLiteDataabase for reading) - the
getCacheDirandgetExtrernalCacheDirsfunction (use cached files)
- Check for HTTP caching (sensitive information) which is stored in Cache.db in internal storage
- Keyboard Cache
- Determine Whether the Keyboard Cache is Disabled for Sensitive Input.
- The keyboard cache file is located in:
/var/mobile/Library/Keyboard
<EditText android:id="@+id/KeyBoardCache" android:inputType="textNoSuggestions" />
- Login and Registration
- Password Forgot and Reset
- Activity which has implemented the intent defined on AndroidManifest.xml
- Encryption and Decryption
- Web API Intregation
- Transactions Related
- OTP Related
- Activity which has implemented webviews
- Database, Shared Preferences, Internal and External Directory Integration
- Build Configs
- Decompile
- Basic Decompilation
apktool d base.apk
- Decompile only resource
apktool d -s base.apk
- Decompile only source
apktool d -r base.apk
- If above give errors
apktool --use-aapt2 d base.apk
- Basic Decompilation
- Recompile
apktool b --use-aapt2 -o out.apk base
- Generate a key
keytool -genkey -v -keystore keys/test.keystore -alias Test -keyalg RSA -keysize 1024 -sigalg SHA1withRSA -validity 10000
- Sign the application
jarsigner -keystore keys/test.keystore dist/test.apk -sigalg SHA1withRSA -digestalg SHA1 Test
- Zipalign the application
zipalign -v 4 <YOUR_APP_NAME> app-release-final.apk
- Automate the signing and zipalign with uber-apk-signer
java -jar uber-apk-signer-1.2.1.jar -a out.apk
- Check if application is communicating with server encrypted or unencrypted
- Check if the private key secrets are being stored hardcode on the source code
- Check if the application is using Base64 for encrypting data for transmitting or storing ➡️
gf base64 - Check for depreciated algorithms like RC1, MD4, MD5 and SHA1 which causes collision issues
- Analyze the source code and workflow of the encryption technique
- Sometimes there might not be issues on hardcoding secrets, depreciated algorithm, but the implementation of the techniques might be done insecurely
- Check if the application has implemented their own custom cryptographic algorithm and try to reverse it.
- Check if application has backup enabled. If enabled, use following commands to extract internal storage even if the device is non-rooted.
# Look for backup on Manifest file
android:allowBackup="true"
# List the package name
adb shell pm list packages | grep "app name"
# Backup the data contained in the package.
adb backup "package-name"
# The file name will be backup.ab
# Convert .ab extension with android backup extractor.
Download link: https://sourceforge.net/projects/adbextractor/
# Convert .ab into tar
java -jar abe.jar unpack backup.ab backup.tar
# Extract the tar file
tar -xvf backup.tar
# Analyze the files in the extracted folder and look for directory like databases, shared preferences, files- Check if application has debuggable mode enabled. If enabled, use following commands to access the android shell as the vulnerable application even if the device is not rooted.
# Look for debuggable mdoe on Manifest file
android:debuggable="true"
# Before app start run,
adb jdwp
# It will list all the process ID of the running applications.
# After app start run,
adb jdwp
# The currently started application process ID can be identified.
adb shell ps | grep "ID-number"
# It will give the package name of the ID.
adb shell
run-as package-name
# Or,
adb shell pm list packages | grep "app-name"
adb shell
run-as package-nameSetup
- Download drozer app for android and PC from here.
- Install the applications on android and PC.
- Forward the port from PC
adb forward tcp:31415 tcp:31415- Open the drozer application on android device and click on ON button
- Launch the application
drozer console connectRetrieving Package information
- View the package name of the application
run app.package.list -f "app-name"- View the basic information of the package
run app.package.info -a "package-name"- View the Manifest information of the package
run app.package.manifest "package-name"- Identify the attack surface
run app.package.attacksurface "package-name"
# It will list all the exported activities, services, providers, broadcasts.Exported Activities
- Verify if unnecessary activities are exported and exploit it
run app.activity.info -a "package-name"
# It will list the exported activities
run app.activity.info -a "package-name" -u
# It will list all the activities
# Start the exported activity from drozer and see the result on android device
run app.activity.start --component "package-name" "component-name"Exported Content Providers
- Verify if any content providers are exported and exploit it
run app.provider.info -a "package-name"
# It will list the exported providers
run scanner.provider.finduris -a "package-name"
# It will list the URIs of the exported providers
run app.provider.query "uri"
# List the query on exported URIs
run app.provider.update "uri" --selection <conditions> <selection arg> <column> <dataa>
# Update the database using exported URIs- SQLi on Content providers
run scanner.provider.sqltables -a "package-name"
# List the tables
run scanner.provider.injection -a "package-name"
# Performs some basic SQLi- Path traversal on Content providers
run scaner.provider.traversal -a "package-name"Exported Broadcast Receivers
- Verify any exported broadcast receivers and exploit it
run app.broadcast.info -a "package-name"
# List the exported broadcast receivers
run app.broadcast.send --component "package-name" "component-name" --extra <type> <key> <value>
# Send data through exported broadcast receivers
run app.broadcast.sniff --action <action>
# Sniff the data through exported broadcast receiversExported Services
- Verify any exported services and exploit it
run app.service info -a "package-name"
# List the exported services
run app.service.start --action <action> --component <package-name> <component-name>
# Start the exported services
run app.service.send <package-name> <component-name> -msg <what> <arg1> <arg2> --extra <type> <key> <value> --bundle-as-obj
# Send data through servicesWith Frida
- Download and install frida
pip3 install frida-tools- Download frida servers according to your android architecture from here and rename it to frida-server
# View CPU architecture of the android device
adb shell getprop ro.product.cpu.abi- Download the certificate from burp and copy as cert-der.crt
- Push the server and certificate file to android
adb root # might be required
adb push frida-server /data/local/tmp/
adb push cert-der.crt /data/local/tmp/
adb shell "chmod 755 /data/local/tmp/frida-server"
adb shell "/data/local/tmp/frida-server &"- Download the SSL Pinning bypass script from here and save it as sslPinningBypass.js
- Change proxy on android device
- Long press on wifi
- Click on Advance option
- Change proxy to manual
- Enter your PC ip address
- Enter a random port (like 5567)
- Save
- Open the burp and Change the proxy option from 127.0.0.1:8080 to PC-IP:5567 (port number must be same)
- Grab the package name with
adb shell pm list packages | grep "app-name" - Run the script
frida -U -l sslPinningBypass.js -f "package-name" --no-pause- The application will open automatically and now the requests will be captured on burp
With Objection (works also on non-rooted device)
- Install Objection
pip3 install objection- Patch the apk with Objection
objection patchapk -s base.apk- If the above patch failed, follow here for manual patch of application using objection
- Installed the patched apk
adb install patched.pak- Proxy the android route into PC as described on frida section
- Setup burp as described on frida section
- Run the Application
- Run Objection explore
objection explore- Disable SSL Pinning
android sslpinning disable- Burp will start intercepting the packets
The use of Frida on bypassing SSL Pinning may not work on flutter. I also performed some exploitatio in libflutter.so file for injecting the memory address of the certificate checker. However it did not work as intended. Here is the reference for bypassing SSL Pinning on flutter application through the exploitation of libflutter.so file.
This is an alternative method for bypassing SSL Pinning in Flutter application.
Note: I have tested this method on few aplications with success but this might not work as well.
-
Requirements
- Genymotion: Android Emulator
- ProxyDroid: Since flutter appication ignores manual proxy configuration through wifi
- Burp Suite
-
Setup and Configurations
- Install ARM Translation tool on the device since flutter application and proxydroid may not work in genymotion since it is of x86 architecture.
- Click on the File Upload widget and INSTALL OPEN GAPPS
- Click INSTALL
- Wait for the package to be installed
- When done, you will be prompted to reboot the virtual device.
- (Optional) Open the Play Store and configure you account.
- Verify ARM Translation tools installtion
adb shell getprob ro.product.cpu.abilist # This command should return "x86,armeabi-v7a,armeabi" as the output. -
Download the Burp Certificate
-
Convert Burp Certificate into PEM format
- Android only accepts certificate of PEM format if needs to be installed as system certificate.
- We can convert the burp certificate into PEM format using openssl. More
openssl x509 -inform DER -in cacert.der -out cacert.pem openssl x509 -inform PEM -subject_hash_old -in cacert.pem | head -1 # Rename the PEM file with the output given by the second command mv cacert.pem <RandomAlphaNumeric>.0 # Example: mv cacert.pem 4a787b67.0
-
Push the certificate file into android application
- We need to push the certificate into /system/etc/security/cacerts directory inorder to install it as system certificate. But although having root access on the device, permission to write on system directory is denied. For this we need to remount the device.
adb root adb remount # Push the file adb push 4a787b67.0 /system/etc/security/cacerts/ # If the above command still throws error. Consider pushing it into the sdcard at first. adb push 4a787b67.0 /sdcard/Download/ adb shell mv /sdcard/Download/4a787b67.0 /system/etc/security/cacerts/ # Change the permission of the file (inside adb shell) chmod 644 /system/etc/security/cacerts/4a787b67.0 # Reboot the device (inside adb shell) reboot
- Verify the certicate installation by navigating to installed certificates on android device through settings. Should list Portswigger CA.
-
Install and Configure the ProxyDroid aplication on the device
-
Since the flutter application ignores the proxy configured through wifi options, proxydroid must be installed.
-
Download Link is here
-
Open the application
- Enter the IP address of your computer (which intercepts the traffic) on the host parameter and a random port number and enable the proxy.
- Remove the custom proxy from the Wifi advance option if you have configured previously.
-
Burp's Things
- Open the Burp
- Go To: Proxy ➡️ Options ➡️ Add ➡️ Request handling
- Enter the previously entered host and port from proxy droid
- Click on Support invisible proxying.
-
Save the configuration, and you will be able to intercept the traffic of the flutter application
- Please follow this for API Pentesting Checklist