Android App Security & Testing

4 years ago 348
BOOK THIS SPACE FOR AD
ARTICLE AD

SACHIN GROVER

#android #findBugs

Image for post

Image for post

Basic Terminology:

Activity- An activity is an entry point for interacting with the user. It represents a single screen with a user interface(UI). Activities provide the users with an interface to interact with the app i.e. see what’s on the screen and perform actions.

Services- A service is a general-purpose entry point for keeping an app running in the background for all kinds of reasons. Services perform operations in the background i.e. background sync, handling notifications, playing music. Services do not have a UI.
Broadcast receivers- A broadcast receiver is a component that enables the system to deliver events to the app outside of a regular user flow, allowing the app to respond to system-wide broadcast announcements. An example of this can be apps showing notifications for certain events like alarms, reminders, app notifications, etc.

Content Providers- A content provider supplies data from one application to others on request. A content provider can store data in different formats such as a file, SQLite database, or even fetch data over the network. External apps can query or modify data if permitted by the content provider.

Exported — Attribute which says whether the service can be accessed by other application or not
Intent- Intents are asynchronous messages which bind individual components to each other at runtime.Intents allows to interact with other android components. From the above mentioned components, activities, services and broadcast receivers can be activated using an intent.

Activities can be started by passing an an Intent to the startActivity() method.You can start a service from an activity or other application component by passing an Intent to startService() or startForegroundService(). The Android system calls the service's onStartCommand() method and passes it the Intent, which specifies which service to start.You can initiate a broadcast by passing an Intent to methods such as sendBroadcast(), sendOrderedBroadcast() or sendStickyBroadcast().You can perform a query to a content provider by calling query() on a ContentResolver().

Every application must have an AndroidManifest.xml(exact like here given name) file in its root directory. The manifest presents essential information about the application to the Android system, information the system must have before it can run any of the application’s code.

Tags which are Security Related

<android:sharedUserId>
The name of a Linux user ID that will be shared with other applications. By default, Android assigns each application its own unique user ID. However, if this attribute is set to the same value for two or more applications, they will all share the same ID — provided that they are also signed by the same certificate.
Application with the same user ID can access each other’s data and, if desired, run in the same process.

2. <uses-permission>

Requests a permission that the application must be granted in order for it to operate correctly. Permissions are granted by the user when the application is installed, not while it’s running.
SYNTAX:

<uses-permission android:name="string" />

android:name
The name of the permission such as “android.permission.CAMERA” or “android.permission.READ_CONTACTS

3. android:debuggable
Whether or not the application can be debugged, even when running on a device in user mode — “true” if it can be, and “false” if not. The default value is “false”

<applicationandroid:debuggable=”false”</application>

4. <permission>
Declares a security permission that can be used to limit access to specific components or features of this or other applications. You can use this to define your own Permission for your application.
SYNTAX

<permission android:description=”string resource”
android:icon=”drawable resource”
android:label=”string resource”
android:name=”string”
android:permissionGroup=”string”
android:protectionLevel=[“normal” | “dangerous” |
“signature” | “signatureOrSystem”] />

android:protectionLevel
Characterizes the potential risk implied in the permission and indicates the procedure the system should follow when determining whether or not to grant the permission to an application requesting it.

Android apps must request permission to access sensitive user data (such as contacts and SMS), as well as certain system features (such as camera and internet). Depending on the feature, the system might grant the permission automatically or might prompt the user to approve the request.

The value can be set to one of the following strings:
“normal” :- The default value. A lower-risk permission that gives requesting applications access to isolated application-level features, with minimal risk to other applications, the system, or the use
“dangerous”:- A higher-risk permission that would give a requesting application access to private user data or control over the device that can negatively impact the user. Because this type of permission introduces potential risk, the system may not automatically grant it to the requesting application. For example, any dangerous permissions requested by an application may be displayed to the user and require confirmation before proceeding
signature”:- A permission that the system grants only if the requesting application is signed with the same certificate as the application that declared the permission. If the certificates match, the system automatically grants the permission without notifying the user or asking for the user’s explicit approval

Two apps of the same company should be signed with signature permission
“signatureOrSystem”:- A permission that the system grants only to applications that are in the Android system image or that are signed with the same certificate as the application that declared the permission. Please avoid using this option, as the signature protection level should be sufficient for most needs and works regardless of exactly where applications are installed. The “signatureOrSystem” permission is used for certain special situations where multiple vendors have applications built into a system image and need to share specific features explicitly because they are being built together.

What specific strings/keys/sensitive info do you peeps grep for in a decompiled APK?

1. I search for deeplink endpoints usually “customhost://”, so searching for “://” often returns interesting stuff. Also cloud API keys, and exploit the key with awscli.
“grep -RP ‘(?<![A-Za-z0–9/+=])[A-Za-z0–9/+=]{40}(?![A-Za-z0–9/+=])’ *”.
3. There’s also specific methods that can lead to insecure implementations such as shouldOverrideUrlLoading, shouldInterceptRequest, onDownloadStart, FirebaseDatabase.getInstance(), and setJavaScriptEnabled(true).
4. Lastly parsing AndroidManifest.xml for exported components. exported=”true”
5. password, user, username, git, firebase, db, database, api key, token, auth, http, other protocols …

Preparing the Connection

First, you’ll need to connect your Android device to the computer you wish to proxy through.Next, you’ll want to set up a reverse port-forward from your phone to your computer, using adb reverse.This will forward anything on your phone that attempts to connect to localhost:8123, to the connected computer.

root@kali:~$ adb reverse tcp:8123 tcp:8123

With the reverse forward setup, you’ll want to set up the Android proxy settings.To do this, go to your network connections, edit the connection, and show the advanced options.

https://blog.jamie.holdings/2018/09/05/bypass-certificate-pinning-on-android

install JAVA JDK, jarsigner is required, make sure path of jarsigner is in the PATH variable.Install apktoolinstall zip aligninstall aaptyou need to install Android SDK also for tools like “adb” or if you do not need full Android Studio, you can just download the basic Android command line tools. Make sure you put the install path in the $PATH so that you can access the tools from anywhere.Run your emulator(genymotion) or connect your device using usb.

Run the below command to check if you can see the device:

# adb devices

Pull the APP for static analysis

adb shell pm list packages

Look through the list of package names and try to find a match between the app in question and the package name.This is usually easy, but note that the package name can be completely unrelated to the app name. If you can’t recognize the app from the list of package names, try finding the app in Google Play using a browser. The URL for an app in Google Play contains the package name.Get the full path name of the APK file for the desired package.

adb shell pm path com.example.someapp

The output will look something like this: package:/data/app/com.example.someapp-2.apk

adb pull /data/app/com.example.someapp-2.apk

you can merge the above two commands in one using the -f option (which displays associated file, just pull the file after this) :
`adb shell pm list packages -f | grep someapp
-> package:/data/app/com.example.someapp-2/base.apk=com.example.someapp`BTW, a useful trick to quickly find the associated package is to launch the app and find the displayed activity using this command:

adb shell dumpsys activity top | grep ACTIVITY

-> ACTIVITY com.example.someapp/.app.HomeActivity 2dbf6e2 pid=18453

Once you get the app either above way or download it directly, you can start static analysis of app using MobSF# docker pull opensecurity/mobile-security-framework-mobsf
# docker run -it -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest
Once Mobsf is up and running, you can go to localhost:8000 and drop/open your apk in it, it will unzip the apk, get the Java source code for you and give you report after static analysis.You can even save the java source code from MobSF UI itself and then grep for stuff or manual analysisLook for sensitive data (like secret, S3 bucket URLs, apikey, bearer token, auth Token, hardcoded credentials for 3rd party services) within AndroidManifest.xml or strings.xml under directory (res →value).MobSF also extracts all the strings and present on the UI so you can search the same on UI too.You can also search for firebase URL.Copy the url and append /.json at the end and open this in browser . If the response is something other than “Permssion Denied” then it can be a valid bug. For further exploitation read this blog.Knowing the package name will help you in frida and objection as well.

Frida

We need a program for dynamically analysis of running applications and the one that I recommend is Frida.So lets install Frida

pip install frida

Install frida-server to the device.

Download the latest frida-server from and choose the correct architecture depending on your device.
- I use Pixel 3 and the architecture is arm64 but the avd/emulator will have x86 arch, so download the x86 version of frida-server.You can check the CPU type# adb shell getprop ro.product.cpu.abi
arm64-v8a

Download Appropriate frida-server

wget https://github.com/frida/frida/releases/download/11.0.3/frida-server-11.0.3-android-arm64.xz (For ARM64) (as I use device)Extract the archiveunxz frida-server-11.0.3-android-arm64.xzRename to frida-servermv frida-server-11.0.3-android-arm64 frida-serverNow we need to transfer this frida-server to the device.To do that we need to use adbadb push frida-server /data/local/tmpChange permissions on the file so we can execute itadb shell chmod 755 /data/local/tmp/frida-serverNow we can run frida-serveradb shell “/data/local/tmp/frida-server &”Verify that frida-server works by listing installed program on the devicefrida-ps -UThe -U argument is used when the device is connected by USB or in this case a android virtual device.On host systemfrida-ps -U | findstr tata (searching for tatacliq app)

Non rooted device

This method will modify a apk and patch it with frida-gadget. That means Objection will try to add a new call to frida-gadget library in the main activity and inject frida-gadget to the lib folder in the apk.Objection does not always succeed with patching apk, so don’t trust it to work every time.

Patch apk with Objection

objection patchapk -s com.app.name.apkWhen the patching is complete the file will have objection in the filenameIf the patching was successful install patched apk to the deviceadb install com.app.name.objection.apk

or push apk to device and manually install it

adb push com.app.name.objection.apk /sdcard/Download

Run modified app

Inject to process and start exploring the appobjection — gadget “com.app.name” explore -q

Patching failed and rooted device

If objection failed to patch an apk, you can still use objection if you have a rooted device.This works because the frida-server is used instead of frida-gadget.So start frida-server on your deviceadb shell “/data/local/tmp/frida-server &”Then you can start objection with the app nameobjection — gadget “com.app.name” explore -q

Disable sslpinning

Some apps use sslpinning to protect the network connection from being sniffed on, but this can be bypassed with objection.Run objection as above, and run this command in objection terminal to disable sslpinning:android sslpinning disable

— — — — — — — — — — — — — — — — — — — — — — — — — -

Android Deep Link

Search for the android:exported=”true” activities in “AndroidManifest.xml”Open this activity in JADx-GUI → Search for “SetJavascriptEnable”Now check for any intents in the activity.A user with root permissions (i.e. # terminal) on the device can invoke any activity, simply by sending an intent to the desired activity. For example:$ adb shell am start -n <package_name>/<activity_name>How do we know what we should call?

For that we should look at the manifest, and look for the activities declarations, those which are defined as exported or which has intents can be invoked even on non rooted device.

adb shell am start -n bounty.pay/.PartOneActivity -a android.intent.action.VIEW -d “one://part?start=PartTwoActivity”

Android Deep Linking with multiple query parameters

adb shell am start -W -a android.intent.action.VIEW -d "myCustomScheme://myHost?key=category_parent_id\&value=93\&title=test" com.myApp.android

(note that we need to use a \ before & when using multiple query parameters)

Example:

Snippet#1

Code :“intent.putExtra(“EXTRA_URL”, str);”

In android “putExtra(String name, str)” is used to add extended data to the intent. It has two parameters, first one specifies the name which of the extra data,and the second parameter is the data itself.

Snippet#2

Code :“loadUrl(getIntent().getStringExtra(“EXTRA_URL”));”

In this case, getIntent() Return the intent that started this activity. If you start an Activity with some data. Let’s make it very simple and short, “intent.putExtra(“EXTRA_URL”, str);” means, you can consider “EXTRA_URL” as a variable & getStringExtra(“EXTRA_URL”)) is used here to get the data or value from “EXTRA_URL” variable.

Proof-of-Concepts Reproduce OpenRedirect:

am start -W -n app.company/.ui.events.web.WebViewActivity -a ACTION_OPEN_WEB -e EXTRA_URL https://evil.com

Reproduce Javascript Injection:

am start -n app.company/.ui.events.web.WebViewActivity -a ACTION_OPEN_WEB -e EXTRA_URL "javascript://google.com%0A alert(lol);"

Reproduce Local File Steal: That bug can :

→ Reveal token, auth, config etc in app sandbox

→ Reveal User data in app sandbox

→ Access ‘/sdcard’ data, if permitted

am start -n app.company/.ui.events.web.WebViewActivity -a ACTION_OPEN_WEB -e EXTRA_URL 'file:///sdcard/personal.txt'

Tool: https://github.com/mzfr/slicer

References:

fingerprint Bypass:

Read Entire Article