Reputation: 3353
I'm trying to run an Android Virtual Device
from Android Studio. Everything works fine, until I try to access any Google's service from inside the virtual device. Our network is using corporate proxy and we have to install corporate certificates in order the applications to work. I installed the certificates to Java(jdk) via keytool -importcert -trustcacerts ...
, then installed it to Android\Android Studio\jre\bin
the same way. Then uploaded the certs into the virtual machine using adb push C:\certs\cert1.cer /sdcard/cert1.cer
, and applied it in the Android in settings. But I'm still getting the error
Caused by: javax.net.ssl.SSLHandshakeException: Unacceptable certificate: CN=CompanyName Root CA, OU=IT Department, O='CompanyName Professional' LLC, L=NY, ST=NY, C=EN
Is it real to bypass anyhow? And why does it still ask for the certificate if I already have it imported. In browser all websites work fine if open it in the virtual machine. Thanx.
Upvotes: 9
Views: 31413
Reputation: 42575
Installing your root CA certificate as "User defined certificate" into the emulator is the wrong way for modern Android devices (Android 6+).
User installed CA certificates are by default not trusted by apps. On a rooted device you can install new CA certificates as system certificates as shown here:
If your device is rooted and has Magisk installed you can also use the Magisk Move Certificates module that moves user installed certificates into the system store.
Since Google introduced the Android Network Security Configuration every app has to explicitly add the user defined certificates to the trust list:
res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config>
<trust-anchors>
<certificates src="system"/>
<certificates src="user"/>
</trust-anchors>
</base-config>
</network-security-config>
Every app that does not define a Android Network Security Configuration or that have such a configuration but do not include the <certificates src="user"/>
entry will ignore your additionally installed certificate.
And make sure the AndroidManifest.xml
contains the android:networkSecurityConfig
attribute in the <application>
tag:
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config"
... >
...
</application>
</manifest>
Additionally some apps (e.g. Google services and Play Store) perform certificate/key pinning which totally prevents breaking the HTTPS traffic unless the system is heavily modified:
You have to root the device and install LSPosed/Xposed + multiple modules to allow SSL/TLS interception like TrustMeAlready and SSL Unpinning).
Alternatively you can use Frida and certain scripts for disabling SSL/TLS certificate checking and some pinning implementations. As far as I know the Frida based Objection project contains some SSL unpinning script(s).
Upvotes: 9
Reputation: 939
For anyone that encounters this error, I got this error on an Android Xamarin App and it was do to the date & time of the device out of sync.
Upvotes: 12
Reputation: 629
public class HttpsTrustManager implements X509TrustManager {
private static TrustManager[] trustManagers;
private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{};
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
public boolean isClientTrusted(X509Certificate[] chain) {
return true;
}
public boolean isServerTrusted(X509Certificate[] chain) {
return true;
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return _AcceptedIssuers;
}
public static void allowAllSSL() {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
SSLContext context = null;
if (trustManagers == null) {
trustManagers = new TrustManager[]{new HttpsTrustManager()};
}
try {
context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
HttpsURLConnection.setDefaultSSLSocketFactory(context
.getSocketFactory());
}
}
HttpsTrustManager.allowAllSSL();
Upvotes: 9