1

I am currently trying to analyse the requests made from the official Home Connect app.

I am however running against a very weird problem, most requests pass through Charles decrypted (due to the FRIDA "ssl-unpinner" script being attached to the app), however, some requests don't.

My setup is as follows:

A real android device rooted with Magisk running the frida server and the app, having its proxy configured to proxy through Charles.

Frida is then told to attach to the app with the following script:

/* 
   Android SSL Re-pinning frida script v0.2 030417-pier 

   $ adb push burpca-cert-der.crt /data/local/tmp/cert-der.crt
   $ frida -U -f it.app.mobile -l frida-android-repinning.js --no-pause

   https://techblog.mediaservice.net/2017/07/universal-android-ssl-pinning-bypass-with-frida/
   
   UPDATE 20191605: Fixed undeclared var. Thanks to @oleavr and @ehsanpc9999 !
*/

setTimeout(function(){
    Java.perform(function (){
        console.log("");
        console.log("[.] Cert Pinning Bypass/Re-Pinning");

        var CertificateFactory = Java.use("java.security.cert.CertificateFactory");
        var FileInputStream = Java.use("java.io.FileInputStream");
        var BufferedInputStream = Java.use("java.io.BufferedInputStream");
        var X509Certificate = Java.use("java.security.cert.X509Certificate");
        var KeyStore = Java.use("java.security.KeyStore");
        var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory");
        var SSLContext = Java.use("javax.net.ssl.SSLContext");

        // Load CAs from an InputStream
        console.log("[+] Loading our CA...")
        var cf = CertificateFactory.getInstance("X.509");
        
        try {
            var fileInputStream = FileInputStream.$new("/data/local/tmp/cert-der.crt");
        }
        catch(err) {
            console.log("[o] " + err);
        }
        
        var bufferedInputStream = BufferedInputStream.$new(fileInputStream);
        var ca = cf.generateCertificate(bufferedInputStream);
        bufferedInputStream.close();

        var certInfo = Java.cast(ca, X509Certificate);
        console.log("[o] Our CA Info: " + certInfo.getSubjectDN());

        // Create a KeyStore containing our trusted CAs
        console.log("[+] Creating a KeyStore for our CA...");
        var keyStoreType = KeyStore.getDefaultType();
        var keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);
        
        // Create a TrustManager that trusts the CAs in our KeyStore
        console.log("[+] Creating a TrustManager that trusts the CA in our KeyStore...");
        var tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        var tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);
        console.log("[+] Our TrustManager is ready...");

        console.log("[+] Hijacking SSLContext methods now...")
        console.log("[-] Waiting for the app to invoke SSLContext.init()...")

        SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").implementation = function(a,b,c) {
            console.log("[o] App invoked javax.net.ssl.SSLContext.init...");
            SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").call(this, a, tmf.getTrustManagers(), c);
            console.log("[+] SSLContext initialized with our custom TrustManager!");
        }
    });
},0);

I know it works, because when I visit a website in Chrome, it doesn't warn me about insecure HTTPS, and it proudly displays it has verified the SSL connection to be safe (see screenshot one).

The problem

I can see one of the OAuth2 requests made from the app in Charles (see screenshot two), this is the request that serves the OAuth2 login page.

Screenshot three shows the request I am actually interested in (the authorization_code being turned in for an access and refresh token), failing with "handshake_failure (40) - Unable to negotiate an acceptable set of security parameters, this probably means there are no cipher suites in common".

The cipher suite used in the good and in the failing request are both "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", so I don't think that's the problem.

Do you have a clue what's going on? Is this some kind of unknown and weird way to really force the SSL certificate to match a stored one? I am clueless. Any help would be appreciated.

Thank you!

Screenshots

Screenshot 1 Screenshot 1

Screenshot 2 Screenshot 2

Screenshot 3 Screenshot 3

Eli Saado
  • 53
  • 1
  • 5
  • I do not understand you well, What's your goal, do you want to intercept the network requests – Jimale Abdi Jul 04 '20 at 22:11
  • Hey, thanks for replying. Yes, that's what I want to do, I am already doing that nut as you can see, it is not working for some requests. – Eli Saado Jul 05 '20 at 07:44
  • I have no experience in **charles-proxy** , I used **burp suite** so try burp suite – Jimale Abdi Jul 05 '20 at 08:09
  • Charles and Burp ab both Java based. For Java the JVM determines the supported cipher suites, hence there will be no difference. The servers for api.home-connect.com are pretty old one only supporting [ECDHE cipher for TLS 1.2](https://www.ssllabs.com/ssltest/analyze.html?d=api.home-connect.com&s=35.157.197.253). EC based cipher are known to [make problems on a lot of OpenJDK Java versions on Linux](https://stackoverflow.com/questions/54922389). – Robert Jul 05 '20 at 09:47
  • @Robert which proxy would you recommend? – Eli Saado Jul 05 '20 at 14:47
  • You can try mitmproxy. It is python based and therefore has a different list of supported ciphers. Or you can try to configure Java/Charles/Burp to allow one of the `TLS_RSA_WITH_AES_128...` ciphers shown in the SSL test result page I had linked in my last comment. – Robert Jul 05 '20 at 15:35
  • Hey @Robert, I tried using mitmproxy and it does the exact same thing, except it doesn't show the failed request, it just completely ignores and hides it, am I missing something? – Eli Saado Jul 07 '20 at 10:10
  • Are you sure that the app does not use a custom certificate pinning your Frida code can not disable? I would check the app code using Jadx and apktool. – Robert Jul 07 '20 at 10:17
  • Thanks again for your response Robert, most of the code is obfuscated which is very annoying. I am going to try looking through the code. – Eli Saado Jul 07 '20 at 11:11

0 Answers0