hacktricks/mobile-pentesting/android-app-pentesting/android-applications-basics.md

425 lines
27 KiB
Markdown
Raw Normal View History

2024-12-12 10:39:29 +00:00
# Android Applications Basics
{% hint style="success" %}
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Support HackTricks</summary>
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
</details>
{% endhint %}
## Android Security Model
**There are two layers:**
* The **OS**, which keeps installed applications isolated from one another.
* The **application itself**, which allows developers to **expose certain functionalities** and configures application capabilities.
### UID Separation
**Each application is assigned a specific User ID**. This is done during the installation of the app so t**he app can only interact with files owned by its User ID or shared** files. Therefore, only the app itself, certain components of the OS and the root user can access the apps data.
### UID Sharing
**Two applications can be configured to use the same UID**. This can be useful to share information, but if one of them is compromised the data of both applications will be compromised. This is why this behaviour is **discourage**.\
**To share the same UID, applications must define the same `android:sharedUserId` value in their manifests.**
### Sandboxing
The **Android Application Sandbox** allows to run **each application** as a **separate process under a separate user ID**. Each process has its own virtual machine, so an apps code runs in isolation from other apps.\
From Android 5.0(L) **SELinux** is enforced. Basically, SELinux denied all process interactions and then created policies to **allow only the expected interactions between them**.
### Permissions
When you installs an **app and it ask for permissions**, the app is asking for the permissions configured in the **`uses-permission`** elements in the **AndroidManifest.xml** file. The **uses-permission** element indicates the name of the requested permission inside the **name** **attribute.** It also has the **maxSdkVersion** attribute which stops asking for permissions on versions higher than the one specified.\
Note that android applications don't need to ask for all the permissions at the beginning, they can also **ask for permissions dynamically** but all the permissions must be **declared** in the **manifest.**
When an app exposes functionality it can limit the **access to only apps that have a specified permission**.\
A permission element has three attributes:
* The **name** of the permission
* The **permission-group** attribute, which allows for grouping related permissions.
* The **protection-level** which indicates how the permissions are granted. There are four types:
* **Normal**: Used when there are **no known threats** to the app. The user is **not required to approve i**t.
* **Dangerous**: Indicates the permission grants the requesting application some **elevated access**. **Users are requested to approve them**.
* **Signature**: Only **apps signed by the same certificate as the one** exporting the component can be granted permission. This is the strongest type of protection.
* **SignatureOrSystem**: Only **apps signed by the same certificate as the one** exporting the component or **apps running with system-level access** can be granted permissions
## Pre-Installed Applications
These apps are generally found in the **`/system/app`** or **`/system/priv-app`** directories and some of them are **optimised** (you may not even find the `classes.dex` file). Theses applications are worth checking because some times they are **running with too many permissions** (as root).
* The ones shipped with the **AOSP** (Android OpenSource Project) **ROM**
* Added by the device **manufacturer**
* Added by the cell **phone provider** (if purchased from them)
## Rooting
In order to obtain root access into a physical android device you generally need to **exploit** 1 or 2 **vulnerabilities** which use to be **specific** for the **device** and **version**.\
Once the exploit has worked, usually the Linux `su` binary is copied into a location specified in the user's PATH env variable like `/system/xbin`.
Once the su binary is configured, another Android app is used to interface with the `su` binary and **process requests for root access** like **Superuser** and **SuperSU** (available in Google Play store).
{% hint style="danger" %}
Note that the rooting process is very dangerous and can damage severely the device
{% endhint %}
### ROMs
It's possible to **replace the OS installing a custom firmware**. Doing this it's possible to extend the usefulness of an old device, bypass software restrictions or gain access to the latest Android code.\
**OmniROM** and **LineageOS** are two of the most popular firmwares to use.
Note that **not always is necessary to root the device** to install a custom firmware. **Some manufacturers allow** the unlocking of their bootloaders in a well-documented and safe manner.
### Implications
Once a device is rooted, any app could request access as root. If a malicious application gets it, it can will have access to almost everything and it will be able to damage the phone.
## Android Application Fundamentals <a href="#2-android-application-fundamentals" id="2-android-application-fundamentals"></a>
- The format of Android applications is referred to as _APK file format_. It is essentially a **ZIP file** (by renaming the file extension to .zip, the contents can be extracted and viewed).
- APK Contents (Not exhaustive)
- **AndroidManifest.xml**
- resources.arsc/strings.xml
- resources.arsc: contains precompiled resources, like binary XML.
- res/xml/files\_paths.xml
- META-INF/
- This is where the Certificate is located!
- **classes.dex**
- Contains Dalvik bytecode, representing the compiled Java (or Kotlin) code that the application executes by default.
- lib/
- Houses native libraries, segregated by CPU architecture in subdirectories.
- `armeabi`: code for ARM based processors
- `armeabi-v7a`: code for ARMv7 and higher based processors
- `x86`: code for X86 processors
- `mips`: code for MIPS processors only
- assets/
- Stores miscellaneous files needed by the app, potentially including additional native libraries or DEX files, sometimes used by malware authors to conceal additional code.
- res/
- Contains resources that are not compiled into resources.arsc
### **Dalvik & Smali**
In Android development, **Java or Kotlin** is used for creating apps. Instead of using the JVM like in desktop apps, Android compiles this code into **Dalvik Executable (DEX) bytecode**. Earlier, the Dalvik virtual machine handled this bytecode, but now, the Android Runtime (ART) takes over in newer Android versions.
For reverse engineering, **Smali** becomes crucial. It's the human-readable version of DEX bytecode, acting like assembly language by translating source code into bytecode instructions. Smali and baksmali refer to the assembly and disassembly tools in this context.
## Intents
Intents are the primary means by which Android apps communicate between their components or with other apps. These message objects can also carry data between apps or component, similar to how GET/POST requests are used in HTTP communications.
So an Intent is basically a **message that is passed between components**. Intents **can be directed** to specific components or apps, **or can be sent without a specific recipient**.\
To be simple Intent can be used:
* To start an Activity, typically opening a user interface for an app
* As broadcasts to inform the system and apps of changes
* To start, stop, and communicate with a background service
* To access data via ContentProviders
* As callbacks to handle events
If vulerable, **Intents can be used to perform a variety of attacks**.
### Intent-Filter
**Intent Filters** define **how an activity, service, or Broadcast Receiver can interact with different types of Intents**. Essentially, they describe the capabilities of these components, such as what actions they can perform or the kinds of broadcasts they can process. The primary place to declare these filters is within the **AndroidManifest.xml file**, though for Broadcast Receivers, coding them is also an option.
Intent Filters are composed of categories, actions, and data filters, with the possibility of including additional metadata. This setup allows components to handle specific Intents that match the declared criteria.
A critical aspect of Android components (activities/services/content providers/broadcast receivers) is their visibility or **public status**. A component is considered public and can interact with other apps if it is **`exported`** with a value of **`true`** or if an Intent Filter is declared for it in the manifest. However, there's a way for developers to explicitly keep these components private, ensuring they do not interact with other apps unintentionally. This is achieved by setting the **`exported`** attribute to **`false`** in their manifest definitions.
Moreover, developers have the option to secure access to these components further by requiring specific permissions. The **`permission`** attribute can be set to enforce that only apps with the designated permission can access the component, adding an extra layer of security and control over who can interact with it.
```java
<activity android:name=".MyActivity" android:exported="false">
<!-- Intent filters go here -->
</activity>
```
### Implicit Intents
Intents are programatically created using an Intent constructor:
```java
Intent email = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));
```
The **Action** of the previously declared intent is **ACTION\_SEND** and the **Extra** is a mailto **Uri** (the Extra if the extra information the intent is expecting).
This intent should be declared inside the manifest as in the following example:
```xml
<activity android:name="ShareActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
```
An intent-filter needs to match the **action**, **data** and **category** to receive a message.
The "Intent resolution" process determine which app should receive each message. This process considers the **priority attribute**, which can be set in the i**ntent-filter declaration**, and t**he one with the higher priority will be selected**. This priority can be set between -1000 and 1000 and applications can use the `SYSTEM_HIGH_PRIORITY` value. If a **conflict** arises, a "choser" Window appears so the **user can decide**.
### Explicit Intents
An explicit intent specifies the class name it's targeting:
```java
Intent downloadIntent = new (this, DownloadService.class):
```
In other applications in order to access to the previously declared intent you can use:
```java
Intent intent = new Intent();
intent.setClassName("com.other.app", "com.other.app.ServiceName");
context.startService(intent);
```
### Pending Intents
These allow other applications to **take actions on behalf of your application**, using your app's identity and permissions. Constructing a Pending Intent it should be **specified an intent and the action to perform**. If the **declared intent isn't Explicit** (doesn't declare which intent can call it) a **malicious application could perform the declared action** on behalf of the victim app. Moreover, **if an action isn't specified**, the malicious app will be able to do **any action on behalf the victim**.
### Broadcast Intents
Unlike the previous intents, which are only received by one app, broadcast intents **can be received by multiple apps**. However, from API version 14, it's **possible to specify the app that should receive** the message using Intent.set Package.
Alternatively it's also possible to **specify a permission when sending the broadcast**. The receiver app will need to have that permission.
There are **two types** of Broadcasts: **Normal** (asynchronous) and **Ordered** (synchronous). The **order** is base on the **configured priority within the receiver** element. **Each app can process, relay or drop the Broadcast.**
It's possible to **send** a **broadcast** using the function `sendBroadcast(intent, receiverPermission)` from the `Context` class.\
You could also use the function **`sendBroadcast`** from the **`LocalBroadCastManager`** ensures the **message never leaves the app**. Using this you won't even need to export a receiver component.
### Sticky Broadcasts
This kind of Broadcasts **can be accessed long after they were sent**.\
These were deprecated in API level 21 and it's recommended to **not use them**.\
**They allow any application to sniff the data, but also to modify it.**
If you find functions containing the word "sticky" like **`sendStickyBroadcast`** or **`sendStickyBroadcastAsUser`**, **check the impact and try to remove them**.
## Deep links / URL schemes
In Android applications, **deep links** are used to initiate an action (Intent) directly through a URL. This is done by declaring a specific **URL scheme** within an activity. When an Android device tries to **access a URL with this scheme**, the specified activity within the application is launched.
The scheme must be declarated in the **`AndroidManifest.xml`** file:
```xml
[...]
<activity android:name=".MyActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="examplescheme" />
</intent-filter>
[...]
```
The scheme from the previous example is `examplescheme://` (note also the **`category BROWSABLE`**)
Then, in the data field, you can specify the **host** and **path**:
```xml
<data android:scheme="examplescheme"
android:host="example"
/>
```
To access it from a web it's possible to set a link like:
```xml
<a href="examplescheme://example/something">click here</a>
<a href="examplescheme://example/javascript://%250dalert(1)">click here</a>
```
In order to find the **code that will be executed in the App**, go to the activity called by the deeplink and search the function **`onNewIntent`**.
Learn how to [call deep links without using HTML pages](./#exploiting-schemes-deep-links).
## AIDL - Android Interface Definition Language
The **Android Interface Definition Language (AIDL)** is designed for facilitating communication between client and service in Android applications through **interprocess communication** (IPC). Since accessing another process's memory directly is not permitted on Android, AIDL simplifies the process by marshalling objects into a format understood by the operating system, thereby easing communication across different processes.
### Key Concepts
- **Bound Services**: These services utilize AIDL for IPC, enabling activities or components to bind to a service, make requests, and receive responses. The `onBind` method in the service's class is critical for initiating interaction, marking it as a vital area for security review in search of vulnerabilities.
- **Messenger**: Operating as a bound service, Messenger facilitates IPC with a focus on processing data through the `onBind` method. It's essential to inspect this method closely for any unsafe data handling or execution of sensitive functions.
- **Binder**: Although direct usage of the Binder class is less common due to AIDL's abstraction, it's beneficial to understand that Binder acts as a kernel-level driver facilitating data transfer between the memory spaces of different processes. For further understanding, a resource is available at [https://www.youtube.com/watch?v=O-UHvFjxwZ8](https://www.youtube.com/watch?v=O-UHvFjxwZ8).
## Components
These include: **Activities, Services, Broadcast Receivers and Providers.**
### Launcher Activity and other activities
In Android apps, **activities** are like screens, showing different parts of the app's user interface. An app can have many activities, each one presenting a unique screen to the user.
The **launcher activity** is the main gateway to an app, launched when you tap the app's icon. It's defined in the app's manifest file with specific MAIN and LAUNCHER intents:
```markup
<activity android:name=".LauncherActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
```
Not all apps need a launcher activity, especially those without a user interface, like background services.
Activities can be made available to other apps or processes by marking them as "exported" in the manifest. This setting allows other apps to start this activity:
```markdown
<service android:name=".ExampleExportedService" android:exported="true"/>
```
However, accessing an activity from another app isn't always a security risk. The concern arises if sensitive data is being shared improperly, which could lead to information leaks.
An activity's lifecycle **begins with the onCreate method**, setting up the UI and preparing the activity for interaction with the user.
### Application Subclass
In Android development, an app has the option to create a **subclass** of the [Application](https://developer.android.com/reference/android/app/Application) class, though it's not mandatory. When such a subclass is defined, it becomes the first class to be instantiated within the app. The **`attachBaseContext`** method, if implemented in this subclass, is executed before the **`onCreate`** method. This setup allows for early initialization before the rest of the application starts.
```java
public class MyApp extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
// Initialization code here
}
@Override
public void onCreate() {
super.onCreate();
// More initialization code
}
}
```
### Services
[Services](https://developer.android.com/guide/components/services) are **background operatives** capable of executing tasks without a user interface. These tasks can continue running even when users switch to different applications, making services crucial for **long-running operations**.
Services are versatile; they can be initiated in various ways, with **Intents** being the primary method for launching them as an application's entry point. Once a service is started using the `startService` method, its `onStart` method kicks into action and keeps running until the `stopService` method is explicitly called. Alternatively, if a service's role is contingent on an active client connection, the `bindService` method is used for binding the client to the service, engaging the `onBind` method for data passage.
An interesting application of services includes background music playback or network data fetching without hindering the user's interaction with an app. Moreover, services can be made accessible to other processes on the same device through **exporting**. This is not the default behavior and requires explicit configuration in the Android Manifest file:
```xml
<service android:name=".ExampleExportedService" android:exported="true"/>
```
### Broadcast Receivers
**Broadcast receivers** act as listeners in a messaging system, allowing multiple applications to respond to the same messages from the system. An app can **register a receiver** in **two primary ways**: through the app's **Manifest** or **dynamically** within the app's code via the **`registerReceiver`** API. In the Manifest, broadcasts are filtered with permissions, while dynamically registered receivers can also specify permissions upon registration.
**Intent filters** are crucial in both registration methods, determining which broadcasts trigger the receiver. Once a matching broadcast is sent, the receiver's **`onReceive`** method is invoked, enabling the app to react accordingly, such as adjusting behavior in response to a low battery alert.
Broadcasts can be either **asynchronous**, reaching all receivers without order, or **synchronous**, where receivers get the broadcast based on set priorities. However, it's important to note the potential security risk, as any app can prioritize itself to intercept a broadcast.
To understand a receiver's functionality, look for the **`onReceive`** method within its class. This method's code can manipulate the received Intent, highlighting the need for data validation by receivers, especially in **Ordered Broadcasts**, which can modify or drop the Intent.
### Content Provider
**Content Providers** are essential for **sharing structured data** between apps, emphasizing the importance of implementing **permissions** to ensure data security. They allow apps to access data from various sources, including databases, filesystems, or the web. Specific permissions, like **`readPermission`** and **`writePermission`**, are crucial for controlling access. Additionally, temporary access can be granted through **`grantUriPermission`** settings in the app's manifest, leveraging attributes such as `path`, `pathPrefix`, and `pathPattern` for detailed access control.
Input validation is paramount to prevent vulnerabilities, such as SQL injection. Content Providers support basic operations: `insert()`, `update()`, `delete()`, and `query()`, facilitating data manipulation and sharing among applications.
**FileProvider**, a specialized Content Provider, focuses on sharing files securely. It is defined in the app's manifest with specific attributes to control access to folders, denoted by `android:exported` and `android:resource` pointing to folder configurations. Caution is advised when sharing directories to avoid exposing sensitive data inadvertently.
Example manifest declaration for FileProvider:
```xml
<provider android:name="androidx.core.content.FileProvider"
android:authorities="com.example.myapp.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
```
And an example of specifying shared folders in `filepaths.xml`:
```xml
<paths>
<files-path path="images/" name="myimages" />
</paths>
```
For further information check:
- [Android Developers: Content Providers](https://developer.android.com/guide/topics/providers/content-providers)
- [Android Developers: FileProvider](https://developer.android.com/training/secure-file-sharing/setup-sharing)
## WebViews
WebViews are like **mini web browsers** inside Android apps, pulling content either from the web or from local files. They face similar risks as regular browsers, yet there are ways to **reduce these risks** through specific **settings**.
Android offers two main WebView types:
- **WebViewClient** is great for basic HTML but doesn't support the JavaScript alert function, affecting how XSS attacks can be tested.
- **WebChromeClient** acts more like the full Chrome browser experience.
A key point is that WebView browsers do **not share cookies** with the device's main browser.
For loading content, methods such as ````loadUrl````, ````loadData````, and ````loadDataWithBaseURL```` are available. It's crucial to ensure these URLs or files are **safe to use**. Security settings can be managed via the ````WebSettings```` class. For instance, disabling JavaScript with ````setJavaScriptEnabled(false)```` can prevent XSS attacks.
The JavaScript "Bridge" lets Java objects interact with JavaScript, requiring methods to be marked with ````@JavascriptInterface```` for security from Android 4.2 onwards.
Allowing content access (````setAllowContentAccess(true)````) lets WebViews reach Content Providers, which could be a risk unless the content URLs are verified as secure.
To control file access:
- Disabling file access (````setAllowFileAccess(false)````) limits access to the filesystem, with exceptions for certain assets, ensuring they're only used for non-sensitive content.
## Other App Components and Mobile Device Management
### **Digital Signing of Applications**
- **Digital signing** is a must for Android apps, ensuring they're **authentically authored** before installation. This process uses a certificate for app identification and must be verified by the device's package manager upon installation. Apps can be **self-signed or certified by an external CA**, safeguarding against unauthorized access and ensuring the app remains untampered during its delivery to the device.
### **App Verification for Enhanced Security**
- Starting from **Android 4.2**, a feature called **Verify Apps** allows users to have apps checked for safety before installation. This **verification process** can warn users against potentially harmful apps, or even prevent the installation of particularly malicious ones, enhancing user security.
### **Mobile Device Management (MDM)**
- **MDM solutions** provide **oversight and security** for mobile devices through **Device Administration API**. They necessitate the installation of an Android app to manage and secure mobile devices effectively. Key functions include **enforcing password policies**, **mandating storage encryption**, and **permitting remote data wipe**, ensuring comprehensive control and security over mobile devices.
```java
// Example of enforcing a password policy with MDM
DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName adminComponent = new ComponentName(context, AdminReceiver.class);
if (dpm.isAdminActive(adminComponent)) {
// Set minimum password length
dpm.setPasswordMinimumLength(adminComponent, 8);
}
```
{% hint style="success" %}
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Support HackTricks</summary>
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
</details>
{% endhint %}