Android app漏洞挖掘初探(2) - http通信安全场景和危害

在Android中使用SSL/TLS,通过校验服务器端来实现安全通信。(这里指单向SSL/TLS, 与之对应的是双向SSL校验,双向SSL 指的是同时校验客户端和服务端证书), 开发者可以自由实现SSL 通信,然而很多开发者不能恰当的使用SSL协议,导致用户的敏感数据在传输过程中泄露。

漏洞分类:忽略SSL证书校验、忽略域名校验。

  1. 忽略SSL证书校验

在自定义实现X509TrustManager时,checkServerTrusted中没有检查证书是否可信,导致通信过程中可能存在中间人攻击,造成敏感数据劫持危害。由于客户端没有校验服务端的证书,因此攻击者就能与通讯的两端分别创建独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密的连接与对方直接对话,但事实上整个会话都被攻击者完全控制。在中间人攻击中,攻击者可以拦截通讯双方的通话并插入新的内容。

public class MyX509TrustManager implements X509TrustManager {  
    // 检查客户端证书  
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
    }  

    // 检查服务器端证书  
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
    }  

    // 返回受信任的X509证书数组  
    public X509Certificate[] getAcceptedIssuers() {  
        return null;  
    }  
}

在重写WebViewClient的onReceivedSslError方法时,调用proceed忽略证书验证错误信息继续加载页面,导致通信过程中可能存在中间人攻击,造成敏感数据劫持危害。

mywebview.setWebViewClient(new WebviewClient(){

    @Override
    public void onReceivedError(WebView view,int errorCode,String description,String falingUrl){

        // TODO Auto generated method stub
        super.onReceivedError(view,errorCode,description,fallingUrl) ;
    }

    @Override
    public void onReceivedSslError(WebView view,SslErrorHandler handler,SslError error)

        // T0D0 Auto-generated method stub
        handler.proceed( );
    };
});

防护:

建议自定义实现X509TrustManager时,checkServerTrusted中对服务器信息进行严格校验。
针对自定义TrustManager,检查checkServerTrusted()函数是否为空实现。
建议不要重写TrustManager 和HostnameVerifier,使用系统默认的。
在重写WebViewClient的onReceivedSslError方法时,避免调用proceed忽略证书验证。

2. 忽略域名校验

在自定义实现HostnameVerifier时,没有在verify中进行严格证书校验,导致通信过程中可能存在中间人攻击,造成敏感数据劫持危害。

HostnameVerifier hv = new HostnameVerifier (){
    @Override 
        public boolean verify(String hostname,SSLSession session){
        return true;
    }
};

在setHostnameVerifier方法中使用ALLOW_ALL_HOSTNAME _VERIFIER,信任所有Hostname,导致通信过程中可能存在中间人攻击,造成敏感数据劫持危害。

private HttpClient getNewHttpClient() {  
    try {  
            KeyStore trustStore = KeyStore.getInstance(KeyStore  
                   .getDefaultType());  
            trustStore.load(null, null);  
            SSLSocketFactory sf = new SSLSocketFactory(trustStore);  
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);  
            HttpParams params = new BasicHttpParams();  
            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);  
            HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);  
            SchemeRegistry registry = new SchemeRegistry();  
            registry.register(new Scheme("http", PlainSocketFactory  
                    .getSocketFactory(), 80));  
            registry.register(new Scheme("https", sf, 443));  
            ClientConnectionManager ccm = new ThreadSafeClientConnManager(  
                    params, registry);  
            return new DefaultHttpClient(ccm, params);  
        } catch (Exception e) {  
            return new DefaultHttpClient();  
        }  
}

防护:

在自定义实现HostnameVerifier时,在verify中对Hostname进行严格校验。
建议setHostnameVerifier方法中使用STRICT_HOSTNAME VERIFIER进行严格证书校验,避免使用ALLOW ALL.HOSTNAME _VERIFIER.

你可能感兴趣的:(android安全)