📒Android

📕 Course Topics

  • Techniques include reverse engineering, static analysis, and dynamic analysis

  • Android application attack surface and vulnerability exploitation

    • Android OS fundamentals

    • APK Building process

    • Testing environment

  • Attacking Android apps

    • Reverse engineer APKs for information gathering

    • Device rooting and understanding the entire attack surface

    • Mobile application traffic analysis

  • Static analysis module

    • Exploitation of SQL injection and Path traversal vulnerabilities

    • Identification of vulnerable activities, receivers, services, and insecure shared preferences

  • Dynamic analysis module:

    • ADB for live debugging and database interaction


AOSP Architecture

AOSP software stack architecture - https://source.android.com/docs/core/architecture

Each layer of the Android operating system platform has a specialized set of functionalities.

  • System Applications - core system apps (email, messaging, calendars, contacts, ...)

  • Java API Framework - full feature-set of Android dedicated Java APIs

  • Native C/C++ Libraries - required native C/C++ libraries for Android system components and low-level processes (e.g. ART, HAL)

  • Android Runtime - virtual machines for each app (ART), core libraries (Java)

  • Hardware Abstraction Layer (HAL) - provides interfaces to expose device hardware capabilities using multiple library modules

  • Linux Kernel - hardware (drivers), memory, processes, power management

The Android software stack - https://developer.android.com/guide/platform

Android virtual machines are abstraction layers between an application and the Android device.

Android apps are written in Java, compiled into DEV (Dalvik EXecutable) bytecode. The Android VM runs the DEX bytecode directly compiled from the original Java. ART has more optimization features than the Dalvik VM.

  • DEX, ODEX, OAT

Native code can be used as well, instead of Java code.

Dalvik vs ART runtimes

Android Security Module layers:

  • UID Separation (installed apps isolated from one another)

  • App's security layer

Each app has a specific UID (User ID) - identity of the app. The app can access only owned files.

The Android Application Sandbox restricts access to its data by using Linux permissions, allowing only the app itself, OS specific components or the root user to interact with it.

  • implemented in the OS

  • separation of files and code execution between apps

  • each application runs a separate process under separate UID

  • SELinux was implemented with Android 5.0 - more secure than only UID Separation

adb shell to a rooted Android device and check the app's UID ownership:

  • Permissions declared in the app's AndroidManifest.xml file can translate into Linux file system permissions. Check /sdcard permissions.


Test Environment - Android Studio

During testing, one can utilize either an emulated Android virtual device or a physically rooted device.

  • Android Studio can be used for testing and debugging over an ADB connection to a real device.

❗️ Please be aware that the source code resources (from INE) for this course lab cannot be compiled in Android Studio due to the use of an outdated Gradle version, and upgrading is not feasible.


  • Compilation, Packaging, Signing

Compilation

  1. aapt -> R.java + .java + .aidl + app source code

  2. Java Compiler -> .class

  3. dex -> classes.dex files

  4. apkbuilder -> .apk

  5. Jarsigner -> signed .apk

  6. zipalign -> signed and aligned .apk

Packaging - APK Structure

.apk is a compressed archive containing the app resources and code.

  • apktool - A tool for reverse engineering Android apk files

e.g. MSTG-Android-Java

AndroidManifest.xml

Classes.dex - a file in that contains the compiled bytecode of the Java source code used by the app.

/assets folder

  • HTML, fonts, mp3, text, image files

/lib folder

  • libraries and precompiled code

  • Linux shared object .so files (dev/third-party libraries)

    • the execution of forged .so files results in arbitrary code execution

/META-INF folder

  • app integrity and authenticity files

    • CERT.RSA - developer's signing certificate

    • CERT.SF - resources + hashes

    • MANIFEST.MF - resources and their SHA1

/res folder

  • resources not compiled into the resources.arsc file

While conducting an audit, be sure to review all source code files to assess their impact on the security of the application.

Code Signing

The APK signing process is essential for maintaining the security, integrity, and trustworthiness of Android applications throughout their lifecycle, from development to distribution and updates.

  • Validation of the identity of the author

  • Ensure code integrity

APK validation process v4 - source.android.com
  • Developers create a keystore, containing cryptographic keys, specifying a private key for signing and a public key for verification - keytool

  • The developer uses the private key from the keystore to sign the APK - jarsigner

  • This process generates a digital signature for the APK, ensuring its integrity and verifying that it comes from a trusted source.

  • e.g. with the CERT.RSA file

MANIFEST.MF contains the hashes of the files themselves.

CERT.SF contains the hashes of the line of the MANIFEST.MF.

📌 Signing Private key must be protected to prevent compromise.

The signed APK must be aligned to optimize its structure for efficient installation on Android devices and enhanced overall performance.


Reversing APKs

Reversing APKs refers to the process of decompiling, analyzing, and understanding the contents of a compiled application, from its original source code.

  • Code understanding

  • Security analysis

  • App's logic

  • Useful during black-box security assessment

apktool

apktool - A tool for reverse engineering Android apk files.

e.g. - decompile example.apk

apktool d example.apk

dex2jar

dex2jar - Tools to work with android .dex and java .class files.

  • Convert classes.dex to .jar files

JD-Gui

JD-Gui - a standalone graphical utility that displays Java sources from CLASS files.

e.g. - open and inspect example-dex2jar.jar into JD-gui

  • Save All Sources to save all the decompiled files into a zip archive

example-dex2jar.jar

Smali / Backsmali

  • Android bytecode is in .dex format, that can be converted/disassembled into the smali code (assembly language).

  • smali is easier to understand than the bytecode.

smali/backsmali - assembler/disassembler for the dex format used by dalvik, Android's Java VM implementation.

  • Disassemble an app with backsmali, modify it and reassemble it with smali (app must be signed again).

e.g. BuildConfig.smali

Bytecode Viewer

Bytecode Viewer - lightweight user-friendly Java/Android Bytecode Viewer, Decompiler & More.

jadx

jadx / jadx-gui - Command line and GUI tools for producing Java source code from Android Dex and Apk files.

Main features:

  • decompile Dalvik bytecode to java classes from APK, dex, aar, aab and zip files

  • decode AndroidManifest.xml and other resources from resources.arsc

  • deobfuscator included

jadx-gui features:

  • view decompiled code with highlighted syntax

  • jump to declaration

  • find usage

  • full text search

  • smali debugger, check wiki page for setup and usage

  • Open the .apk


🧪 Practice Lab 1

e.g. - LocatingSecrets app debug

  • app-debug.apk is inside the /LocatingSecrets/app/build/outputs/apk/ directory

Check the AndroidManifest.xml

AndroidManifest.xml
  • android.permission.INTERNET is required - app contacts a remote server

  • Access (MAIN activity - seen at app start), Files activities are used

  • Or open the app-debug.apk with Jadx-Gui

    • dex code is being automatically decompiled to java classes (pay attention to the decompiled code)

  • Opening out_LocatingSecrets.jar, onCreate method can be found with resource id of R.layout.activity_access

    • this id value can be found in the R file

jadx-gui
Access.class
  • res/layout/activity_access.xml - these elements build the first activity interface

activity_access.xml

The ACCESS button calls the access method

  • Gets and stores the input value into the code

  • This value is called and sent to the Files activity

Access.class

Open the Files.class file and analyze the onCreate method

  • username and password are stored separately from the source code, in the string class

  • check res/values/strings.xml for the 2 parameters values (hard-coded credentials)

  • extra: using the 5v3f4g string, will access more files


🧪 Practice Lab 2

e.g. - BypassSecurityControls app debug

  • Review app's functionality, decode, decompile the app, extract critical information, identify how the PIN is calculated, access the restricted area

AndroidManifest.xml

AndroidManifest.xml
  • ELSApp - main activity

  • Admin - page accessible only with code

  • Verify - insert the code here

Verify.class - access method

Verify.class
  • editText - retrieve input

  • str1 - manipulated string

  • str3 - device ID, cut to 5 chars

  • str4 - user's value

  • str5 - value defined in the string Resources at strings.xml

At each iteration, the app appends to str1 the char at position i of the strings str3 and str5, in a sequence of pairs repeating 5 times.

The input string (str4) is compared with the manipulated string (str1). If they match, an activity is started for the Admin class.

strings.xml - find the str5 value under the node seed

  • check the value in the res/values/strings.xml - 5f247F

strings.xml

At the fifth iteration of the for statement, str1 will contain 5f247F.

Access the Admin area using 5f247F - not working on a physical device.

tm.getDeviceID is a number specific to the phone, IMEI / MEID HEX.

  • (This method was deprecated in API level 26)

  • e.g. In this case, using the first 5 chars of the IMEI (e.g. 35950) and the 5f247F string, the str4 must be: 53f5294570 and the actual code only 5 chars long is not working since the used phone has no call permission and getDeviceID is not working.

  • Since the dev_id_complete = 0000000000 the actual working code is 50f02


Obfuscation

Obfuscation is the process of deliberately making source code difficult to understand or reverse engineer.

  • Minifying code involves compressing and optimizing it by removing unnecessary elements like whitespace, comments, and unused code, enhancing efficiency and reducing the app size

  • Obfuscation does not guarantee security against skilled reverser

  • e.g. ProGuard can alter class, field and method names assigning them meaningless values

Obfuscated apk Example - opened with Jadx-gui
apktool.yml

Hardware Optimization

Hardware optimization in mobile apps involves enhancing the utilization of a device's hardware resources to improve performance, efficiency and user experience.

  • .odex (optimized dex) - specific to hw platform, for pre-installed apps

OEM Apps

OEM Apps are pre-installed by the AOSP ROM, device manufacturer, cell phone provider.

  • usually located in the /system/app directory and commonly run with system / root permissions


🧪 Practice Lab 3 - Reversing Applications

🔗 AndroGoat App

Download AndroGoat.apk and open it with Jadx-Gui.

  • In the AndroidManifest.xml file check

    • android:exported="true"

    • Activities

    • Permissions

    • Intents

  • classes.dex is already decompiled from dex to jar by Jadx.

    • check some of the Java classes inside owasp.sat.agoat

    • check for hardcoded strings, misconfiguration, code vulnerabilities

    • use Search tool

    • methods (onCreate, onReceive etc)

  • e.g. ShowDataReceiver class

    • The provided code snippet contains a BroadcastReceiver in Android named ShowDataReceiver that in the AndroidManifest.xml file has the attribute android:exported="true", meaning that ShowDataReceiver is exported and can be invoked by other apps

    • The Toast.makeText method includes a hardcoded message that reveals sensitive information - exposed credentials in app's code.

SMALI Code Review

  1. Class Definition:

    • The class is defined as Lowasp/sat/agoat/ShowDataReceiver and extends android/content/BroadcastReceiver.

  2. Constructor:

    • The constructor is defined to call the constructor of the superclass (android/content/BroadcastReceiver).

  3. onReceive Method:

    • The onReceive method is implemented, which is invoked when the BroadcastReceiver receives a broadcast.

    • It takes two parameters: context (of type Landroid/content/Context;) and intent (of type Landroid/content/Intent;).

  4. Annotations:

    • The Smali code includes metadata annotations (Lkotlin/Metadata;) generated from the Kotlin source code.

    • Annotations provide additional information about the Kotlin class, including its structure and methods.

  5. Toast Message:

    • The onReceive method creates a Toast message displaying the hardcoded string "Username is CrazyUser, Password is CrazyPassword and Key is 123myKey456"

  6. Parameter Checking:

    • Parameter checking is performed using the Intrinsics.checkParameterIsNotNull method to ensure that the context and intent parameters are not null.

  7. Initialization:

    • The onReceive method initializes a Toast message and shows it using the makeText and show methods, respectively.


Network Traffic

TLS - All network requests from a mobile app should be using encryption, HTTPS (HTTP over TLS).

Good cryptography provides confidentially, integrity and authenticity.

  • Authenticity provided by x.509 (a standard defining the format of public-key certificates) certificates

  • Established organizations digital identity - prevents Man-in-the-Middle attacks

  • CSR (Certificate Signing Request) - an applicant sends a message (with the public key, identifying info and proof of authenticity) to the CA (Certificate Authority) of the PKI (public key infrastructure) in order to apply for a digital identify certificate. The CA verifies the real-world identity of the applicant.

    • The certificate validates the digital identity in the format of DNS hostnames (CAA).

    • With new the signed certificate, the applicant can present it to its software clients requesting identity verification

    • A Certificate Authority (CA) is a reliable third party. Each application maintains a list of authorities linking CAs to their unique public keys, dedicated solely for the purpose of certificate signing.

  • Validation

    • Identity stated in the certificate has to match the DNS hostname requested (wildcard match, etc), checked via Subject's Common Name

    • Verify proper certificate signing by CA in the trusted CA list

    • Period of Validity

Testing environment servers might lack valid certificates for the testing domains; however, this insecure configuration should not be deployed to the public or production environment.

  • Applications lacking proper certificate validation expose users to vulnerabilities. To exploit network weaknesses, an attacker positioned between the user and the site being accessed often manipulates ARP or DNS responses, causing traffic to be routed through the attacker's network.

  • Lack of hostname validation can be exploited by the attacker with a certificate signed by a CA trusted by the device

  • If case of CA not validated, the attacker can make and sign his own certificate

From the static analysis we can check when developers disable certificate validation, e.g. :

  • Creating an X509TrustManager that trust all certificates (invalid too)

  • Creating an insecure HostNameVerifier allowing all hostnames

Proxy

🔗 BurpSuite

🔗 Zaproxy

  • Device - Manual proxy configuration on the device is necessary, to get the traffic through a pentester's proxy.

  • Host - configure the Proxy Listener to accept connections from on all the interfaces (not just the loopback 127.0.0.1).

BurpSuite

The host and the device must be on the same network and able to communicate with each other.

  • To intercept HTTPS traffic using BurpSuite, the proxy's (e.g. BurpSuite "Portswigger CA") certificate must be trusted by the device (copy it to device and install from local storage)

  • Once the certificate is installed, HTTPS traffic is visible in the proxy (without certificate pinning implemented)

  • ❗️ User installed CAs (proxy's certificate for example) are no longer trusted by default for apps with API Level 24+ (Android 7.0+)

  • Network Security Config can be used to customize the app's network security settings, and trust a custom set of CAs, implement certificate pinning, cleartext traffic opt-out, etc :

    • Decode the app (apktool)

    • Add network_security_config.xml to res/xml app's folder

    • Add the non-public/self-signed CA certificate (PEM or DER format), to res/raw/certname app's folder

    • Repackage and sign the app


🧪 Practice Lab 4

Objectives

  • Understand and reproduce common certificate validation vulnerabilities

  • Reverse apps and locate certificate validation vulns in the source code

Install the app.

Capture network traffic with a proxy (Zaproxy, BurpSuite).

  • com.outlook.apk - HTTPS traffic visible, Outlook is trusting all certificates.

    • 📌 even with a CA-signed certificate with a specific hostname or without a trusted certificate installed, this vulnerable Outlook app does not perform any kind of hostname validation or trusted CA check

  • com.ubercab - HTTPS traffic not captured and app errors "Network error"

Decode and decompile the apps.

📌 Open com.outlook.apk with Jadx-GUI

Check for HostNameVerifier misconfiguration.

  • Search for ALLOW_ALL and check the Connectivity class

  • This insecure aVar.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); implementation is the cause of the certificate validation vulnerability

  • Search for com.microsoft.live.AuthorizationRequest Class

AuthorizationRequest
  • This code is part of a WebView implementation, specifically within the onReceivedSslError method. This method is typically called when there is an SSL error during the loading of a web page over HTTPS. The SSL error is being ignored by calling handler.proceed() without any further checks or validations, and this might allow the WebView to continue loading the page despite SSL errors.

📌 Open com.ubercab.apk with Jadx-GUI

Check the UBTrustManager class for certificate validation vulnerabilities, and HostNameVerifier for host name validation issues.

  • This UBTrustManager defines a custom X509TrustManager named UBTrustManager that lacks proper certificate validation. The checkClientTrusted and checkServerTrusted methods do not contain any validation logic, making the trust manager susceptible to accepting any certificate without verification. This exposes the application to potential man-in-the-middle attacks

Check for HostNameVerifier misconfiguration.

  • Search for HostNameVerifier and check the com.google.api.client.http.apache.TrustAllSSLSocketFactory class

  • The class uses SslUtils.trustAllSSLContext() to obtain an SSLContext that trusts all certificates, effectively disabling SSL/TLS certificate validation.

    • The setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER) method is called, disabling hostname verification. This allows connections to hosts with different names than the one to which the certificate was issued

  • e.g. Mitigations:

    • Implement proper certificate validation checks instead of blindly trusting all certificates.

    • Enable hostname verification to ensure that the certificate matches the host.


Certificate Pinning

Certificate pinning is a security mechanism where applications validate a server's certificate against a predefined trusted set of certificates, public keys or issuers.

  • Prevents MITM attacks

  • In Android apps, certificates can be hardcoded, restricting the accepted certificates to a predefined set. Certificates/public keys must be knows and installed on the servers.

By pinning to a specific certificate/public key, all other certificates/public keys will be refused during the LS handshake.

  • A list of certs/keys should be pinned in the app and in the event of compromise, remove only the compromised one from the list.

  • Ensure protected backup certs/keys

  • Only trust a single CA

To test an app with certificate pinning implemented, it must be disabled by

  • reverse engineering and patching the certificate validation procedure class at .smali files level, repackage the app and install it

  • using Frida/Objection tools for SSL Unpinning


🧪 Practice Lab 5

Objectives

  • Understand cert pinning, its implementation and bypass

  1. The PinTester lab app pins the certificate for https://www.elearnsecurity.com to a specific public key, using a library that pins by comparing a hex-encoded hash of an X.509 certificate's SubjectPublicKeyInfo field containing the public key. This exact public key (expected in the TLS handshake) has been hardcoded into the application.

Open PinTest.apk with Jadx-GUI and search for X509Certificate.

Open the org.thoughtcrime.ssl.pinning.PinningTrustManager class.

  • Static Pins: The public key pins (pins) are hardcoded in the PinningTrustManager constructor, limiting the app to accept only these specific certificates.

    • The constructor takes an array of strings (pins) representing the hexadecimal representation of public key hashes. These values are then converted to byte arrays using the hexStringToByteArray method and added to the pins list. The pins in this list are later used for comparison during the certificate pinning process in the isValidPin method.

  • SHA-1 Algorithm Usage: The code uses SHA-1 for hashing the public keys, which is considered weak and deprecated

  • No Pin Expiry Check

Check the MainActivity class for pins string.

Extract the remote's server certificate.

  • Create a new Python script to generate SPKI pin hashes from X.509 files (based on the pin.py - moxie0 tool).

    • ❗️ This method is considered insecure due to vulnerabilities of SHA-1 used in the script without any salt, making it vulnerable to collision attacks. Use it only for testing environment like this laboratory.

Today's certificate Pin Value is not equal to the hardcoded one.

Decompile, modify the string to c19e11308c73545ab7814fae1ebde8ad8f73ed1 in the MainActivity.smali file, recompile, sign and reinstall apk.

  • Testing the app, it crashes with FATAL EXCEPTION: AsyncTask #1 java.lang.RuntimeException: An error occurred while executing doIn Background() - I won't continue further troubleshooting in this notes.

  1. The PatchMe lab app implements certificate pinning trusting https://wwww.bing.com certificate, based on this project https://github.com/ikust/hello-pinnedcerts. Bypass certificate pinning.


Device & Data Security

🔗 Android Data Storage

Storage

The best way to secure data in a mobile app is not to retain it at all.

  • Clear the local data whenever the app is closed / sign out

  • Use encryption on sensitive data, with secure storage of the keys

Internal Storage

Linux file permissions are used in Android OS.

  • /data/app/ - apps directory

  • /system/app/ - system apps directory

  • /system/priv-app/ - sensitive system apps directory

Files under the internal storage app's directory are accessible only to the app itself.

  • SharedPreferences - allows to save and retrieve data in the form of key-value pair, using the getSharedPreferences method, with the second parameter being the MODE

    • MODE_APPEND - append data to the end of the file

    • MODE_PRIVATE - the file can only be accessed using calling application (or same user ID app)

    • MODE_WORLD_READABLE (deprecated since API level 17) - allow other application to read the file

    • MODE_WORLD_WRITEABLE (deprecated since API level 17) - allow other application to write to the file

  • DataStore - allows to store key-value pairs or typed objects with protocol buffers. DataStore uses Kotlin coroutines and Flow to store data asynchronously, consistently, and transactionally.

External Storage

  • Removable SD Cards

  • /sdcard/ or /mnt/sdcard/ - Emulated SD Card

Android defines the following storage-related permissions:

On Android 4.4 (API level 19) or higher, your app doesn't need to request any storage-related permissions to access app-specific directories within external storage. The files stored in these directories are removed when your app is uninstalled.

On devices that run Android 9 (API level 28) or lower, your app can access the app-specific files that belong to other apps, provided that your app has the appropriate storage permissions.

To give users more control over their files and to limit file clutter, apps that target Android 10 (API level 29) and higher are given scoped access into external storage, or scoped storage, by default. When scoped storage is enabled, apps cannot access the app-specific directories that belong to other apps.


🧪 Practice Lab 6

Objectives

  • Understand level of data storage security on various Android API levels

Install labs apps to the (emulated) devices (one with API Level <=17, one with API Level >17).

Test the app and data storage.

With the InsecureExternalStorage app it saves a file in the /sdcard/Android/data/com.els.insecureexternalstorage/files/FileContainer directory.

With the ReadExternalStorage app tries to read the file.

  • 📌 Device with API Level 17 (Android 4.2) or lower, any files stored by an application in the external storage are accessible by other applications on the device.

  • 📌 Device with API Level over 17 (e.g. Android 9), any files stored by an application in the external storage is not accessible by other applications on the device. (Permission denied error)


Device Administration API

Companies can use MDM (Mobile Device Management) software solutions to maintain a measure of control to protect sensitive data on corporate or personal devices (BYOD - Bring your own device).

An MDM app must be installed for administrators remote control. MDM uses built-in Android features (Device Administration API) to:

  • enforce password policy

  • force storage encryption

  • enable remote wiping

  • detect rooted device

  • control installed software, etc

Root Detection

Rooting - obtain root (superuser) access on Android (same as Linux)

  • full control over the device

  • app's with root permission can interact with data outside of its directory - device at risk

Root detection can be bypassed. Check MASTG - Testing Root Detection.

🔗 7 methods for Bypassing Android Root detection - Kishor balan


Third Party Code

SDK (Software Development Kits) - classe or jar files used to interface with code written by third-parties. SDKs must be coming from reputable sources.

A pentester must understand which SDKs are included in the app and what functionalities they offer or known vulnerabilities.

Libraries - the use of third-party libraries is common and they can introduce vulnerabilities (e.g. Heartbleed).

  • track the use of libs, update regularly

  • crate an inventory of those libraries

Device Tracking is used sometimes to track users' behavior or for DRM purposes, through unique identifiers like the MAC Address, IMEI, Serial Number, Android ID, etc.

  • Tracking/Advertising standards


Tapjacking

Tapjacking on Android refers to a type of user interface (UI) attack where an attacker overlays a malicious UI element on top of a legitimate app's interface, tricking users into unintended interactions by tapping on seemingly harmless elements that actually perform malicious actions.

🧪 Tapjacking Hacktricks

🔗 Read Tapjacking-ExportedActivity Attack app - by HackTricks - This project is an Android application that will start by launching the indicated exported application and then it will put on the foreground a malicious application that will be changing what the user is looking at while the user is actually interacting with the malicious application.

  • In the AndroidManifest.xml Check the presence of explicitly exported activities (android:exported="true") and implicitly exported (using an intent-filter)

  • filterTouchesWhenObscured="true" attribute would prevent the exploitation of this vulnerability. If set to true, the view will not receive touches whenever view's windows is obscured.


Static Code Analysis

Static Code Analysis is the examination of the application source code, without executing the program.

  • mapping the sources of potential attacker controlled input, determine all the sinks, and checking whether the input encounters a sensitive function

  • components trust one another, but the user/attacker should not be trusted

  • trust boundary - line between the user and all internal portions of an app

  • sanitize the inputs through intermediate steps

Creating a threat model for Android apps requires enumerating unprotected exported components and monitoring the flow of Intents and Extras throughout the application.

  • AndroidManifest.xml specifies the Intents and Extras that our apps will accept as input from other applications on the device. It also defines the behavior of the WebViews, File storage and which components are exposed to attacks. In addition, untrusted input is the active content (JavaScript) rendered in WebViews.

  • Unencrypted transport layer is considered a potentially untrusted input.

🧪 Practice Lab 7

goatdroid.apk + lab files will be used

Objectives

  • Static analysis with vulnerability identification

  • Reverse the in scope app

  • Exploit non secure app's receiver

Decompile the app and examine the source code. Identify insecure broadcast receiver based vulnerabilities and create evidence.

AndroidManifest.xml
  • This receiver is implicitly exported due to the intent-filter presence. Since it's not protected, any other app can pass an Intent to it and trigger the receiver.

  • Check the SendSMSNowReceiver class

SendSMSNowReceiver
  • The onReceive method retrieves Extras from the Intent using Bundle bundle = arg1.getExtras(). The values of those Extras are used in the sendTextMessage sensitive method (it allows an application to send SMS messages without user interaction).

Vulnerability

  • Any app on the device can broadcast the org.owasp.goatdroid.fourgoats.SOCIAL_SMS action, triggering the SendSMSNowReceiver to send SMS messages.

  • An attacker can craft broadcasts with arbitrary content for the phoneNumber and message Extras, potentially leading to SMS spoofing.

Check Drozer Tool for the exploitation.


If the source-sink is user-controllable input, there exists a potential vulnerability known as SQL Injection, where the sink is the query itself (input not sanitized, etc) being altered.

SQL Query: Projection (select specific table columns) + Selection ("where", select specific table rows based on a condition)

  • If the construction of the selection string lacks parameterization, it becomes susceptible to SQL Injection.

Parameterized queries, or prepared statements, are SQL queries in which placeholders are used for parameters instead of directly inserting values into the query string. Parameterized queries help to sanitize input data and protect against malicious input that could manipulate the SQL query structure.

  • e.g. of vulnerable query

Content Resolver / Provider

ContentResolver - This class provides applications access to the content model. It acts as an intermediary between the application and the Content Provider, allowing the application to perform various operations on data stored in the Android system.

  • It resolves content URIs (Uniform Resource Identifier) to the corresponding content provider, allowing applications to specify the data they want to access

  • CRUD (create, retrieve, update, delete) operations are available via content URIs

    • these map to specific methods on the Content Resolver object - insert, query, update, delete

    • they map the content URIs to a specific Content Providers

  • content://authority/path/id URI format

The CredentialProvider of the InjectMe app is vulnerable to SQL injection.

These vulnerabilities can manifest in the Content Providers in Android apps, and are exploited to dump databases.

Content Providers - facilitate structured data sharing among applications by defining a uniform and secure interface for data retrieval and manipulation.

  • Content providers may be exposed to other apps

  • Control dynamic access to content URIs by using various attributes in the <provider> element of the AndroidManifest.xml file, carefully configuring these attributes.

    • android:exported:

    • android:permission: - permission that clients must have to access the content provider

    • android:readPermission:

    • android:writePermission:

    • etc

    • <grant-uri-permission> sub-element in the <provider> element is used to specify additional URI patterns for which other apps can be granted temporary permissions to access the content provider. This element is often used in conjunction with the android:exported attribute to control access to specific URIs within the provider.


🧪 Practice Lab 8

InjectMe app lab files will be used.

Objectives

  • Enumerate URIs and exploit the app's content provider to inject SQL query.

Decompile the app and examine the source code. Identify content URI in the application and as much as possible about the app's attack surface.

  • Create and store some credentials - CredentialProvider is used

Check InjectMe/app/src/main/AndroidManifest.xml

InjectMe - AndroidManifest.xml
  • Physical Local Attacks - On devices with API Levels 8 - 23, Content providers can be queried from a privileged context (e.g. ADB shell) even if android:exported="false", but not on devices with API Level 24+

  • The content provider is accessible by third-party apps with no permissions, on devices with API Level <17 (since the content provider is explicitly exported)

To enumerate all the content URIs extract classes.dex file from the built apk and check it with strings command

Explore the CredentialProvider.java class in the source code

CredentialProvider.java
  • Check the source code for Query (retrieve) methods, parameterized queries or input sanitization.

    • switch statement - as long as the URI is valid, it will match one of the two options and take the URI input into the query

    • The code concatenates the uri.getLastPathSegment() directly into the SQL query for the CREDENTIALS_ID case. If the getLastPathSegment() method returns user-controlled input, it could lead to SQL injection vulnerabilities. There is no explicit usage of parameterized queries or input sanitization.

    • The code logs information using Log.v("InjectMe", ...). Logging sensitive information like database queries or IDs might expose details to potential attackers

Exploit the vulnerability, by interacting with the insecure content provider.

  • Try the same on an Android 6 (API level 23) device, permissions should be granted.


Path Traversal

Path traversal is a security vulnerability where an attacker manipulates file paths to access unauthorized directories or files.

This vulnerability impacts Android content providers and services, enabling exploitation by other applications with the ability to read data from the affected app.


🧪 Practice Lab 9

FileBrowser app lab files will be used.

Objectives

  • Exploit app's user input sanitization to perform a path traversal attack

  • Create a POC (Proof of Concept) exploit app FileBrowserExploit.apk

Install both FileBrowser.apk and FileBrowserExploit.apk

Understand application's attack surface - AndroidManifest.xml.

  • FileBrowser.apk allows to read the contents of different files stored on the SD card

Examine source code for possible user input sanitization inefficiencies.

  • The content provider of the application is explicitly exposed and provides file operations. Through this content provider implementation, file access to the application (or other apps) is granted when provided with a URI.

    • It has to implement the openFile method (accessfile class)

accessfile class
  • The method, when provided with a URI, returns a ParcelFileDescriptor file object, allowing the application to perform operations on it.

    • The File object is created directly from the URI path without proper validation, allowing the possibility of directory traversal attacks.

Opening the Content class, check how the app opens and reads a file.

Content class
  • Lack of Input Validation/Sanitization - The code does not validate or sanitize the URI obtained from getIntent().getData().

❗️ This could lead to path traversal attacks or unintended access to sensitive files, allowing any external app to use a directory traversal attack to request other files by supplying a URI with ../ repeated characters and the name of the files to read.

Prove the vulnerability by using the FileBrowserExploit.apk to read the /etc/hosts file.


Vulnerable Activities

Activities - In contrast to programming paradigms with a main() method for app launch, the Android system triggers code execution in an Activity instance (visual elements, screens) through designated callback methods, each corresponding to distinct stages in its lifecycle.

  • Activities are vulnerable when allow access to user data without authentication, when exported unnecessarily, etc

  • e.g. When not protected properly, a login requirement can be bypassed

Here is an example of an exported activity with no android:permission set. Any application can send an appropriate intent to this vulnerable app and spawn this activity, and sensitive information can be found.

LeakyActivity class

Vulnerable Receivers

Receivers - components in the Android system that enable apps to respond to system-wide events or broadcasts. They listen for and react to broadcast messages from the system or other apps.

  • e.g. of vulnerable receiver (implicitly) exported without any permissions. The corresponding class contains code for extracting an Extra (named PASSWORD) for the intent received, then send an intent to MainActivity passing the password along as an Extra.

VulnerableReceiver class
MainActivity class

Vulnerable Services

Services - component that either executes prolonged operations without user interaction or provides functionality for other applications to utilize.

  • e.g. of vulnerable purposefully exported service. When started, it writes a file called /data/data/com.elearnsecurity.sillyservice/files/private.txt. Since it run a shell find command, it allows another app to send an intent to verify the file exists.

    • onStartCommand method is called when an intent is received to start or connect to the service

    • cmdExtra value is drawn from an Extra with the name COMMAND

    • if statement ensures the command received starts with the string find. If this check passes, Extra value is passed to String Array cmd

    • once the String Array cmd is compiled, it passes to the exec method of the Runtime object = bin files can be spawned like in a cmd prompt

  • ❗️ unless the input is limited, the pattern of untrusted input ends up in a sensitive function, executing arbitrary commands (check Dynamic Analysis for the vulnerability)

SillyService class

Shared Preferences

SharedPreferences - used for storing and retrieving key-value pairs of primitive data types persistently (locally). It is commonly employed to save application settings, user preferences, or other small amounts of data that need to be preserved across app sessions.

  • /data/data/<package_name>/shared_prefs/ - only the app that created the xml files in this directory can access it

  • using local access, backup, adb, this data can be retrieved

shared_prefs - Chrome

Local Databases

Apps store their information in database files.

  • /data/data/<package_name>/databases/

Check .db file by pulling them into the local pc and using sqlite3 or sqlitebrowser tools.

sqlitebrowser

Tools

  • drozer - 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

Install drozer-agent app on the device, open it and turn on. From the command line use Drozer via docker to connect to the device.

🔗 Android Pentesting Using Drozer - 1 - Tech Blogs

run app.package.info -a org.owasp.goatdroid.fourgoats

  • qwark (Quick Android Review Kit) - look for several security related Android application vulnerabilities, either in source code or packaged APKs.

    • handles decompiling, attack surface enumeration, vuln detection, static code analysis with an HTML final report

    • creation of exploit APK to attack the target app

  • It will output a report in /.local/pipx/venvs/qark/lib/python3.11/site-packages/qark/report/report.html

If it gives W: Could not decode attr value, using undecoded value instead: ns=android, name=text, value=0x0000000d error, try to fix it with following commands and re-run qark --apk goatdroid.apk

  • Build a custom exploit apk with qark

❗ Compilation may NOT work with Python 3.11.2, to fix it open the file

❗ It still may not work because of Could not determine java version from '17.0.9'. eror.


Dynamic Code Analysis

Dynamic Code Analysis is the examination of the application code, by executing the program in a normal, virtualized or in a debugger environment.

  • examine the changes made to memory/file system as they occur

  • intercept network requests

  • check real-time encountered errors

Debugging

Debugging is used in security to verify the conditions necessary to reach a know vulnerable piece of code, or for POC (Proof Of Concept) exploit development.

An Android app is considered debuggable based on the android:debuggable attribute in the AndroidManifest.xml file.

  • when android:debuggable="true", the app is debuggable

  • this can leak information is someone can take the victim's device and connects it to a computer

ADB

adb (Android Debug Bridge) - command line tool used to interact with Android devices/emulators, via USB cable or Network.

BusyBox App for android can be useful too.

adb components:

  • client (runs on host pc) - the program

  • server (runs on host pc) - manages communication between the client and daemon

  • daemon - runs in background on the device, executes commands passed via the server

How ADB Works - https://github.com/lana-20/android-debug-bridge
adb

Activity Manager

adb shell am COMMAND can start an activity, send broadcast intents, monitor system interaction, etc


🧪 Practice Lab 10

NoteList app lab files will be used.

Objectives

  • Perform dynamic analysis using ADB and Activity Manager

Install the NotesList.apk on device.

Open NotesList.apk in Jadx-GUI.

  • AndroidManifest.xml

  • NotesList activity has the action MAIN (the default intent that will be called if you tap the icon in the launcher)

  • NoteEditor activity includes an action named EDIT

    • <data android:mimeType="vnd.android.cursor.item/vnd.google.note"/> - specifies the mimeType and the URI to use with the intent filter. This cursor will contain one item.

Interact with the app via adb.

  • Activity name: NotesList

  • Action name: android.intent.action.MAIN

  • Package: com.example.android.notepad


🧪 Practice Lab 11

LeakResult app lab files will be used.

Objectives

  • Perform dynamic analysis using ADB and Activity Manager

  • Reverse and find the app's attack surface

  • Launch the SecretActivity, LeakyActivity, Bypass LeakResult app's authentication mechanism, check the logs for sensitive information

  • Create a POC exploit application that sends an intent to the LeakyActivity Activity and extract the data returned, leveraging unprotected activities

Lab

Install leakresult.apk on the device

Open leakresult.apk with Jadx-GUI

📌 AndroidManifest.xml

  • Package - com.elearnsecurity.insecureactivities

  • Application debuggable and backupable

  • minSdkVersion - 15

  • targetSdkVersion - 23

  • Permissions - GET_ACCOUNTS, READ_PROFILE, READ_CONTACTS

  • Activities

    • LoginActivity - action MAIN

    • LeakyActivity (exported) - action leaky

    • SecretActivity (exported) - action bypass

AndroidManifest.xml

Use adb to launch the found activities.

In a separate terminal run logcat/pidcat

Bypass application's authentication.

SecretActivity

Launch the LeakyActivity

Check the "pidcat terminal" as it generates live logs

LeakyActivity

📌 LeakyActivity class

📌 SecretActivity class

📌 An exploit application that will launch LeakyActivity can be created, since this activity is explicitly exported.

LeakyActivity Activity suffers from information leakage via:

  1. Sensitive Information Logging

    • There are two logging statements (Log.v) that reveal sensitive information.

    • Logging sensitive information poses a security risk, especially if logs are accessible or exposed in a production environment.

  2. Intent with Secret Data

    • The intentMessage object includes sensitive information using putExtra("SECRET", "...").

    • Passing sensitive data via Intents may expose it to other components or apps if not handled securely.

An exploit application can:

#1 launch LeakyActivity and parse the device's log files (on Android >=4.1 rooted device).

#2 launch the unprotected activity using startActivityForResult() and overriding onActivityResult()

Create the application #1.

  • this app is a weaponized version of the MatLog app with the only modification to exploit LeakResult.apk as following

    • in the LogcatActivity.java file add the following snippet after the super.onCreate(savedInstanceState);

LogcatActivity Class
  • When the exploit app is run, an Intent will be sent to the LeakResult.apk and LeakyActivity will be launched.

  • Sensitive data should be seen in the exploit application's view (search for OOPS)

Open matlog/ directory in Android Studio.

  • Upgrade Gradle as suggested by Android Studio

  • Build the app - there are too many Build Scan and unsupported Gradle problems with matlog outdated source code, so I proceed with the install of the LeakResult/exploit apks/matlog-master/app/app-debug.apk from the course lab resources

  • With LeakResult.apk installed, run the installed MatLog DEBUG - Accept the Superuser permissions

  • Search for OOPS in the app

Create the application #2.

  • Opening the lab source code of the HelloWorldExploit app

    • launch LeakyActivity using startActivityForResult()

    • override the onActivityResult to extract the result LeakActivity returns

  • When the exploit app is run, a Hello world! message will be displayed but on the background launches LeakyActivity, extract the result and writes it in its logs.


🧪 Practice Lab 12

VulnerableReceiver app lab files will be used.

Objectives

  • Perform dynamic analysis

  • Reverse and find the app's attack surface

  • Bypass authentication by exploiting an insecure broadcast receiver

Lab

Install VulnerableReceiver.apk on the device

Open VulnerableReceiver.apk with Jadx-GUI

📌 AndroidManifest.xml

  • Package - com.elearnsecurity.vulnerablereceiver

  • Application debuggable and backupable

  • minSdkVersion - 20

  • targetSdkVersion - 23

  • Activities

    • MainActivity - action MAIN

    • ProfitActivity (not exported)

  • Receivers

    • VulnerableReceiver (implicitly exported with Intent) - action CHANGEPW

AndroidManifest.xml

Use adb to launch the found activities.

In a separate terminal run logcat/pidcat

Bypass application's authentication.

📌 MainActivity class

  • a random password is generated, but if an Intent is received with an Extra of NEWPASS the password is reset

📌 VulnerableReceiver class

  • implicitly exported due to intent-filter and with no permissions, any other app can pass an Intent to it

  • the onReceve method takes a parameter which is an Intent named newpass, extracting an Extra named PASSWORD, then sent to MainActivity as an Intent with the password as an Extra

MainActivity onCreate

Launch the attack via adb by interacting with the identified vulnerable broadcast receiver.

  • Password is set now, and login can be made with pw 1234

    • The correct login will open ProfitActivity


🧪 Practice Lab 13

SillyService app lab files will be used.

Objectives

  • Perform dynamic analysis

  • Reverse and find the app's attack surface

  • Inspect log files

Lab

Install SillyService.apk on the device

Open SillyService.apk with Jadx-GUI

📌 AndroidManifest.xml

  • Package - com.elearnsecurity.sillyservice

  • Application debuggable and backupable

  • minSdkVersion - 15

  • targetSdkVersion - 23

  • Permissions - WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE, WRITE_INTERNAL_STORAGE, READ_INTERNAL_STORAGE

  • Activities

    • MainActivity - action MAIN

  • Services

    • SillyService (exported)

AndroidManifest.xml

Use adb to launch the found activities.

In a separate terminal run logcat/pidcat

📌 SillyService class

  • cmdExtra value is drawn from an Extra named COMMAND

  • the if statement ensures that the received command start with the string find, then the value of the Extra is passed to String Array cmd

  • once cmd is compiled, it is passed to the exec method of the Runtime object - resulting in binary executable files to be spawned as separate process = arbitrary command execution ❗️

SillyService class

Exploit this vulnerability via adb.


🧪 Practice Lab 14

WeakWallet app lab files will be used.

Objectives

  • Perform dynamic analysis

  • Reverse and find the app's attack surface

  • Interact with the Content Provider, manipulate database

Lab

Install weakwallet.apk on the device

Open weakwallet.apk with Jadx-GUI

📌 AndroidManifest.xml

  • Package - com.elearnsecurity.weakwallet

  • Application debuggable and backupable

  • minSdkVersion - 15

  • targetSdkVersion - 23

  • Activities

    • MainActivity - action MAIN

  • Providers

    • VulnerableProvider class with authority com.elearnsecurity.provider.Wallet

AndroidManifest.xml

📌 VulnerableProvider class

Vulnerabilities in the VulnerableProvider Class:

  1. SQL Injection Risk:

    • Lack of parameterized queries in the query method.

  2. Insecure URI Handling:

    • Insufficient validation in delete, update, and query methods.

  3. No Input Validation:

    • Absence of proper user input validation.

  4. Weak Database Security:

    • Missing encryption for sensitive database data.

  5. Missing Content Provider Permissions:

    • Lack of defined permissions for data access.

  6. Hardcoded Credentials:

    • Hardcoded database-related constants - DATABASE_NAME and CARDS_TABLE_NAME

Open the app on the device and interact with it, entering some test data.

Use adb to test the app's database.

  • full control of the database, manipulate it


Last updated

Was this helpful?