最近项目被网络安全局扫出有网络安全问题,提示我们的app有未校验服务器证书漏洞,检测的步骤:在手机上安装抓包工具证书,就可以明文查看我们的app请求接口的报文,刚开始很不解,你都允许授权安装不可信任的证书到你的手机上了,看到你的明文请求报文不是很正常吗?这不是没事找事吗?经过检查发现项目中的代码确实也有不规范的地方,于是就这个机会做出修复动作,鉴于这个问题很难收到,且搜索到的也是一些没用的信息就发个贴记录一下,希望也能帮到遇到同样问题的伙伴。
我们网络不规范的地方就是重写了证书校验逻辑,绕过了证书校验和服务器合法性校验的逻辑。不规范的代码如下:
private static final X509TrustManager DEFAULT_TRUST_MANAGERS = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
// Trust.
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
// Trust.
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
public TLSSocketFactory() {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] {DEFAULT_TRUST_MANAGERS}, new SecureRandom());
delegate = sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
throw new AssertionError(); // The system has no TLS. Just give up.
}
}
上述代码就是重写了证书校验的逻辑,信任所有的证书,正确的逻辑是要校验证书是否是可信任的证书签发机构所认证的,如果不校验的话你虽然是用了https加密传输,只要你的客户端用户信任了其他的证书哪怕是非法的证书,一样能够请求通过,而这个证书的服务器就可以解密你的报文,拿到你的隐私信息了。
另外一个不合规的地方就是重写了域名合法性的校验,不规范的代码如下:
private static final HostnameVerifier HOSTNAME_VERIFIER = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
上述代码是重写了域名校验的逻辑,每个证书里携带的域名是不可更改的,如果证书是合法的证书签发机构签发的,并且域名是和你要请求的域名对的上的,基本上就能确认你访问就服务器地址就是要访问的服务器地址,这样才是安全的。如果你不校验上面两处的信息,别人就有机会拦截你的请求做一些非法事情,所以我们需要修复上面的错误逻辑。
正确的修复办法也很简单,我封装了工具类设置到网络框架的配置里即可。代码如下:
public