23

Is there a way to install CA certificate (.crt file) under the Security -> Trusted Credential -> User tab via ADB? or any other "scriptable" way.

Nir Duan
  • 6,164
  • 4
  • 24
  • 38
  • did you solved the problem ? – Incepter Oct 04 '17 at 14:21
  • The only way to install certificate silently is via Device Policy Manager, and only apps (.apks) can register as DPM, so sadly after long research I reached a dead end.@MohamedELAYADI – Nir Duan Oct 04 '17 at 15:49
  • I figured out a way to do this; openssl x509 -inform PEM -subject_hash_old -in charles-proxy-ssl-proxying-certificate.pem | head -1>toto set /p totoVar= %totoVar% echo %totoVar% openssl x509 -inform PEM -text -in charles-proxy-ssl-proxying-certificate.pem -out nul >> %totoVar% adb shell mount -o rw,remount,rw /system adb push %totoVar% /system/etc/security/cacerts/ adb shell mount -o ro,remount,ro /system adb reboot – Incepter Oct 04 '17 at 16:23
  • If you're interested in this being easier, star the Google issue here: https://issuetracker.google.com/issues/168169729?pli=1 – Tim Perry Apr 11 '22 at 07:12

7 Answers7

25

I figured out a way to do this, thus i was able to trust charles proxy certificate. it will be added as trusted SSL root certificate.

First you need to get the certificate hash

openssl x509 -inform PEM -subject_hash_old -in charles-proxy-ssl-proxying-certificate.pem | head -1>hashedCertFile

i use windows, store it in a var in a matter to automate the process

set /p certHash=<hashedCertFile
    

set certHash=%certHash%.0 && DEL toto
cat charles-proxy-ssl-proxying-certificate.pem > %certHash%

openssl x509 -inform PEM -text -in charles-proxy-ssl-proxying-certificate.pem -out nul >> %certHash%

adb shell mount -o rw,remount,rw /system

adb push %certHash% /system/etc/security/cacerts/

adb shell mount -o ro,remount,ro /system

adb reboot

This is the unix version copied from this answer:

PEM_FILE_NAME=logger-charles-cert.pem
hash=$(openssl x509 -inform PEM -subject_hash_old -in $PEM_FILE_NAME | head -1)
OUT_FILE_NAME="$hash.0"

cp $PEM_FILE_NAME $OUT_FILE_NAME
openssl x509 -inform PEM -text -in $PEM_FILE_NAME -out /dev/null >> $OUT_FILE_NAME

echo "Saved to $OUT_FILE_NAME"
adb shell mount -o rw,remount,rw /system
adb push $OUT_FILE_NAME /system/etc/security/cacerts/
adb shell mount -o ro,remount,ro /system
adb reboot
Incepter
  • 2,711
  • 15
  • 33
  • "adb shell mount -o rw,remount,rw /system" not correct, you should use "adb shell mount -o rw,remount /system" – SelenUser Oct 18 '18 at 08:09
  • 1
    I have to also set the cert's permission to 644 to make it work. Otherwise the cert is not recognized. – wddd Jun 03 '20 at 05:09
  • @Incepter I do not see, where the certificate is installed? I see that PEM certificate being pushed into the cacerts folder. – Ralf Wickum Aug 20 '21 at 13:00
  • 2
    `adb shell mount -o rw,remount,rw /system` -> `mount: '/system' not in /proc/mounts` – Dr.jacky Jan 14 '23 at 14:23
21

Thanks to this answer Install User Certificate Via ADB I was able to adapt a script that works on a bash shell:

PEM_FILE_NAME=logger-charles-cert.pem
hash=$(openssl x509 -inform PEM -subject_hash_old -in $PEM_FILE_NAME | head -1)
OUT_FILE_NAME="$hash.0"

cp $PEM_FILE_NAME $OUT_FILE_NAME
openssl x509 -inform PEM -text -in $PEM_FILE_NAME -out /dev/null >> $OUT_FILE_NAME

echo "Saved to $OUT_FILE_NAME"
adb shell mount -o rw,remount,rw /system
adb push $OUT_FILE_NAME /system/etc/security/cacerts/
adb shell mount -o ro,remount,ro /system
adb reboot

(Yes, I know this should probably be a comment, but I don't have enough reputation to post it as a comment yet)

0x8BADF00D
  • 7,138
  • 2
  • 41
  • 34
Brian Mirletz
  • 211
  • 2
  • 4
  • 1
    I got this error. ./ssl_pinning.sh: line 3: !!: command not found head: cert_name=.0: No such file or directory – Gorio Nov 04 '18 at 23:39
  • @Gorio you might find [this script](https://gist.github.com/cbachert/e580f1ac06ce196a9831beda349fcfa3) helpful. You will surely need to update it a bit (I couldn't copy the resulting file to the /system partition of the AVD but was successful with Genymotion). – Sufian Nov 23 '18 at 11:30
  • there are too many `ro` and `rw` in your remount commands – BLuFeNiX Apr 14 '22 at 20:59
11

I was able to get a server cert to show up under the Trusted Credential -> User tab (rather than the system tab, which other answers show) with the following steps:

#!/bin/bash
subjectHash=`openssl x509 -inform PEM -subject_hash_old -in server.crt | head -n 1`
openssl x509 -in server.crt -inform PEM -outform DER -out $subjectHash.0
adb root
adb push ./$subjectHash.0 /data/misc/user/0/cacerts-added/$subjectHash.0
adb shell "su 0 chmod 644 /data/misc/user/0/cacerts-added/$subjectHash.0"
adb reboot
EmpireJones
  • 2,936
  • 4
  • 29
  • 43
  • +1 tested on lineages android 10, works like a charm. do not forget to click on "trust" in `Trusted Credential -> User` after reboot – Hannes Tiltmann Jan 12 '21 at 14:44
5

2022: httptoolkit has a good solution to inject a custom cert without rebooting into rooted devices/emulators

Details here: https://httptoolkit.tech/blog/intercepting-android-https/#injecting-ca-certificates-into-rooted-devices

    set -e # Fail on error
    # Create a separate temp directory, to hold the current certificates
    # Without this, when we add the mount we can't read the current certs anymore.

    mkdir -m 700 /data/local/tmp/htk-ca-copy
    # Copy out the existing certificates

    cp /system/etc/security/cacerts/* /data/local/tmp/htk-ca-copy/
    # Create the in-memory mount on top of the system certs folder

    mount -t tmpfs tmpfs /system/etc/security/cacerts
    # Copy the existing certs back into the tmpfs mount, so we keep trusting them

    mv /data/local/tmp/htk-ca-copy/* /system/etc/security/cacerts/
    # Copy our new cert in, so we trust that too

    mv ${certificatePath} /system/etc/security/cacerts/
    # Update the perms & selinux context labels, so everything is as readable as before

    chown root:root /system/etc/security/cacerts/*
    chmod 644 /system/etc/security/cacerts/*
    chcon u:object_r:system_file:s0 /system/etc/security/cacerts/*
    # Delete the temp cert directory & this script itself

    rm -r /data/local/tmp/htk-ca-copy
    rm ${injectionScriptPath}
    echo "System cert successfully injected"

Source

spartanz51
  • 311
  • 3
  • 9
5

Push file to device

adb push "C:\path\cacert.cer" "/data/local"

Start the CertInstaller

adb shell am start -n com.android.certinstaller/.CertInstallerMain -a android.intent.action.VIEW -t application/x-x509-ca-cert -d file:///data/local/cacert.cer

Now finish installing with the prompt that will appear on your device.

hogarth45
  • 3,387
  • 1
  • 22
  • 27
  • 2
    I tried this on my Wear OS watch (Fossil Gen 6). adb does not have permission to upload on "/data/local/", but it is possible to upload to "/data/local/tmp/". And here are the possible MIME types: * application/x-x509-ca-cert * application/x-x509-user-cert * application/x-x509-server-cert * application/x-pem-file * application/pkix-cert * application/x-pkcs12 * application/x-wifi-config – Fulkerson Aug 07 '22 at 08:16
  • Same as @Fulkerson. Mine was forced to set a Screen Lock before being able to install the cert. is there any way to not set Screen Lock? – Dr.jacky Jan 08 '23 at 14:29
  • @Fulkerson Did you manage to install the certificates on your watch? When running the command I see the UI on the watch but then after tapping OK there's an error toast. When connecting with ADB, the exception is: `W CertInstaller: android.content.ActivityNotFoundException: Unable to find explicit activity class {com.android.settings/com.android.settings.security.CredentialStorage}; have you declared this activity in your AndroidManifest.xml?` – virtualdj Jul 16 '23 at 13:12
0

In my case, I first needed to start the emulator as writable:

adb start-server
emulator -writable-system -avd Pixel_2_API_24

Then you can install certificate:

adb root
adb remount
adb push c8750f0d.0 /system/etc/security/cacerts

https://docs.mitmproxy.org/stable/howto-install-system-trusted-ca-android

Zombo
  • 1
  • 62
  • 391
  • 407
0

This only launches the "do you want to trust this certificate window" on a non-rooted android. It is the answer by @hoghart45 except with a line that ensures you have permission to paste your certificate into the /data/local/.. directory:

certificateName=ca.crt
ca_dir_in_phone="/data/local/tmp/try3"
ca_path_in_phone="$ca_dir_in_phone/$certificateName"

adb shell mkdir -m 700 "$ca_dir_in_phone"
adb push "$certificateName" "$ca_path_in_phone"

adb shell am start -n com.android.certinstaller/.CertInstallerMain -a android.intent.action.VIEW -t application/x-x509-ca-cert -d file://"$ca_path_in_phone"

enter image description here

For completeness, here is a WIP Python project WIP that also automates clicking "OK" in a controlled fashion using uiautomator. (It verifies it is the ok button before clicking, it does not just send a blind enter, like the send keyevent 20 command). Disclaimer, I am involved with that project.

a.t.
  • 2,002
  • 3
  • 26
  • 66