How to get charles proxy work with Android 7 nougat?

AndroidSslAndroid 7.0-Nougat

Android Problem Overview


Android 7 introduced some changes to the way certificates are handled (http://android-developers.blogspot.com/2016/07/changes-to-trusted-certificate.html) and somehow I cannot make my Charles proxy work any more.

My network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config>
        <trust-anchors>
            <certificates src="system" />
        </trust-anchors>
    </base-config>
    <debug-overrides>
        <trust-anchors>
            <certificates src="user" />
        </trust-anchors>
    </debug-overrides>
</network-security-config>

I'm running in debug mode. But no matter what, I get javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found..

Needless to say, I did install a pfx certificate from Settings -> Security -> Install from storage. The certificate shows in User Credentials but not in Trusted credentials -> User. On my lollipop device, the certificates are listed there.

I'm using okhttp3 as HTTP library.

Any idea what I am doing wrong ?

Android Solutions


Solution 1 - Android

The solution is do not use .p12, just navigate with Chrome (with configured proxy on wifi) to http://charlesproxy.com/getssl and install downloaded .pem file.

I had exactly the same problem on my Nexus 5X running Android 7.0. There was previously exported .p12 from Charles 3.11.5 (Help->SSL Proxying->Export Charles Root certificate and Private key). When I tried to install .p12 from phone (Settings->Security->Install from storage) it appears only under "User credentials" and never at "Trusted credentials", and of course SSL with Charles proxy did not work.

The total "how-to" for Android 7.0 would be like that:

  1. Configure WiFi + proxy (how Charles requires it). Connect it.
  2. On device, navigate with Chrome to http://charlesproxy.com/getssl, accept request for download .pem, then press "open", it launches "Certificate installer" app. Use it to install the certificate as "VPN and apps".
  3. Put the attribute android:networkSecurityConfig="@xml/network_security_config" to <application> at Manifest.xml
  4. Create res/xml/network_security_config.xml with content from the first post (it is totally correct).
  5. Launch Charles and app and have fun.

P.S. Check date/time on the device. It should be correct.

Solution 2 - Android

Based on the troubleshooting thread of comments for the OP, the answer is to install just the proxy's CA cert as trusted, not its cert + private key.

The issue was caused by two factors:

  1. Installing not just the MiTM proxy's CA cert but also its private key (thus enabling VPN apps on the device to decrypt/MiTM network traffic from other apps). You don't need the MiTM proxy's private key on the device.

  2. Android Nougat change in behavior of the Settings -> Security -> Install from storage flow for files which contain a private key in addition to cert(s). This change in behavior unmasked the above issue.

Prior to Nougat, the Settings -> Security -> Install from storage flow for files containing a private key in addition to certs erroneously installed the certs as trusted for server authentication (e.g., HTTPS, TLS, thus making your MiTM succeed), in addition to being correctly installed as client certs used for authenticating this Android device to servers. In Nougat, the bug was fixed and these certs are no longer installed as trusted for server authentication. This prevents client authentication credentials from affecting (weaking) the security of connections to servers. In your scenario, this prevents your MiTM from succeeding.

What complicates matters is that the Settings -> Security -> Install from storage does not provide an explicit way for the user to specify whether they are installing a client authentication credential (private key + cert chain) or a server authentication trust anchor (just a CA cert -- no private key needed). As a result, the Settings -> Security -> Install from storage flow guesses whether it's dealing with client/user authentication credential or server authentication trust anchor by assuming that, if a private key is specified, it must be a client/user authentication credential. In your case, it incorrectly assumed that you are installing a client/user authentication credential rather than a server authentication trust anchor.

P. S. With regards to your Network Security Config, you should probably configure the app to also trust "system" trust anchors in debug mode (debug-overrides section). Otherwise debug builds of the app won't work unless connections are MiTM'd by a proxy whose CA cert is installed as trusted on the Android device.

Solution 3 - Android

For me SSL proxy was not working in release build variant. In debug worked.

Solution 4 - Android

I also had the same error and tried every way until I read the following message which was key: "The certificate shows in User Credentials but not in Trusted credentials".

So the problem was how to make the certificate appear there and these were the steps I followed:

  1. Download the certificate in the emulator from http://chls.pro/ssl
  2. Install the certificate & Trust
  • Setting app -> Security -> Encryption & Credentials -> Install a Certificate -> Select CA Certificate option
  • Select Install Anyway

enter image description here

  • Select Charles Proxy Certificate that you downloaded on your storage
  1. Verify that you're trusted the certificate
  • Open Trusted Credentials -> User Tab and you can see your certificate here enter image description here
  1. Start intercepting HTTPS Traffic

Solution 5 - Android

I'm on Android 7.1.1, here's how I setup on my device (OnePlus One) - without the change of manifest (I was targeting API 21 for my app):

In Charles Proxy:

  1. Help > SSL Proxying > Install Charles Root Certificate on a Mobile Device or Remote Browser. This steps gives you the proxy IP and port number and also the link to where you should download charles proxy SSL.

On your phone:

  1. Wifi Settings > Modify Network > Advanced Options. Set Proxy to Manual and enter the IP and Port number you received from Charles into Proxy hostname and Proxy port respectively.

  2. (OPTIONAL) You may or may not be able to access the chls.pro/ssl link provided by Charles earlier. On my device, I was always notified that I had no network connection. I added the charlesproxy.com to the Bypass proxy for field.

  3. On your browser, go to the link in step 3 and download whatever certificate necessary (if it doesn't work on Chrome, download Dolphin Browser).You can name your certificate with whatever name.

Back on Charles Proxy:

  1. You should get the prompt to either Allow or Deny your phone to use the proxy if your settings is defaulted to prompt you for remote connections.

You can now use Charles on Nougat 7.1.1.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmbonninView Question on Stackoverflow
Solution 1 - AndroidAlexander SkvortsovView Answer on Stackoverflow
Solution 2 - AndroidAlex KlyubinView Answer on Stackoverflow
Solution 3 - AndroidkrekerView Answer on Stackoverflow
Solution 4 - AndroidJorge CasariegoView Answer on Stackoverflow
Solution 5 - AndroidTiffanyView Answer on Stackoverflow