Frida Android

Network Security Configuration bypasses with Frida (update API 27-29)

Network Security Configuration bypasses with Frida (update API 27-29)

TL;DR In this blogpost I show the update of the analysis on different scripts that executes the bypass of network security configuration with Frida on devices with API 27 to 29.

In the previous post I explain how and why each script works. It is not mandatory to read it before reading this one: https://cmrodriguez.me/blog/nsc-bypass/

It has been a while since I did the first analysis of different scripts used to bypass the network security configuration of Android devices. In the moment I did it we did not have in Genymotion (the VM I use for pentesting) devices with Android 27 and above, so I limited the analysis on the devices with API 24 to 26. Now we can create Android emulated devices till API 29, so I thought it was a good moment to do a review on the scripts I had collected for the first post.

I’ll use the same criteria to execute the analysis as I did before. I created three applications with different network security configurations:

  1. An application that used the default NSC configuration (without network-security-config xml file) - called BypassNSC
  2. An application with a NSC file that used only system certificates - called BypassNSC2.
  3. An application with a NSC file that enforced the certificate pinning - called BypassNSC3.

Each application has three different ways to execure requests:

  • OKHttp (it is also used in retrofit and volley also)
  • HttpsURLConnection
  • WebView (Chromium in API 25 and 26, and Default WebView in API 24).

The scripts I used are the following ones:

  • network-security-config-bypass-1.js
  • network-security-config-bypass-2.js
  • network-security-config-bypass-3.js
  • network-security-config-bypass-cr.js <– this is the one I created

The following github repository has all the applications I developed and the scripts I used.

https://github.com/CesarMRodriguez/network-security-config-frida-2

The following is a screenshot of the table I created with the results of the analysis:

This is an image

network-security-config-bypass-1.js

Original reference: Link

I had to change the network-security-config-bypass-1.js. It threw some errors that in previous version of frida-cli worked. The errors were related to undefined variables. The change to avoid this error was to add in some variable declarations were the let or var modified.

network-security-config-bypass-2.js

Original Reference: Link

I had to change the network-security-config-bypass-2.js. It threw the same kind of errors as in the firs script.

network-security-config-bypass-3.js

Original Reference: Link

In this case I did not need to change anything from the original script

network-security-config-bypass-cr.js

For API 28 and AÏ 29, the original script does not work. There is a change in the signatures of the methods hooked by the library, which throws the following error:

[NSC 28::com.example.bypassnsc]-> Error: ManifestConfigSource$DefaultConfigSource(): specified argument types do not match any of:
    .overload('boolean', 'android.content.pm.ApplicationInfo')
    at ge (frida/node_modules/frida-java-bridge/lib/class-factory.js:584)
    at frida/node_modules/frida-java-bridge/lib/class-factory.js:923
    at /network-security-config-bypass-2.js:16
    at frida/node_modules/frida-java-bridge/lib/vm.js:11
    at frida/node_modules/frida-java-bridge/index.js:446
    at frida/node_modules/frida-java-bridge/index.js:431                                                                                                                                                   
    at je (frida/node_modules/frida-java-bridge/lib/class-factory.js:633)
    at frida/node_modules/frida-java-bridge/lib/class-factory.js:616

The fix was the following one:

if (DefaultConfigSource.$new.argumentTypes[1].className == "android.content.pm.ApplicationInfo") {
    var ApplicationInfo = Java.use("android.content.pm.ApplicationInfo");
    var appInstance = ApplicationInfo.$new();
    appInstance.targetSdkVersion.value = ANDROID_VERSION_M;
    appInstance.targetSandboxVersion.value = 1;
    return DefaultConfigSource.$new(true,appInstance);
  }

The change is neccesary because the constructor of “DefaultConfigSource” changed to the following one:

    DefaultConfigSource(boolean usesCleartextTraffic, ApplicationInfo info) {
        mDefaultConfig = NetworkSecurityConfig.getDefaultBuilder(info)
            .setCleartextTrafficPermitted(usesCleartextTraffic)
            .build();
    }

I also had to set some values in the second parameter (object from class ApplicatoinInfo). In order to see what we need to set, we had to check the implementation of the method getDefaultBuilder from the NetworkSecurityConfig class:

    public static Builder getDefaultBuilder(ApplicationInfo info) {
        Builder builder = new Builder()
                .setHstsEnforced(DEFAULT_HSTS_ENFORCED)
                // System certificate store, does not bypass static pins.
                .addCertificatesEntryRef(
                        new CertificatesEntryRef(SystemCertificateSource.getInstance(), false));
        final boolean cleartextTrafficPermitted = info.targetSdkVersion < Build.VERSION_CODES.P
                && info.targetSandboxVersion < 2;
        builder.setCleartextTrafficPermitted(cleartextTrafficPermitted);
        // Applications targeting N and above must opt in into trusting the user added certificate
        // store.
        if (info.targetSdkVersion <= Build.VERSION_CODES.M && !info.isPrivilegedApp()) {
            // User certificate store, does not bypass static pins.
            builder.addCertificatesEntryRef(
                    new CertificatesEntryRef(UserCertificateSource.getInstance(), false));
        }
        return builder;
    }

we can see that we have to set the “targetSdkVersion” to 23 in order to make the application to import UserCertificateSource, and we need to set targetSandboxVersion to 1, so the clearTextTraffic is set to true.

With this change, the script worked as intended. I also checked the parameter types to make the script compatible with older versions as well.

Conclusion:

The results from the analysis of the scripts used for the network security config bypass show that they are as effective in the newer APIs as they were in the old ones. Two of the scripts works in all scenarios (network-security-config-1.js) and (network-security-config-cr.js).