Previously we discussed Android Basics, Reversing APK & LAB Setup for Android Security Testing. We are considering that you are aware of all the previous concepts. If you haven’t read it, check it out now, click here and get back to this.
Static analysis is a process of testing applications without executing them; only the code is examined. In addition to predefined guidelines, code should be tested for technical & logical errors. During static analysis, we look for Permissions, Configurations, Cryptographic issues, Hardcoded sensitive data, and various things that will increase the attack surface for dynamic analysis.
Lack of Code Obfuscation
Code obfuscation is modifying an executable to make it useless to hackers but still fully functional. The process can change the actual method statement or metadata, but it does not change the program’s output.
Here is a simple example of what code looks like after and before obfuscation –
When the APK has been de-compiled, we are ready to analyze the code, but first, check if the code is obfuscated or not. It is a security issue if the code is not obfuscated because anyone can read, manipulate, and reverse it. If the code is obfuscated, it becomes challenging to read; even if it is obfuscated, we can de-obfuscate it by using tools such as JADX, or we can perform Manual De-obfuscation
Developers can use the Proguard for obfuscation, ultimately a precaution against reverse engineering.
Missing Root Detection
It is essential for security teams and developers to enable apps to detect root detection. Hackers often root their devices or use their rooted devices to access sensitive user data and other secrets stored in the app’s source code. Detecting this vulnerability is essential to the security of your app, as it is challenging to ensure system security and various protections after gaining root privileges.
In the following example, you can see how apps implement root detection; this is not only the way to implement some apps, not even launch on a rooted device.
There are several methods of root detection, but these are some developers can use to implement root detection –
If the root detection has been implemented, we need to bypass it, there are several methods to bypass, including reverse engineering, Xpose framework, Frida and objection, etc. In this blog, we will bypass root detection using Frida Framework –
Quick Setup for Frida –
pip install Frida && pip install objection && pip install Frida-tools
adb shell getprop ro.product.cpu.abi
xz -d Frida-server-xxxx.android-arm.xz
mv Frida-server-xxxx.android-arm.xz Frida-server
/data/local/tmpusing command –
adb push Frida-server /data/local/tmp
adb shell "chmod 755 /data/local/tmp/frida-server"
adb shell "/data/local/tmp/frida-server &"
If you faced any errors while setting up Frida, you could just go through https://github.com/frida/frida/issues hope this will solve your problem.
Let’s try to bypass –
frida -U -l frida-antiroot.js -f com.infrasoft.uboi --no-pause
you can download frida-antiroot.js from here
3. Check app we have successfully bypassed root detection –
Not every time will this script work for bypassing root detection bypass accordingly; how source code has implemented root detection technique you have to modify the script, or you can write your own. If you wish to learn more about Frida, please visit here
SSL Pinning does not implement
SSL certificate pinning is designed to prevent dangerous and complex security attacks. This security measure modifies the identity of the mobile app’s trusted certificate and blocks unknown documents from suspicious servers. Applications with fixed SSL certificates rely not on the CA’s storage license but on the stored credential. Using this technique, you can pin an SSL certificate host (a list of trusted certificates) to your application during development and compare the server certificate with the list at run time.
If SSL pinning is not implemented, then all the communication between the application and the server could be intercepted by an attacker. Because of this, the attacker can craft malicious requests to the server and look for multiple vulnerabilities. Additionally, automated attacks can be mounted against the application with the help of a proxy tool.
By using two-way SSL authentication, SSL Pinning Bypass can be prevented. This technique allows the application to act as an SSL client and send its certificate after the SSL server has validated it. Due to the complexity of two-way SSL, if we can prevent the modification or reverse engineering of the android application, that will prevent SSL Pinning bypasses via reverse engineering or hooking.
If SSL pinning has been implemented, we can bypass it. There are several methods to bypass SSL pinning, but here we go with simply Frida. As we have set up Frida, we move on to the next part, how to bypass SSL pinning using Frida.
frida -U -l fridascript.js -f com.package.nameto start
3. Let’s Intercept the traffic –
4. Open burpsuite history and check request
In this way, we can bypass the SSL pinning and intercept the traffic of android apps.
Android apps are compressed, packaged, and distributed as .apk files that resemble .jar or .zip files. These typically include your app’s compiled resources (compiled code, images, layouts, XML files, databases, etc.). The APK can be extracted using simple archiving software, and the compiled source code can be easily decompiled using free, open-source tools such as APKTool and Dex2Jar. Attackers can exploit this vulnerability and reverse the app if there is no mechanism for checking the code integrity.
This is a simple example to show how we can reverse apk –
Follow the steps to reverse apk:
keytool -genkey -v -keystore my-release-key.keystore -keyalg RSA --alias demo
jarsigner -verbose -sigalg MD5withRSA -digestalg SHA1 -keystore my-release-key.keystore modifiedAPK.apk demo
This is just a small example of reversing we can do a lots of things with reversing such as bypassing SSL Pinning, Root detection, Emulator detection bypass. Boolean strings change to get unintended results from app and many more things checkout
To avoid security risks, we can implement the following integrity checks.
It is now possible to search for Hardcoded Sensitive Information, either in Java source code or in XML files. Start by looking at Java source code, either by looking for sensitive components such as loginActivity or any component that could be interacting with sensitive data. You can also use the search option to search for sensitive words such as password, key, user, email, etc.
[Filename].apk/res/values/Arrays.xml; these files are essential for sensitive information and also help in understanding the app.
Password, Keys, and Credentials are not the only sensitive information to check; we can look at API Endpoints, Hidden URLs, IP addresses, Cloud Buckets, and much more information that might take some time to unravel, such as API URLs or endpoints needing to be fuzz tested manually with some techniques, we can escalate that, but it’s worth doing.
MD5, MD4, SHA1, RC2, base64, etc., are the depreciated cryptographic algorithms, so if the app is using these algorithms for encryption purposes of sensitive information like passwords, then serious security might occur. That’s why we can’t neglect it. If we find any hardcoded key that the app uses, we can look in the code to see if it used symmetric cryptography. If so, both encryption and decryption keys will be the same, so that encryption will be useless.
Let’s see one simple example,
Here is one hard-coded string with base64 in /res/values/strings.xml
Try to decode it
In hardcoded strings and app flow, the app should not use any insecure cryptographic algorithms. If possible, avoid storing any sensitive data on your mobile device. According to OWASP minimum requirement for cryptography should be as follows –
Key exchange: Diffie–Hellman key exchange with minimum 2048 bits Message Integrity: HMAC-SHA2 Message Hash: SHA2 256 bits Asymmetric encryption: RSA 2048 bits Symmetric-key algorithm: AES 128 bits Password Hashing: PBKDF2, Scrypt, Bcrypt ECDH, ECDSA: 256 bits
Here is something interesting we want to include –
AES Killer, decrypt AES traffic on the fly –
What it does
NOTE: Currently support AES/CBC/PKCS5Padding and AES/ECB/PKCS5Padding encryption/decryption.
Check it out now; click here
An unintended data leak occurs when a developer places sensitive data or information in an area that other apps can easily access on a mobile device.
Log.v() (Verbose logs), Log.d() (debug logs), Log.i() (informational logs), Log.w() (Warning Logs), and Log.e() (Error Logs) these are the functions commonly used for writing logs, so if an app is using any of these functions, look at the code to see if there is any sensitive information is written logs; if so, it is vulnerable for insecure logging. Logs should not be written with sensitive information because up to Android API 20 (android version 4), they are accessible by other apps as well, so there is a possibility of potential theft.
Check logs by using adb logcat; you can monitor all the logs; to sort specific records, you can use “grep”
e.g. adb logcat | grep “com.example.app” will go to grep all the logs which involved our package name.
Copy/Paste buffer Caching:
In the android system, a single clipboard is accessible by all the applications. Therefore, if the application has been enabled, copy and paste on sensitive functions such as email, password, and credit card, so it may be possible that the other application might access that information. Therefore, to avoid any security risk, it is necessary to disable the clipboard on sensitive functions.
Here is an example of how to check if the clipboard is enabled or not –
Android apps take screenshots of their current activity in the background and display them for aesthetic purposes when they emerge from the background. However, this may leak sensitive information.
File-based encryption (FBE) devices store snapshots in the following location – /data/system_ce/<USER_ID>/<IMAGE_FOLDER_NAME> folder. The name of the image folder depends on the vendor, but snapshots and recent_images are the most common names. If the device does not support FBE, the /data/system/<IMAGE_FOLDER_NAME> folder is used.
Here is the example that the app is not hiding the information when it sends to background and activity captured the screenshot and saved in the following location –
Now we need to pull the file using adb –
$ adb shell # mv /data/system_ce/0/recent_images/648_task_thumbnail /data/local/tmp # exit $ adb pull /data/local/tmp/648_task_thumbnail
Once you have pulled the file, you can open it using any available software, and here is the file –
There are other vulnerabilities you can check for related to unintended data leakage; some of them are mentioned below –
android.database.sqlite.* These are the libraries for SQLite databases, and now we can identify where SQLite is used, how it’s configured, and if we can break a query that may lead to SQL injections. As an example, here is a query designed to show user details
"SELECT * FROM sqliuser WHERE user = '" + srchtxt.getText().toString() + "'", null
After reading this, we can try to break this query such as “ ‘ OR ‘1=1” In this case, we break the query using a single quote then we start writing our query. OR is the operator that executes the query in case one of both conditions is matched. Now, as we don’t know which usernames exist, we pass 1=1, which is always true, so as our one condition is true query will execute.
Both conditions are matched. Now, as we don’t know which usernames exist, we go through 1=1, which is always true, so as our one condition is true query will execute.
Most of the time, mobile phones are connected to public WIFI, which increases the chances of traffic interception. Uses of SSL/TSL Might helps in protecting information. Session Tokens, Passwords or any personal information of often transmitted, so it is necessary to keep an eye on data transmission protocols and cryptography; however, it does not guarantee that the information can’t be decrypted, so better to follow the best practices to encrypt data with solid algorithms use a secure protocol such as TSL/ SSL.
We can look for this kind of discrepancy in Androidmanifest.xml as best practice.
If the android manifest has not declared anything about it must have another look into com.example.app/res/xml/network_security_config.xml, you might find any misconfiguration
<network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">192.168.1.1</domain> </domain-config> </network-security-config>
Here is the another best example of wrong implementation –
The above code will accept any CA certificate issued to any domain, which is a wrong implementation.
According you can look for this type of security risk.
Hope you have already set up the lab as per our previous blog; if you haven’t set it up yet, please look at ‘How to Intercept Android Traffic.’
2. Start your burp suite and configure for traffic interception
3. Open hpandro app and click on reload
4. Open burpsuite Proxy > HTTP history > /task/http.android
In the previous example, we successfully got the flag in response. Still, there can be other scenarios such as credit card details, user credentials and other things depending on functionality; sensitive information can leak.
When a developer assumes that a user or malicious app cannot access sensitive information on the mobile device, they might store it in plain text. We can easily access the file system & look for any sensitive data stores. In an earlier version of android, another app is not allowed to interfere with internal storage, which increases security. Still, most of the time, developers leave the files or directories with word_readable and word_writeable so anyone can access and modify the data and then any malicious user or application can access those files.
Some sensitive directories to look for
/mnt/sdcard/[filename] /data/data/com.example/shared_pref/[filename] /data/data/com.example/Databases/ [filename] /data/data/com.example/[.temp files]
Here is the one best example of how android app is storing data in shared preferences without any encryption. you can download the DIVA from here.
4. Once credentials successfully saved enter into adb shell as per following command.
$adb shell #cat /data/data/jakhar.aseem.diva/shared_prefs/jakhar.aseem.diva_preferences.xml
we able to see that the app stored the credentials in plain text.
Take one more example of insecure data storage in databases –
3. Enter into adb shell and use following commands to check databases
$adb shell #sqlite3 /data/data/jakhar.aseem.diva/databases/ids2 sqlite> .tables sqlite> select * from myuser;
In the above image, we can see that the data is stored in plaintext. It is always recommended to store data using hashes or encryption; other than this, we have the choice to encrypt the database file by using SQL cipher.
The most crucial part of Android is its manifest file. It might store sensitive information, but more than that, it contains all the configuration information of the app, and here we find most of the attack surface.
All information about the application configuration can be found here, such as which components are used, which permissions are available, etc.
Let’s start with package details,
It might be hard to decide what to do with the package name, but later on, while doing tests, it will be beneficial. The package name is different from the app name used by the system to analyze operations. The directory where most of the app’s data is stored has the name /data/data/com.example.app.
Next is API Information,
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="21" android:maxSdkVersion="22"/>
The SDK version and Android version are different; for example, the SDK version of android 4.4 (KitKat) is 19. So what does API information tell us? minSdkVersion says it will not work below SDK 19; max version means it will not work above SDK 22, and targetSdkVersion that the app is built for that particular SDK version.
After that there are flags in file
<application... android: allow Backup:"true"></app>
The first flag is Backup, which is true, and the app can take a backup automatically or manually. It is possible that the attacker can Backup the app with sensitive information such as credit card numbers, usernames, passwords, etc. and restore it on his app, thus posing a threat to user privacy.
<application... android: allow debuggable:"true"></app>
Secondly, the debuggable mode is true, which should not be the case. Due to the staging environment, attackers can execute runtime code injections and gather plenty of information if it is true. So, setting false is crucial for preventing security risks.
Whenever an app uses permissions, it must be listed in the AndroidManifest.xml file; as in the above example, it requests approval for the camera, which is not owned by the app. WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE Writing to External Storage and Reading from External Storage indicate something is interacting with External Storage, so we can look into external storage to see if it might be storing any sensitive information.
<activity android:exported="true" android:name:".activities.example"/>
The above code describes the activity. In this case, com.example.app/com.example.app.activities.example is the same as com.example.app/.activities.example. While decompiling the code, simply look in the folder com > example > app > activities > example.class
Similarly, other components of Android are declared in a file.
<service>for each subclass of Service.
<receiver>for each subclass of BroadcastReceiver.
<provider>for each subclass of Content Provider
Another thing to notice is exported=”true” – what does it mean? If an app needs to access an external app or interfere with the activity of any other app during this time, it is allowed. Still, now that it is accessible by other apps, any malicious app can do some malicious activities with the app. Still, there is a condition that the permissions should be missing, such as if the developer configures the permissions, then the app can only run if granted.
<intent-filter> <action android:name="android.action.intent.MAIN" /> <category android:name:"android.intent.category.LAUNCHER"/> <intent-filter>
Any component, such as an activity, service, or broadcast, must intend to start. When there is explicit intent, everything knows what to do next. However, implicit intent filters exist when many choices are available, such as the share function.
Activities that is declared under an intent filter are exported by default.
Mobile Security Framework (MobSF) is an automated, all-in-one mobile application (Android/iOS/Windows) pen-testing, malware analysis and security assessment framework capable of performing static and dynamic analysis. MobSF supports mobile app binaries (APK, XAPK, IPA & APPX) along with zipped source code and provides REST APIs for seamless integration with your CI/CD or DevSecOps pipeline. In addition, the Dynamic Analyzer helps you to perform runtime security assessment and interactive instrumented testing.
Either we host locally or use directly hosted from https://mobsf.live/
Once the app has been successfully uploaded, it will be automatic scan for every possibility and generate the report.
Before assuming anything, it is essential that you need to confirm issues manually. However, MobSF simplifies everything, saving lots of time and giving detailed reports.
Hope you enjoyed it, In this blog we have discussed most of the static analysis of android, and we will cover the rest of the part in our next blog; stay tuned!
Android apps are utilized nowadays for various purposes, including mobile banking, shopping, sharing personal information, social networking, and entertainment. Unfortunately, android devices are vulnerable to threats from multiple hacking techniques, including malware, code injection, buffer overflow, and reverse engineering. No matter how big or small your business is, security should always come first. Connect with us to do penetration testing to keep your apps safe and secure.
Find more about us here.