Mar 6, 2025 von Stefan Bernhardsgrütter
Mobile applications are an integral part of everyday life, often handling sensitive data such as personal messages, financial information, or digital credentials. Ensuring these apps are secure is paramount. At Redguard, we specialize in mobile application penetration testing, identifying vulnerabilities before attackers can exploit them. To conduct thorough assessments, we leverage the OWASP Mobile Application Security (MAS) framework, which provides comprehensive coverage of mobile security topics. While existing «Crackme» apps provide valuable training for security professionals, they are not always aligned with real-world vulnerabilities. To address this gap, we created the MAS Reference App, which implements a broad range of MAS-defined weaknesses and defense-in-depth techniques. Read this blog post to find out more about its key features and how it supports security testing and development.
Given the complexity of mobile security, Redguard continuously invests in advanced tools to enhance the efficiency and quality of our penetration tests. This includes maintaining tools such as our Mobile Testing Lab and developing automated solutions for vulnerability analysis. The MAS Reference App supports the development of these tools further.
The MAS Reference App is designed to illustrate common mobile security weaknesses categorized under the MAS framework. The following images show the app in action:
The app interface presents different security categories. Upon selecting a category, users can explore various security topics. For example, in the «Storage» category, Android-specific topics like SharedPreferences and Java File API are listed, while iOS-specific topics will be displayed on Apple devices only. The terminal at the bottom provides feedback on executed tests.
The tests align with the Mobile Application Security Weakness Enumeration (MASWE), which categorizes common vulnerabilities. Below is an overview of these categories and how our app addresses them:
MASWE Category | Description |
---|---|
Storage | Mobile apps often store sensitive data. This can be done in various ways. For example, the location of the data storage can have an impact on the security of the data. Also, sensitive data can escape the app's sandbox using insecure backups or misconfigured logging. These tests implement common issues found in this category. |
Crypto | Tests in this category focus on the lifecycle management of cryptographic material, including key properties, storage, and protection against unauthorized access during runtime. They also cover the use of insecure cryptographic primitives, such as improperly configured ciphers. |
Auth | Local authentication, including biometrics, PINs, and passwords, plays a vital role in mobile app security. However, implementations of these methods offer varying levels of security. The tests in this category go through the different risks associated with them. |
Network | This category is designed to ensure that the mobile app sets up secure connections under any circumstances. Specifically, it focuses on verifying that the app establishes a secure, encrypted channel for network communication. Additionally, this category covers situations where a developer may choose to trust only specific Certificate Authorities (CAs), which is commonly referred to as certificate or public key pinning. |
Platform | This category includes tests for vulnerabilities arising from insecure interactions with the mobile platform. These tests cover platform-provided IPC mechanisms, insecure WebView configurations that may lead to sensitive data leakage and functionality exposure, and the display of sensitive data in the app’s user interface. |
Code | This category covers coding vulnerabilities that arise from external sources such as app data entry points, the OS, and third-party software components. The use cases also cover the enforcement of app updates and checks to ensure the app runs on up-to-date platforms, protecting users from known vulnerabilities. |
Resilience | The tests in this category aim to ensure that the app is running on a trusted platform, prevent tampering at runtime and ensure the integrity of the app’s intended functionality. Due to the nature of the category, the absence of these controls in an application is the risk. |
Privacy | Mobile apps can access a variety of personal data under certain circumstances. These tests simulate apps which try to access these information. |
Tests within each category can reveal insecure configurations or practices. For example, storing sensitive data in external storage is a known vulnerability. Conversely, some tests verify the presence of security features — where the absence of a test could indicate a risk. To better understand these different objectives, let’s explore a few use cases:
Security testing often involves a mix of static and dynamic analysis, particularly when dealing with obfuscated code. To enhance automation, we develop tools that detect common vulnerabilities. However, validating these tools requires test environments that mirror real-world apps. Although, tools such as Crackme applications exist, their focus is generally limited to implementing challenges like root detection bypass or providing introductory lessons on dynamic instrumentation. In contrast, our approach extends beyond these areas. So let’s explore a few questions penetration testers ask themselves during a mobile app test:
Some of these questions can be answered by simple static code analysis others are not so easy for example if the code is heavily obfuscated. In this case, it’s often helpful to look at how the application interacts with the operating system API, since those can’t be hidden. Let us take the creation of key material on Android as an example to see how the MAS Reference App can be used to develop a dynamic check for such a weakness. When creating new keys, the developer creates a KeyGenParameterSpec
which defines the key’s parameters. These parameters have an effect on how secure the key is. For example, it is possible to create keys with weak key sizes. But it is also possible to define whether the key must be stored in secure storage or how the user must authenticate before accessing the key.
Now we want to develop a dynamic check which automatically detects the creation of weak keys, but also warns us, if additional security measures are not configured. This can be done with Frida.Re. By using dynamic instrumentation, we can intercept the Android methods setKeySize(int keySize)
or setUserAuthenticationParameters (int timeout, int type)
of the KeyGenParameterSpec.Builder
class in order to detect configurations which weaken or enhance security. Now we can use our dynamic check while the application is running. The creation of weak keys is detected if the method setKeySize
is called. The absence of hardening the key can be detected if the method setUserAuthenticationParameters
is not called during the runtime. However, in both cases the check needs to know exactly what pattern to look for.
Of course, it would be possible to simply take a look at the documentation and only code against the specification without really verifying it properly. However, this approach is usually more error-prone compared to actual tests against a real target. Now we can test our check against the MAS Reference App, which we know has a specific weakness or a defined defense-in-depth implementation.
We can also use it to test and enhance our Frida.Re scripts, a dynamic sandbox or log analyzer, and also static scanners that try to find insecure hard-coded secrets.
Developers frequently ask us, «How can I ensure my app is secure?». The answer is usually complex and depends on an app specific threat model. But no matter what the answer for a specific app is, we think every developer should have an understanding of the different areas mobile app security is important. Redguard therefore also offers trainings for developers.
The MAS Reference App gives a great security overview for developers. As part of a daily workshop, we use the Android app in a virtual machine for exercises. The participants use the app to get a firm understanding on how data is really stored when using the file API, how to attack weak local authentication or to see how much effort it takes to bypass different kinds of code obfuscation.
For new colleagues joining Redguard, we provide structured onboarding programs and the MAS Reference App plays a key role in our internal mobile security training. Similar to the way we teach developers, we can use the MAS Reference App to educate ourselves - and so can you! While it is not (yet) a fully functional Crackme, it can help penetration testers to understand how mistakes can happen and how to spot them in a real application. Also, the app can be used as a real world checklist when implementing defense-in-depth mechanisms such as device integrity validation.
If you read this far, you must be interested in how the application works under the hood. So let’s take a look at it. The MAS Reference App is built using React Native for its cross-platform interface, while security tests are implemented in native Java, Kotlin, Objective-C, or Swift. We don’t want to get too technical here, but we’d like to show you how new use cases can be added:
React Native builds on TypeScript. Hence, we can define the tests according to the following type:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
type MASCategory = {
key: string;
color: string;
description: string;
tests: TestGroup[];
};
type TestGroup = {
title: string;
description: string;
testCases: TestCase[];
maswe?: string;
};
type TestCase = {
title: string;
description?: string;
nativeFunction: any;
maswe?: string;
};
You can compare these tests to the initial figure of this blog post, and you should see the matching structure from the category on the left side with each test case on the right side.
A new test case is defined by a title, description and optional MSWE ID and the name of the native function. Some of the tests are shared between Android and iOS, while others are not. To avoid overhead, we split the tests into the following categories:
The following example shows an excerpt from the Android tests:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
var androidTestCases: Dictionary<TestGroup[]> = {
CRYPTO: [
{
title: 'KeyGenParameterSpec',
description:
'This class represents properties for cryptographic keys. It is used when creating keys within the' +
'Android KeyStore for example. Since the security of the cryptography is also depending on secure ' +
'key properties, a misconfigured KeyGenParameterSpec may be the source of a security risk.',
testCases: [
{
title: 'Set Weak Key Size',
maswe: '0009',
description:
'Sets a weak size (in bits) of the key to be generated. ',
nativeFunction: CryptoKeyGenParameterSpec.setWeakKey,
},
{
title: 'Set to Exportable',
maswe: '0014',
description:
'Forces the key not to be stored in the StrongBox HSM using setIsStrongBoxBacked(false). Such a' +
'key can now be accessed form within the application.',
nativeFunction: CryptoKeyGenParameterSpec.setExportable,
},
{
title: 'Configure User Authorization',
maswe: '0018',
description:
'By default, there is no timeout on how long a key can be accessed if user authentication is required.' +
'This use case configures this using setUserAuthenticationParameters (int timeout, int type).',
nativeFunction: CryptoKeyGenParameterSpec.configureUserAuth,
},
{
title: 'Configure User Authorization (legacy)',
maswe: '0018',
description:
'By default, there is no timeout on how long a key can be accessed if user authentication is required.' +
'This use case configures this using setUserAuthenticationValidityDurationSeconds (int seconds).',
nativeFunction: CryptoKeyGenParameterSpec.configureUserAuthLegacy,
},
],
},
],
[...]
};
export default androidTestCases;
The test itself must be implemented in native code. For example, the following Kotlin code is called when the Test Case with the title Configure User Authorization is called:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@ReactMethod(isBlockingSynchronousMethod = true)
fun configureUserAuth(): String {
val r = ReturnStatus()
val b = KeyGenParameterSpec.Builder("masRefAppKeyAlias", KeyProperties.PURPOSE_ENCRYPT)
b.setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG)
r.success("Configured that user must authenticate each time before accessing the key and STRONG BIOMETRY is required.")
b.setUserAuthenticationParameters(0, KeyProperties.AUTH_DEVICE_CREDENTIAL)
r.success("Configured that user must authenticate each time before accessing the key and DEVICE CREDENTIAL is required.")
return r.toJsonString()
}
The React Native GUI will update all elements such as buttons, description tool tip and terminal automatically.
In summary, if you want to add a new test case, do the following:
For further details, visit the source code repository.
While the MAS Reference App is a valuable security testing resource, we also want to talk about what the application is not:
We are very excited to finally release this app and receive feedback from fellow security professionals, developers, or anyone interested in mobile security. Feel free to download the source code, give feedback or talk to us about future mobile penetration testing or mobile-related developer trainings. You can reach us by email or at our contact page.