daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

install-burp-certificate.md (15622B)


      1 ---
      2 title: "Install Burp Certificate"
      3 section: "Mobile"
      4 sectionSlug: "mobile-pentesting"
      5 sourcePath: "src/mobile-pentesting/android-app-pentesting/install-burp-certificate.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/mobile-pentesting/android-app-pentesting/install-burp-certificate.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Install Burp Certificate
     14 
     15 ## System-wide proxy via ADB
     16 
     17 Configure a global HTTP proxy so all apps route traffic through your interceptor (Burp/mitmproxy):<sup>[[6]](#references)</sup>
     18 
     19 ```bash
     20 # Set proxy (device/emulator must reach your host IP)
     21 adb shell settings put global http_proxy 192.168.1.2:8080
     22 
     23 # Clear proxy
     24 adb shell settings put global http_proxy :0
     25 ```
     26 
     27 Tip: In Burp, bind your listener to 0.0.0.0 so devices on the LAN can connect (Proxy -> Options -> Proxy Listeners).
     28 
     29 ## On a Virtual Machine
     30 
     31 First of all you need to download the Der certificate from Burp. You can do this in _**Proxy**_ --> _**Options**_ --> _**Import / Export CA certificate**_
     32 
     33 ![Clear proxy - On a Virtual Machine: First of all you need to download the Der certificate from Burp. You can do this in Proxy -- Options -- Import / Export CA certificate](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28367%29.png)
     34 
     35 **Export the certificate in Der format** and lets **transform** it to a form that **Android** is going to be able to **understand.** Note that **in order to configure the burp certificate on the Android machine in AVD** you need to **run** this machine **with** the **`-writable-system`** option.\
     36 For example you can run it like:
     37 
     38 ```bash
     39 C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -http-proxy 192.168.1.12:8080 -writable-system
     40 ```
     41 
     42 Then, to **configure burps certificate do**:
     43 
     44 ```bash
     45 openssl x509 -inform DER -in burp_cacert.der -out burp_cacert.pem
     46 CERTHASHNAME="`openssl x509 -inform PEM -subject_hash_old -in burp_cacert.pem | head -1`.0"
     47 mv burp_cacert.pem $CERTHASHNAME #Correct name
     48 adb root && sleep 2 && adb remount #Allow to write on /syste
     49 adb push $CERTHASHNAME /sdcard/ #Upload certificate
     50 adb shell mv /sdcard/$CERTHASHNAME /system/etc/security/cacerts/ #Move to correct location
     51 adb shell chmod 644 /system/etc/security/cacerts/$CERTHASHNAME #Assign privileges
     52 adb reboot #Now, reboot the machine
     53 ```
     54 
     55 Once the **machine finish rebooting** the burp certificate will be in use by it!
     56 
     57 ## Using Magisk
     58 
     59 If you **rooted your device with Magisk** (maybe an emulator), and you **can't follow** the previous **steps** to install the Burp cert because the **filesystem is read-only** and you cannot remount it writable, there is another way.
     60 
     61 Explained in [**this video**](https://www.youtube.com/watch?v=qQicUW0svB8) you need to:<sup>[[7]](#references)</sup>
     62 
     63 1. **Install a CA certificate**: Just **drag&drop** the DER Burp certificate **changing the extension** to `.crt` in the mobile so it's stored in the Downloads folder and go to `Install a certificate` -> `CA certificate`
     64 
     65 <figure><img src="https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%2853%29.png" alt="" width="164"><figcaption></figcaption></figure>
     66 
     67 - Check that the certificate was correctly stored going to `Trusted credentials` -> `USER`
     68 
     69 <figure><img src="https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%2854%29.png" alt="" width="334"><figcaption></figcaption></figure>
     70 
     71 2. **Make it System trusted**: Download the Magisk module [MagiskTrustUserCerts](https://github.com/NVISOsecurity/MagiskTrustUserCerts) (a .zip file), **drag&drop it** in the phone, go to the **Magisk app** in the phone to the **`Modules`** section, click on **`Install from storage`**, select the `.zip` module and once installed **reboot** the phone:
     72 
     73 <figure><img src="https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%2855%29.png" alt="" width="345"><figcaption></figcaption></figure>
     74 
     75 - After rebooting, go to `Trusted credentials` -> `SYSTEM` and check the Postswigger cert is there
     76 
     77 <figure><img src="https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%2856%29.png" alt="" width="314"><figcaption></figcaption></figure>
     78 
     79 ### Rooted Play Store AVD workflow (no Frida required)
     80 
     81 If you need to intercept traffic from **Google Play** emulator images, remember that these AVDs are **production builds**: `adb root` normally fails, but you can still root them with **rootAVD + Magisk** and then inject the proxy CA at runtime. This is useful when the app trusts the Android system store but ignores **user** CAs.<sup>[[1]](#references)</sup>
     82 
     83 1. Root the matching Play Store image (`google_apis_playstore`) with **rootAVD**, cold boot it, finish the **Magisk** setup, and verify root from ADB:<sup>[[2]](#references)</sup>
     84 
     85 ```bash
     86 adb shell
     87 su
     88 whoami   # root
     89 ```
     90 
     91 2. Prepare the proxy CA in Android's **system CA** naming format (`<subject_hash_old>.0`). Burp exports DER directly; Caido usually exports PEM first:
     92 
     93 ```bash
     94 # Burp DER -> Android CA filename
     95 openssl x509 -inform DER -subject_hash_old -in cacert.der | head -1
     96 mv cacert.der <hash>.0
     97 
     98 # Caido PEM -> DER -> Android CA filename
     99 openssl x509 -in ca.crt -outform DER -out caido.der
    100 openssl x509 -inform DER -subject_hash_old -in caido.der | head -1
    101 mv caido.der <hash>.0
    102 
    103 adb push <hash>.0 /storage/self/primary/
    104 ```
    105 
    106 3. Run the **Post Android 14** bind-mount technique below as `root` so `/system/etc/security/cacerts` is overlaid with `tmpfs`, the original certs are restored, the new CA is added, and the modified directory is bind-mounted into `/apex/com.android.conscrypt/cacerts` for **Zygote/Zygote64** and already running apps.
    107 
    108 4. This change is **runtime only** on the emulator: after every reboot, rerun the CA-injection script **before** testing. Then point the device at Burp/Caido with `adb shell settings put global http_proxy <ip>:<port>` and clear it later with `adb shell settings put global http_proxy :0`.
    109 
    110 This bypasses trust decisions that rely only on the Android system CA store, but it is **not** a universal unpinning technique: apps with hardcoded/public-key/native pinning can still require [Frida hooks or patching](/hacktricks/mobile-pentesting/android-app-pentesting/android-anti-instrumentation-and-ssl-pinning-bypass).
    111 
    112 ### Alternative: AlwaysTrustUserCerts (Android 7-16 Beta)
    113 
    114 If you're on Android 14+ (or on older devices that received Conscrypt Mainline updates and now use `/apex/com.android.conscrypt/cacerts`), the Magisk module **AlwaysTrustUserCerts** automates the bind-mounting required for system trust. It mirrors user CAs into system trust and injects mounts into Zygote/app namespaces so apps see the certs without manual `nsenter` work.<sup>[[4]](#references)[[5]](#references)</sup>
    115 
    116 1. Install the Burp CA as a **user** cert first.
    117 2. Install the module and reboot.
    118 3. If the module offers a choice, prefer `--rbind` when mounting `/system/etc/security/cacerts` into `/apex/com.android.conscrypt/cacerts` to ensure nested mounts (from other modules) are visible.
    119 
    120 ### Learn how to create a Magisk module
    121 
    122 Check [https://medium.com/@justmobilesec/magisk-for-mobile-pentesting-rooting-android-devices-and-building-custom-modules-part-ii-22badc498437](https://medium.com/@justmobilesec/magisk-for-mobile-pentesting-rooting-android-devices-and-building-custom-modules-part-ii-22badc498437)
    123 
    124 ## Post Android 14
    125 
    126 In the latest Android 14 release, a significant shift has been observed in the handling of system-trusted Certificate Authority (CA) certificates.
    127 
    128 Note: Some Android 12/13 devices that received **Conscrypt Mainline** updates already use `/apex/com.android.conscrypt/cacerts`. If that directory exists on your device, you must use the same APEX injection technique described below.<sup>[[4]](#references)</sup>
    129 
    130 Previously, these certificates were housed in **`/system/etc/security/cacerts/`**, accessible and modifiable by users with root privileges, which allowed immediate application across the system. However, with Android 14, the storage location has been moved to **`/apex/com.android.conscrypt/cacerts`**, a directory within the **`/apex`** path, which is immutable by nature.
    131 
    132 Attempts to remount the **APEX cacerts path** as writable are met with failure, as the system does not allow such operations. Even attempts to unmount or overlay the directory with a temporary file system (tmpfs) do not circumvent the immutability; applications continue to access the original certificate data regardless of changes at the file system level. This resilience is due to the **`/apex`** mount being configured with PRIVATE propagation, ensuring that any modifications within the **`/apex`** directory do not affect other processes.
    133 
    134 The initialization of Android involves the `init` process, which, upon starting the operating system, also initiates the Zygote process. This process is responsible for launching application processes with a new mount namespace that includes a private **`/apex`** mount, thus isolating changes to this directory from other processes.
    135 
    136 Nevertheless, a workaround exists for those needing to modify the system-trusted CA certificates within the **`/apex`** directory. This involves manually remounting **`/apex`** to remove the PRIVATE propagation, thereby making it writable. The process includes copying the contents of **`/apex/com.android.conscrypt`** to another location, unmounting the **`/apex/com.android.conscrypt`** directory to eliminate the read-only constraint, and then restoring the contents to their original location within **`/apex`**. This approach requires swift action to avoid system crashes. To ensure system-wide application of these changes, it is recommended to restart the `system_server`, which effectively restarts all applications and brings the system to a consistent state.<sup>[[3]](#references)</sup>
    137 
    138 ```bash
    139 # Create a separate temp directory, to hold the current certificates
    140 # Otherwise, when we add the mount we can't read the current certs anymore.
    141 mkdir -p -m 700 /data/local/tmp/tmp-ca-copy
    142 
    143 # Copy out the existing certificates
    144 cp /apex/com.android.conscrypt/cacerts/* /data/local/tmp/tmp-ca-copy/
    145 
    146 # Create the in-memory mount on top of the system certs folder
    147 mount -t tmpfs tmpfs /system/etc/security/cacerts
    148 
    149 # Copy the existing certs back into the tmpfs, so we keep trusting them
    150 mv /data/local/tmp/tmp-ca-copy/* /system/etc/security/cacerts/
    151 
    152 # Copy our new cert in, so we trust that too
    153 mv $CERTIFICATE_PATH /system/etc/security/cacerts/
    154 
    155 # Update the perms & selinux context labels
    156 chown root:root /system/etc/security/cacerts/*
    157 chmod 644 /system/etc/security/cacerts/*
    158 chcon u:object_r:system_file:s0 /system/etc/security/cacerts/*
    159 
    160 # Deal with the APEX overrides, which need injecting into each namespace:
    161 
    162 # First we get the Zygote process(es), which launch each app
    163 ZYGOTE_PID=$(pidof zygote || true)
    164 ZYGOTE64_PID=$(pidof zygote64 || true)
    165 # N.b. some devices appear to have both!
    166 
    167 # Apps inherit the Zygote's mounts at startup, so we inject here to ensure
    168 # all newly started apps will see these certs straight away:
    169 for Z_PID in "$ZYGOTE_PID" "$ZYGOTE64_PID"; do
    170     if [ -n "$Z_PID" ]; then
    171         nsenter --mount=/proc/$Z_PID/ns/mnt -- \
    172             /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
    173     fi
    174 done
    175 
    176 # Then we inject the mount into all already running apps, so they
    177 # too see these CA certs immediately:
    178 
    179 # Get the PID of every process whose parent is one of the Zygotes:
    180 APP_PIDS=$(
    181     echo "$ZYGOTE_PID $ZYGOTE64_PID" | \
    182     xargs -n1 ps -o 'PID' -P | \
    183     grep -v PID
    184 )
    185 
    186 # Inject into the mount namespace of each of those apps:
    187 for PID in $APP_PIDS; do
    188     nsenter --mount=/proc/$PID/ns/mnt -- \
    189         /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts &
    190 done
    191 wait # Launched in parallel - wait for completion here
    192 
    193 echo "System certificate injected"
    194 ```
    195 
    196 ### Bind-mounting through NSEnter
    197 
    198 1. **Setting Up a Writable Directory**: Initially, a writable directory is established by mounting a `tmpfs` over the existing non-APEX system certificate directory. This is achieved with the following command:
    199 
    200 ```bash
    201     mount -t tmpfs tmpfs /system/etc/security/cacerts
    202 ```
    203 
    204 2. **Preparing CA Certificates**: Following the setup of the writable directory, the CA certificates that one intends to use should be copied into this directory. This might involve copying the default certificates from `/apex/com.android.conscrypt/cacerts/`. It's essential to adjust the permissions and SELinux labels of these certificates accordingly.
    205 3. **Bind Mounting for Zygote**: Utilizing `nsenter`, one enters the Zygote's mount namespace. Zygote, being the process responsible for launching Android applications, requires this step to ensure that all applications initiated henceforth utilize the newly configured CA certificates. The command used is:
    206 
    207 Tip: If `/system/etc/security/cacerts` contains nested mounts (common with Magisk modules), use `--rbind` instead of `--bind` so those mounts propagate into app namespaces.<sup>[[4]](#references)</sup>
    208 
    209 ```bash
    210 nsenter --mount=/proc/$ZYGOTE_PID/ns/mnt -- /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
    211 # If /system/etc/security/cacerts includes nested mounts, prefer --rbind
    212 nsenter --mount=/proc/$ZYGOTE_PID/ns/mnt -- /bin/mount --rbind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
    213 ```
    214 
    215 This ensures that every new app started will adhere to the updated CA certificates setup.
    216 
    217 4. **Applying Changes to Running Apps**: To apply the changes to already running applications, `nsenter` is again used to enter each app's namespace individually and perform a similar bind mount. The necessary command is:
    218 
    219 ```bash
    220 nsenter --mount=/proc/$APP_PID/ns/mnt -- /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
    221 ```
    222 
    223 5. **Alternative Approach - Soft Reboot**: An alternative method involves performing the bind mount on the `init` process (PID 1) followed by a soft reboot of the operating system with `stop && start` commands. This approach would propagate the changes across all namespaces, avoiding the need to individually address each running app. However, this method is generally less preferred due to the inconvenience of rebooting.
    224 
    225 ## References
    226 
    227 - [1] [Bypassing SSL Pinning on Play Store AVDs without Frida](https://www.mfumis.com/posts/bypassing-ssl-pinning-on-play-store-avds-without-frida/)
    228 - [2] [rootAVD](https://gitlab.com/newbit/rootAVD)
    229 - [3] [Android 14: Install a system CA certificate on a rooted device](https://httptoolkit.com/blog/android-14-install-system-ca-certificate/)
    230 - [4] [Intercepting traffic on Android with Mainline and Conscrypt](https://blog.nviso.eu/2025/06/05/intercepting-traffic-on-android-with-mainline-and-conscrypt/)
    231 - [5] [AlwaysTrustUserCerts Magisk module](https://github.com/NVISOsecurity/AlwaysTrustUserCerts)
    232 - [6] [Build a Repeatable Android Bug Bounty Lab: Emulator vs Magisk, Burp, Frida, and Medusa](https://www.yeswehack.com/learn-bug-bounty/android-lab-mobile-hacking-tools)
    233 - [7] [Root Android Studio Device with Magisk and Install Burp Certificate as System cert in (4 Easy Steps)](https://www.youtube.com/watch?v=qQicUW0svB8)