Skip to content

Instantly share code, notes, and snippets.

@esafirm
Last active April 17, 2023 00:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save esafirm/1be9ae77530ffd2abda6d9908034fea4 to your computer and use it in GitHub Desktop.
Save esafirm/1be9ae77530ffd2abda6d9908034fea4 to your computer and use it in GitHub Desktop.
Android Nougat Above - Install Certificate to System

For more information https://blog.jeroenhd.nl/article/android-7-nougat-and-certificate-authorities


Ran into this issue as well while trying to check for privacy implications of an app. The blog post and docs linked above does explain what happened, but not how. Source code references follows based on nougat-mr2.3.

The change was made in commit aosp-mirror/platform_frameworks_base@32d2a10, see frameworks/base:core/java/android/security/net/config/NetworkSecurityConfig.java. After that change, only the system root store (/etc/security/cacerts) is considered.

NetworkSecurityConfig.getDefaultBuilder is used in XmlConfigSource.java when parsing the configuration file, if the option is not found in the APK, then it uses that default (which only includes the system root).

XmlConfigSource (and the fallback to getDefaultBuilder) is used in NetworkSecurityConfig, which is used all over the place. And unlike permissions, this configuration does not seem cached in /data/system/.

Editing each APK after installation and upgrades seem fragile...

So let's turn to the alternative since I have root, adding the certificate to the root store in /etc/security/cacerts/. Certificates here are stored based on the hash of the Subject field plus an index number (increasing from 0; in case the same certificate is issues with multiple hash algorithms, e.g. SHA-1 and SHA-256).

$ openssl x509 -noout -subject_hash_old -in ~/.mitmproxy/mitmproxy-ca-cert.pem
c8750f0d

Now you need to copy your PEM-encoded CA file to the system partition, like:

$ adb root
$ adb push ~/.mitmproxy/mitmproxy-ca-cert.pem /etc/security/cacerts/c8750f0d.0
$ adb shell chmod 644 /etc/security/cacerts/c8750f0d.0

In my case, my /system was readonly and I could not write it. So as workaround, I cloned the cacerts directory from system to userdata, added the cert and bind-mounted it over the system directory.

ca=~/.mitmproxy/mitmproxy-ca-cert.pem
hash=$(openssl x509 -noout -subject_hash_old -in $ca)
adb root
adb shell cp -a /etc/security/cacerts /data/
adb push $ca /data/cacerts/$hash.0
adb shell chmod 644 /data/cacerts/$hash.0
adb shell mount --bind /data/cacerts /etc/security/cacerts
adb unroot  # optional: restart adbd as normal user

Restarted the app, and it works! No more "Trust anchor for certification path not found." errors!

Note: this needs to be done once every time you restart the device and want to perform a mitm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment