Estimated difficulty: 💜💜💜💜🤍
We are continuing on our quest to conquer the OWASP Mobile Top 10, and if you have been following this series then congratulations, you have made it to M4: Insecure Authentication! This post is going to delve into the world of how mobile apps can use weak authentication methods and how an attacker might exploit them. On our hunt to find purposefully weak mobile applications, pentester land has brought us joy, and we are going to use the sieve app to help demonstrate how insecure authentication can be exploited.
What in the APK is it?
There are many different types of authentication methods that might be used within a mobile application. Authentication may be done locally on a mobile device, authentication can be done based on a client-server model, authentication might even be based on features a mobile device has, such as biometrics or pin codes. Unlike a web application, there may also be a need for authentication to be offline depending on the requirements.
An attacker would want to bypass authentication so they can anonymously interact with the app and execute existing functions or possibly interact with the back-end. This could allow them to access or load data they would otherwise be unauthorised to do so. If authentication is done locally, for example, there may be hardcoded or insecurely stored credentials that might otherwise be used. My previous blog post on M2: Insecure Data Storage touched on this. Another example of how an attacker may exploit insecure authentication is by sending GET/ POST requests to the application without any kind of authentication token. The attacker must understand how authentication is enforced in the mobile application to take the necessary steps to test any ways of bypassing it.
Due to the nature of the attack, it can have a severe impact on the organisation. Notably, it would be difficult to pinpoint where an attack might be coming from as authentication to the app would have been bypassed!
If the attack was successfully executed this could have a reputational impact, data could be stolen and unauthorised access would be granted.
Unauthenticated and anonymous interactions and actions with an application may also indicate unauthorised access. If permissions for different users are in place, the bypass of any kind of authentication could then allow them to bypass this access.
How it Works
There are multiple ways that a mobile application may become vulnerable to insecure authentication. The OWASP documentation bullet points this well.
- If requests can be made to the backend of the application without the need for an access token.
- If credentials are stored locally and insecurely on the device.
- If the application implements a weak password policy.
- If biometric features such as touch ID are incorporated into the application.
Local authentication is where an application will locally authenticate with credentials that are stored on the mobile device itself. There are multiple ways a user may authenticate to a mobile device locally, such as:
- Facial recognition (Biometrics)
- Fingerprint scanning (Biometrics)
- PIN code (Credentials)
- Password (Credentials)
Below I’ll try to give you a high level overview of how these types of authentication are working and how we might be able to exploit or bypass these methods.
When an application/ device makes use of biometrics, there are a number of factors that can be used to measure the strength of these. Notably for Android, these are: Spoof Acceptance Rate (SAR), Imposter Acceptance Rate (IAR) and False Acceptance Rate (FAR).
SAR – The chance a biometric model will accept a pre recorded (if voice recognition) sample and unlock the device or application.
IAR – The chance a biometric model will accept a mimiced actual biometric, such as a copied fingerprint.
FAR – The frequency a biometric model will accept a false biometric input.
In Android, there are different types of classes offered to be used within the code of an application to make use of local authentication. These have been highlighted in the image below.
A biometric library is used to implement biometric authentication. To test the biometrics security, you need to know the authentication flow. This has been described well here. As a TL;DR if the CryptoObject class within the flow is not used as a part of the authenticate method within the code of the application, then it would be possible to bypass authentication using a tool called Frida. Frida is a dynamic analysis tool.
In previous versions of the Android API, notably Android API 6.0 there was a feature that allowed an application to authenticate with the credentials used to authenticate to the mobile device itself. In the documentation these were referred to as confirm credentials.
Confirm credentials will allow you to authenticate users to your app based on how recently they last unlocked their device. When testing the security of the implemented use of confirm credentials within an application, there are a few points you want to look out for:
- Is there a lock screen in place?
- Is there a password / PIN set?
- How strong is their password or PIN? If it is something like 1234 then an unauthorised user of the device may be able to guess this and access information in the app they otherwise shouldn’t.
- How long is access allowed after the device has been unlocked? Long periods of time may allow an unauthorised user to access information in the app.
Dynamic analysis can also be performed on an application when testing the implemented confirm credentials. You can test the number of seconds passed that allows the user to authenticate to the application.
Authentication to a mobile application can also be remote. A high level overview of a mobile applications architecture looks like the below. A user will interact with the interface and given the actions they supply to the application the device will talk to the remote infrastructure.
Similarly to local authentication, some of the following authentication methods can be used:
- Username and password (Credentials)
- Access tokens (Stateless authentication)
- SessionID (Sateful authentication)
I will give a high level overview of how these methods of authentication are working and what we should look out for to exploit them.
Credentials are a common method for authentication. Like web application authentication, mobile applications may also require credentials such as a username and password. Below is a basic diagram outlining the process of authentication from a mobile app to a remote server.
Insecure authentication is prominent when the password policy is weak. If credentials are weak and stored in a server, and if that server gets compromised, user accounts for the application may be easily cracked. Given that, unauthorised access may be granted to those with the application installed and malicious activity could be carried out with the attacker impersonating the victim using the compromised credentials.
If the connection is stateless as mentioned previously then an access token can be provided. OAuth is a common standard created for users to grant applications access to information on other sites. For example, if we had a mobile application called test and that application had the option to authenticate the user using Facebook, when a user clicks login with Facebook the below workflow occurs.
An authorization request is made to the Authorization server and the login page is returned. Once the user successfully enters in their Facebook credentials then the application will redirect to the application itself and display it’s content.
There are other scenarios that can occur where an access token may be granted, however this isn’t in the scope of the blog post. When stateless authentication has been implemented, it is important to check that the session terminates properly and that the refresh token is invalidated. All access tokens should be deleted from the client side. If these measures are not in place then it may be possible for information or data previously accessed to be leaked.
If the connection to the application is stateful then a session ID will be granted to the user for a set amount of time defined by how long the session should last before timing out, or after a set amount of time of inactivity.
When testing session management, you want to look out for some of the following points listed below. More information on session management and testing guidelines can be found here.
- Ensure that the session ID is required and consistent throughout when sending requests to get sensitive data.
- Make sure that the session ID is strong and hard to be brute forced. e.g. a session ID of customer1 would not be secure.
- Session IDs should be sent over HTTPS so they cannot be intercepted, leading to session hijacking.
- Session IDs should not be saved. A new session ID should be generated each time a new session begins.
One scary thought is that even with 2FA implemented in one mobile applications security controls, a bounty hunter from HackerOne was able to bypass this by brute-forcing the secondary 4 digit pin. There was a lack of authentication code expiration and there was no mechanism in place to prevent multiple requests being sent to the backend. As a 4 digit PIN does not have many different possibilities, it was possible for our hacker here to brute force the PIN and gain account takeover by editing a victims account details. The issue was recorded to be resolved and fixed in a timely manner.
Try it Yourself!
For this walkthrough we will be focussing on the static analysis of an APK and how to spot insecure authentication. The Sieve APK was created by MWR and it’s intended use was to be a password manager. Alas, this application is not the most secure, as we are about to find out.
What you will need:
1. Reverse the application by loading into either JADX-GUI or Android Studio. I have used both (for no good apparent reason) when carrying out this exercise.
2. First things first is we want to gather more information about the application. The best place to start is by checking the AndroidManifest.xml file. This file includes the permission the app would request to run and carry out some of its functionality. The permissions used within this application can be seen in the below code snippet.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.INTERNET" /> <permission android:label="Allows reading of the Key in Sieve" android:name="com.mwr.example.sieve.READ_KEYS" android:protectionLevel="0x1" /> <permission android:label="Allows editing of the Key in Sieve" android:name="com.mwr.example.sieve.WRITE_KEYS" android:protectionLevel="0x1" />
This application has it’s own permissions defined, which look rather… interesting!
3. We can look at the activites and the services defined in the AndroidManifest.xml file also. From reading this we can spot login activities and services such as Auth and Crypto.
<service android:name=".AuthService" android:exported="true" android:process=":remote" /> <service android:name=".CryptoService" android:exported="true" android:process=":remote" />
The activities that have been defined within the AndroidManifest.xml file had the following names:
PWList SettingsActivity AddEntryActivity ShortLoginActivity WelcomeActivity PINActivity
4. Since we know that the application has been created as an intended password manager, the activity named PWList seems like a good place to probe.
5. The next steps from looking at the code is to begin dynamic analysis. The below video outlines the solution and demonstrates this well using the tool, Drozer, created by MWR originally and taken over by FSecure.
6. Once you have managed to launch the strange activity PWList you have successfully bypassed any authorisation checks. Good going!
Finally, congratulations if you have made it this far in the post. Apologies for it being such a beefy boi. Thank you for reading and have an amazing weekend! Let me know what you think, or if you have any questions then don’t hesitate to ping me a message! 🙂