本文共 4908 字,大约阅读时间需要 16 分钟。
/** * 覆盖java默认的证书验证 */ private static final TrustManager[] TRUSTALLCERTS = new TrustManager[]{ new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[]{}; } @SuppressLint("TrustAllX509TrustManager") public void checkClientTrusted(X509Certificate[] chain, String authType) { } @SuppressLint("TrustAllX509TrustManager") public void checkServerTrusted(X509Certificate[] chain, String authType) { } } }; try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, TRUSTALLCERTS, new java.security.SecureRandom()); //配置自己的信任管理类(信任策略) SSLSocketFactory newFactory = sc.getSocketFactory(); connection.setSSLSocketFactory(newFactory); } catch (Exception e) { e.printStackTrace(); }
如上代码所示,自定义与使用了X509TrustManager子类,但又没有实现信任校验的逻辑时遇,对安全平台扫描APK时,会报如下风险
【漏洞】自定义实现的X509TrustManager子类中,未对服务器端证书做验证,默认接受任意服务端证书,会存在安全风险,可能会导致恶意程序利用中间人攻击绕过证书校验
【修复的建议通常的如下】
利用X509TrustManager子类中的checkServerTrusted函数,校验服务器端证书的合法性
PS:一般自定义信任管理器,通常是使用自签名或android不认可的证书颁发机构SSL证书的业务场景
使用这个方式最麻烦是公钥/证书放置在前端,以及公钥的同步等问题!!!个人的修复建议是
【前提条件】 1、你的SSL证书是由android认可的证书颁发机构或者该结构下属的机构颁发的证书(最关键) 2、使用的https的服务的请求与响应的数据安全性不是那么高(数据不敏感与私密), 3、又不保证服务器的证书是否不会被替换, 那么性价较高且简单明了的方案是不要使用509TrustManager子类!
不要使用509TrustManager子类! 不要使用509TrustManager子类! 即使用默认的系统网络库默认的信任管理/校验方案,系统会使用证书链的信任管理策略
PS:
Android已经把将近150个CA根证书(数字证书认证机构认证过的证书)内置在我们手机中。这150多个证书被全世界信赖
利用chrome打开对应的域名,查看即可
证书详情设置->安全->信任的凭据
说明 : 如下代码copy自
public static SSLSocketFactory getSSLSocketFactory() throws Exception { final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { // 本地公钥信息,实现项目中在考虑该值的更新,否则服务证书一换,之前的端不会能正常工作了 public static final String PUB_KEY = "3082010a0282010100d52ff5dd432b3a05113ec1a7065fa5a80308810e4e181cf14f7598c8d553cccb7d5111fdcdb55f6ee84fc92cd594adc1245a9c4cd41cbe407a919c5b4d4a37a012f8834df8cfe947c490464602fc05c18960374198336ba1c2e56d2e984bdfb8683610520e417a1a9a5053a10457355cf45878612f04bb134e3d670cf96c6e598fd0c693308fe3d084a0a91692bbd9722f05852f507d910b782db4ab13a92a7df814ee4304dccdad1b766bb671b6f8de578b7f27e76a2000d8d9e6b429d4fef8ffaa4e8037e167a2ce48752f1435f08923ed7e2dafef52ff30fef9ab66fdb556a82b257443ba30a93fda7a0af20418aa0b45403a2f829ea6e4b8ddbb9987f1bf0203010001"; @Override public void checkClientTrusted( java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted( java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { if (chain == null) { throw new IllegalArgumentException("checkServerTrusted:x509Certificate array isnull"); } if (!(chain.length > 0)) { throw new IllegalArgumentException("checkServerTrusted: X509Certificate is empty"); } if (!(null != authType && authType.equalsIgnoreCase("RSA"))) { throw new CertificateException("checkServerTrusted: AuthType is not RSA"); } try { TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); tmf.init((KeyStore) null); for (TrustManager trustManager : tmf.getTrustManagers()) { ((X509TrustManager) trustManager).checkServerTrusted(chain, authType); } } catch (Exception e) { throw new CertificateException(e); } RSAPublicKey pubkey = (RSAPublicKey) chain[0].getPublicKey(); String encoded = new BigInteger(1 , pubkey.getEncoded()).toString(16); final boolean expected = PUB_KEY.equalsIgnoreCase(encoded); if (!expected) { throw new CertificateException("checkServerTrusted: Expected public key: " + PUB_KEY + ", got public key:" + encoded); } } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[0]; } }}; final SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); return sslContext .getSocketFactory(); }
转载地址:http://lkmbi.baihongyu.com/