From def3645a629d1c69c6040692ee93de011e1b1ce0 Mon Sep 17 00:00:00 2001 From: Dennis Titze Date: Tue, 18 Feb 2025 17:57:59 +0100 Subject: [PATCH 1/8] Port mastg test 0022 (by @guardsquare) --- .../0x05g-Testing-Network-Communication.md | 56 ++++++++++++++++++- .../android/MASVS-NETWORK/MASTG-TEST-0022.md | 3 + 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/Document/0x05g-Testing-Network-Communication.md b/Document/0x05g-Testing-Network-Communication.md index 7193f3b053..a623bcaef9 100644 --- a/Document/0x05g-Testing-Network-Communication.md +++ b/Document/0x05g-Testing-Network-Communication.md @@ -88,9 +88,17 @@ The default configuration for apps targeting Android 6.0 (API level 23) and lowe ``` -#### Certificate Pinning +### Certificate Pinning -The Network Security Configuration can also be used to pin [declarative certificates](https://developer.android.com/training/articles/security-config.html#CertificatePinning "Certificate Pinning using Network Security Configuration") to specific domains. This is done by providing a `` in the Network Security Configuration, which is a set of digests (hashes) of the public key (`SubjectPublicKeyInfo`) of the corresponding X.509 certificate. +Certificate pinning is a critical security mechanism employed in Android applications to safeguard against man-in-the-middle (MITM) attacks by ensuring that the app communicates exclusively with servers possessing predefined cryptographic credentials. + +While effective when implemented correctly, insecure implementations potentially enable attackers to read and modify all communication. See @MASWE-0047 for details on impact, modes of introduction and mitigations. + +Various approaches exist, depending on the API level of your app, and on the used libraries. In the following, the most common ones are briefly highlighted. + +#### Pinning via Network Security Configuration (API 24+) + +The Network Security Configuration can also be used to pin [declarative certificates](https://developer.android.com/training/articles/security-config.html#CertificatePinning) to specific domains. This is done by providing a `` in the Network Security Configuration, which is a set of digests (hashes) of the public key (`SubjectPublicKeyInfo`) of the corresponding X.509 certificate. When attempting to establish a connection to a remote endpoint, the system will: @@ -105,7 +113,7 @@ If at least one of the pinned digests matches, the certificate chain will be con - Use certificate pinning for OWASP website access including sub domains + owasp.org owasp.org - + YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg= @@ -127,47 +127,46 @@ If at least one of the pinned digests matches, the certificate chain will be con ``` -!!! note "Backup Pin" - When implementing Certificate Pinning you should always include a backup pin to ensure that the app's connectivity is unaffected, in case you need update the certificate. A backup pin could be the intermediate certificate of the CA. +**Important Considerations:** -!!! note "Expiration dates" - If you [set an expiration date](https://developer.android.com/privacy-and-security/security-config#CertificatePinning), make sure to update your application in time. Otherwise pinning will **not** be performed at all after the configured date. +- **Backup Pins:** Always include a backup pin to maintain connectivity if the primary certificate changes unexpectedly. +- **Expiration Dates:** Set an appropriate [expiration date](https://developer.android.com/privacy-and-security/security-config#CertificatePinning) and ensure timely updates to prevent the app from bypassing pinning after the date has passed. +- **Scope of Application:** Be aware that this configuration applies only to connections made using `HttpsURLConnection` or libraries that rely on it. Other networking libraries or frameworks may require separate pinning implementations. -!!! warning "Technologies not using Network Security Configuration" - If your application uses low level networking APIs or SDKs like Flutter, the Network Security Configuration might not be used by default. In these cases, you will need to enable certificate pinning specifically for the technology used. - For example, applications based on Cordova do not support Certificate Pinning natively, so the plugin [PhoneGap SSL Certificate Checker](https://github.com/EddyVerbruggen/SSLCertificateChecker-PhoneGap-Plugin) can be used. +#### Pinning using Custom TrustManagers -### Certificate Pinning using the OkHttp Library +Before Network Security Configuration became available, the recommended way to implement certificate pinning was to create a custom `TrustManager` (using `javax.net.ssl` APIs) and override the default certificate validation. You can still use this approach on modern Android versions for flexibility or when you need more direct control. -The OkHttp library is widely used for certificate pinning in Android due to its built-in `CertificatePinner` class, which enables developers to pin public key hashes or certificate signatures. This provides robust protection against MITM attacks. +This approach involves: -For example, [CertificatePinner](https://square.github.io/okhttp/features/https/#certificate-pinning-kt-java) can be set up as follows: +1. Loading the server's certificate(s) into a `KeyStore`. +2. Creating a custom `TrustManager` that only trusts the certificate(s) in the `KeyStore`. +3. Initializing an `SSLContext` with the custom `TrustManager`. +4. Applying the custom `SSLContext` as the socket factory for the network connections (e.g., `HttpsURLConnection`). -```java -val client = OkHttpClient.Builder() - .certificatePinner( - CertificatePinner.Builder() - .add("publicobject.com", "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=") - .build()) - .build() -``` +**Important Note:** This is a **low-level approach and is prone to errors** if not done carefully. Some key considerations include: + +- [`SSLSocket` does not automatically verify hostnames](https://developer.android.com/privacy-and-security/security-ssl#WarningsSslSocket), so you must handle this manually using a `HostnameVerifier` with a safe implementation (this includes explicitly checking the return value of `HostnameVerifier.verify()`). More information can be found in the [Android documentation](https://developer.android.com/privacy-and-security/risks/unsafe-hostname). +- [Do **not** include a "trust-all" `TrustManager`](https://developer.android.com/privacy-and-security/security-ssl#UnknownCa) that silently accepts all certificates. This opens the door for attackers to intercept and modify user data with minimal effort. +- Certificates loaded from raw resources can be extracted if someone repackages the APK. As with NSC, that risk is mitigated by Android's APK signing model, though for highly sensitive apps, additional protections (obfuscation, integrity checks) may be warranted. + +#### Pinning using Third-party Libraries -### Certificate Pinning using TrustKit +Several third-party libraries offer built-in support for certificate pinning, simplifying the implementation process in some cases. These libraries typically utilize the custom `TrustManager` method, providing higher-level abstractions and additional features. Notable examples include: -For Android versions prior to API 24, the [TrustKit library](https://github.com/datatheorem/TrustKit-Android) offers a backward-compatible solution. TrustKit validates pins against the cleaned certificate chain. However, improper configuration — such as enabling non-default options like CA pinning — can reintroduce [vulnerabilities akin to custom implementations](https://www.blackduck.com/blog/ineffective-certificate-pinning-implementations.html). +For example, [OkHttp](https://github.com/square/okhttp)'s offers pinning in its `CertificatePinner`. Under the hood, it uses a custom `TrustManager` to enforce pinning rules. -### Custom Certificate Pinning +#### Pinning in WebViews -Certificate pinning can be implemented manually by overriding `TrustManager` or `HostnameVerifier` in [`HttpsURLConnection`](https://developer.android.com/reference/java/net/HttpURLConnection). This approach is highly error-prone, as it often involves directly inspecting server-sent certificates via `getPeerCertificates()`, which returns unvalidated chains that [be manipulated by attackers](https://www.blackduck.com/blog/ineffective-certificate-pinning-implementations.html). +For in-app `WebView` traffic on Android, the easiest approach is to rely on the **Network Security Configuration**. Since Android automatically applies NSC rules to WebView traffic within the same application, any pinning rules you set up in `network_security_config.xml` will also apply to resources loaded in that WebView. -!!! warning "Implementing Certificate Pinning Manually" - Implementing certificate pinning manually has a high risk of adding functionality to your application that makes the app even less secure. If you are adding this manually, take extreme care of implementing this correctly. +If you need additional customization beyond what NSC offers, you could implement pinning by intercepting requests at the WebView level (e.g., using `shouldInterceptRequest`), but in most cases the built-in support is sufficient and simpler. -### Vulnerable Third-Party Libraries +#### Pinning in Native Code -Third-party libraries like older versions of the Secure-HTTP Cordova plugin or misconfigured PhoneGap plugins historically introduced vulnerabilities by [mishandling certificate chains](https://www.blackduck.com/blog/ineffective-certificate-pinning-implementations.html). These libraries often exposed non-default configuration options that, when enabled, allowed attackers to bypass pinning by injecting untrusted certificates into the chain. +It's also possible to implement pinning in [native code](https://developer.android.com/ndk) (C/C++/Rust). By embedding or dynamically verifying certificates within compiled native libraries (`.so` files), you can increase the difficulty of bypassing or modifying the pinning checks via typical APK reverse engineering. -Developers must audit third-party libraries for adherence to chain-validation best practices and prefer those leveraging the Android Keystore system for pinning. +That said, this approach requires significant security expertise and a careful design to manage certificates or public key hashes in native space. Maintenance and debugging also become more complex, so it's generally reserved for high-security apps with specialized needs. ### Security Provider From 8526097bb201fe1554dee3478aa3745849b0db1c Mon Sep 17 00:00:00 2001 From: Dennis Titze Date: Mon, 24 Feb 2025 12:32:05 +0100 Subject: [PATCH 5/8] Add section for frameworks --- Document/0x05g-Testing-Network-Communication.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Document/0x05g-Testing-Network-Communication.md b/Document/0x05g-Testing-Network-Communication.md index 6f3d3a12ec..8706759f90 100644 --- a/Document/0x05g-Testing-Network-Communication.md +++ b/Document/0x05g-Testing-Network-Communication.md @@ -166,7 +166,19 @@ If you need additional customization beyond what NSC offers, you could implement It's also possible to implement pinning in [native code](https://developer.android.com/ndk) (C/C++/Rust). By embedding or dynamically verifying certificates within compiled native libraries (`.so` files), you can increase the difficulty of bypassing or modifying the pinning checks via typical APK reverse engineering. -That said, this approach requires significant security expertise and a careful design to manage certificates or public key hashes in native space. Maintenance and debugging also become more complex, so it's generally reserved for high-security apps with specialized needs. +That said, this approach requires significant security expertise and a careful design to manage certificates or public key hashes in native space. Maintenance and debugging also typically become more complex. + +#### Pinning in Cross-Platform Frameworks + +Cross-platform frameworks like Flutter, React Native, Cordova and Xamarin might require special considerations. Depending on the framework one of the following can apply: + +- The framework might support NSC. This is the case for Flutter apps on Android, but the NSC needs to be enabled specifically for Flutter. See the [Flutter documentation](https://docs.flutter.dev/release/breaking-changes/network-policy-ios-android#migration-guide) on how to enable the network policy. + +- The framework might use other networking libraries under the hood, which need to be configured appropriately. E.g., React Native uses OkHttp on Android, which can be configured with a custom `CertificatePinner`. + +- The framework might offer plugins to perform certificate pinning. This is the case for example for Cordova. + +- The framework might not offer any built-in mechanisms to perform certificate pinning (as it the case for Xamarin). In this case, pinning needs to be implemented manually. ### Security Provider From 06b395f1c662d9d030506aa5373f47caef690e29 Mon Sep 17 00:00:00 2001 From: Dennis Titze Date: Mon, 24 Feb 2025 12:35:32 +0100 Subject: [PATCH 6/8] Add sentence for native code --- Document/0x05g-Testing-Network-Communication.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Document/0x05g-Testing-Network-Communication.md b/Document/0x05g-Testing-Network-Communication.md index 8706759f90..78044a0a81 100644 --- a/Document/0x05g-Testing-Network-Communication.md +++ b/Document/0x05g-Testing-Network-Communication.md @@ -98,7 +98,7 @@ Several approaches to certificate pinning exist, depending on the app's API leve #### Pinning via Network Security Configuration (API 24+) -The Network Security Configuration can be used to pin [declarative certificates](https://developer.android.com/training/articles/security-config.html#CertificatePinning) to specific domains. This is done by providing a `` in the Network Security Configuration, which is a set of digests (hashes) of the public key (`SubjectPublicKeyInfo`) of the corresponding X.509 certificate. +The **Network Security Configuration (NSC)** is the preferred and recommended way to implement certificate pinning in Android, as it provides a declarative, maintainable, and secure approach without requiring code changes. It applies to all network traffic managed by the Android framework within the app, including `HttpsURLConnection`-based connections and `WebView` requests (unless a custom `TrustManager` is used). For communication from native code, NSC does not apply, and other mechanisms need to be considered. When attempting to establish a connection to a remote endpoint, the system will: @@ -172,7 +172,7 @@ That said, this approach requires significant security expertise and a careful d Cross-platform frameworks like Flutter, React Native, Cordova and Xamarin might require special considerations. Depending on the framework one of the following can apply: -- The framework might support NSC. This is the case for Flutter apps on Android, but the NSC needs to be enabled specifically for Flutter. See the [Flutter documentation](https://docs.flutter.dev/release/breaking-changes/network-policy-ios-android#migration-guide) on how to enable the network policy. +- The framework might support NSC. This is the case for Flutter apps on Android, but the NSC needs to be enabled in the `AndroidManifest`. See the [Flutter documentation](https://docs.flutter.dev/release/breaking-changes/network-policy-ios-android#migration-guide) on how to enable the network policy. - The framework might use other networking libraries under the hood, which need to be configured appropriately. E.g., React Native uses OkHttp on Android, which can be configured with a custom `CertificatePinner`. From b7a3b0ef5e53239bbbe7917686aca09dc66e2334 Mon Sep 17 00:00:00 2001 From: titze Date: Tue, 25 Feb 2025 08:04:51 +0100 Subject: [PATCH 7/8] Apply suggestions from code review Co-authored-by: Carlos Holguera --- Document/0x05g-Testing-Network-Communication.md | 2 +- tests-beta/android/MASVS-NETWORK/MASTG-TEST-0241.md | 8 ++++++-- tests-beta/android/MASVS-NETWORK/MASTG-TEST-0242.md | 10 +++++----- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Document/0x05g-Testing-Network-Communication.md b/Document/0x05g-Testing-Network-Communication.md index 78044a0a81..6d839d8dc4 100644 --- a/Document/0x05g-Testing-Network-Communication.md +++ b/Document/0x05g-Testing-Network-Communication.md @@ -90,7 +90,7 @@ The default configuration for apps targeting Android 6.0 (API level 23) and lowe ### Certificate Pinning -Certificate pinning is a critical security mechanism employed in Android applications to safeguard against man-in-the-middle (MITM) attacks by ensuring that the app communicates exclusively with servers possessing predefined cryptographic credentials. +[Certificate pinning](0x04f-Testing-Network-Communication.md/#restricting-trust-identity-pinning) can be employed in Android apps to safeguard against Machine-in-the-Middle (MITM) attacks by ensuring that the app communicates exclusively with remote endpoints possessing specific identities. While effective when implemented correctly, insecure implementations potentially enable attackers to read and modify all communication. For more general details on pinning, refer to @MASWE-0047. diff --git a/tests-beta/android/MASVS-NETWORK/MASTG-TEST-0241.md b/tests-beta/android/MASVS-NETWORK/MASTG-TEST-0241.md index 99d4f0eff7..78bd5cc0a1 100644 --- a/tests-beta/android/MASVS-NETWORK/MASTG-TEST-0241.md +++ b/tests-beta/android/MASVS-NETWORK/MASTG-TEST-0241.md @@ -1,5 +1,5 @@ --- -title: Expired Certificate Pins +title: Expired Certificate Pins in the Network Security Configuration platform: android id: MASTG-TEST-0241 type: [static] @@ -8,7 +8,11 @@ weakness: MASWE-0047 ## Overview -Apps can configure expiration dates for pinned certificates in the [Network Security Configuration]("../../../Document/0x05g-Testing-Network-Communication.md#certificate-pinning"). After the expiration date, the pin is no longer used and all installed CAs for that domain are trusted. +Apps can configure expiration dates for pinned certificates in the [Network Security Configuration (NSC)]("../../../Document/0x05g-Testing-Network-Communication.md#certificate-pinning") by using the `expiration` attribute. When a pin expires, the app no longer enforces certificate pinning and instead relies on its configured trust anchors. This means the connection will still succeed if the server presents a valid certificate from a trusted CA (such as a system CA or a custom CA defined in the app's configuration). However, if no trusted certificate is available, the connection will fail. + +If developers assume pinning is still in effect but don't realize it has expired, the app may start trusting CAs it was never intended to. + +> Example: A financial app previously pinned to its own private CA but, after expiration, starts trusting publicly trusted CAs, increasing the risk of compromise if a CA is breached. The goal of this test is to check if any expiration date is in the past. diff --git a/tests-beta/android/MASVS-NETWORK/MASTG-TEST-0242.md b/tests-beta/android/MASVS-NETWORK/MASTG-TEST-0242.md index 8b2a88815c..11146f316e 100644 --- a/tests-beta/android/MASVS-NETWORK/MASTG-TEST-0242.md +++ b/tests-beta/android/MASVS-NETWORK/MASTG-TEST-0242.md @@ -2,17 +2,17 @@ title: Missing Certificate Pinning in Network Traffic platform: network id: MASTG-TEST-0x242 -type: [static] +type: [network] weakness: MASWE-0047 --- ## Overview -There are various ways how certificate pinning can be done for an application. +There are multiple ways an application can implement certificate pinning, including via the Android Network Security Config, custom TrustManager implementations, third-party libraries, and native code. Since some implementations might be difficult to identify through static analysis, especially when obfuscation or dynamic code loading is involved, this test uses network interception techniques to determine if certificate pinning is enforced at runtime. -Since statically finding all of the locations where certificate pinning is performed might not be feasible, this test case uses dynamic analysis to observe all connections the app makes. +The goal of this test case is to observe whether a [MITM attack]("../../../Document/0x04f-Testing-Network-Communication.md#mitm-attack) can intercept HTTPS traffic from the app. A successful MITM interception indicates that the app is either not using certificate pinning or implementing it incorrectly. -The goal of this test case is to dynamically check if the connection to a server can be intercepted using a [Man-in-the-Middle attack]("../../../Document/0x04f-Testing-Network-Communication.md#mitm-attack). If this is possible, it means that the certificate is not pinned correctly or not pinned at all. +If the app is properly implementing certificate pinning, MITM should fail because the app would reject certificates issued by an unauthorized CA, even if the CA is trusted by the system. ## Steps @@ -22,7 +22,7 @@ The goal of this test case is to dynamically check if the connection to a server ## Observation -The output should contain a list domains, for which the interception was successful. +The output should contain a list of domains for which the interception was successful. ## Evaluation From a20152feae2c5daff805df81a3397763093f1de3 Mon Sep 17 00:00:00 2001 From: Dennis Titze Date: Tue, 25 Feb 2025 08:31:17 +0100 Subject: [PATCH 8/8] Review comments --- .../android/MASVS-NETWORK/MASTG-TEST-0240.md | 16 ++++------------ .../android/MASVS-NETWORK/MASTG-TEST-0242.md | 4 ++-- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/tests-beta/android/MASVS-NETWORK/MASTG-TEST-0240.md b/tests-beta/android/MASVS-NETWORK/MASTG-TEST-0240.md index c6b3fab785..154e571ff4 100644 --- a/tests-beta/android/MASVS-NETWORK/MASTG-TEST-0240.md +++ b/tests-beta/android/MASVS-NETWORK/MASTG-TEST-0240.md @@ -1,5 +1,5 @@ --- -title: Missing Certificate Pinning in Code +title: Missing Certificate Pinning in Network Security Configuration platform: android id: MASTG-TEST-0240 type: [static] @@ -10,14 +10,6 @@ weakness: MASWE-0047 Apps can configure certificate pinning using the [Network Security Configuration]("../../../Document/0x05g-Testing-Network-Communication.md#certificate-pinning"). For each domain, one or multiple digests can be pinned. -Certificate pinning can also be done manually in the code. Depending on the used technologies, this can be done for example by: - -- Pinning a certificate with a custom `TrustManager`, -- configuring the used third party networking libraries to pin certificates, -- use plugins to achieve certificate pinning for hybrid apps. - -Chapter [Certificate pinning without Android Network Security Configuration]("../../../Document/0x05g-Testing-Network-Communication.md#certificate-pinning-without-android-network-security-configuration") explains in more detail how this can be achieved in the app. - The goal of this test is to check if any certificate pinning exists. !!! note "Limitations" @@ -26,8 +18,8 @@ The goal of this test is to check if any certificate pinning exists. ## Steps 1. Reverse engineer the app (@MASTG-TECH-0017). -2. Inspect the AndroidManifest.xml, and check if a `networkSecurityConfig` is set in the `` tag. If yes, inspect the referenced file, and all domains which have a pinned certificate. -3. Run a static analysis tool such as @MASTG-TOOL-0011 or @MASTG-TOOL-0018 on the code and look for APIs or configurations performing certificate pinning (see above). Extract all domains for which the certificates are pinned. +2. Inspect the AndroidManifest.xml, and check if a `networkSecurityConfig` is set in the `` tag. +3. Inspect the referenced network security config file, and extract all domains which have a pinned certificate. ## Observation @@ -35,4 +27,4 @@ The output should contain a list of domains which enable certificate pinning. ## Evaluation -The test case fails if any relevant domain does not enable certificate pinning. +The test case fails if no `networkSecurityConfig` is set, or any relevant domain does not enable certificate pinning. diff --git a/tests-beta/android/MASVS-NETWORK/MASTG-TEST-0242.md b/tests-beta/android/MASVS-NETWORK/MASTG-TEST-0242.md index 11146f316e..52cdea79e2 100644 --- a/tests-beta/android/MASVS-NETWORK/MASTG-TEST-0242.md +++ b/tests-beta/android/MASVS-NETWORK/MASTG-TEST-0242.md @@ -1,7 +1,7 @@ --- title: Missing Certificate Pinning in Network Traffic platform: network -id: MASTG-TEST-0x242 +id: MASTG-TEST-0242 type: [network] weakness: MASWE-0047 --- @@ -12,7 +12,7 @@ There are multiple ways an application can implement certificate pinning, includ The goal of this test case is to observe whether a [MITM attack]("../../../Document/0x04f-Testing-Network-Communication.md#mitm-attack) can intercept HTTPS traffic from the app. A successful MITM interception indicates that the app is either not using certificate pinning or implementing it incorrectly. -If the app is properly implementing certificate pinning, MITM should fail because the app would reject certificates issued by an unauthorized CA, even if the CA is trusted by the system. +If the app is properly implementing certificate pinning, the MITM attack should fail because the app rejects certificates issued by an unauthorized CA, even if the CA is trusted by the system. ## Steps