2015-07-03 96 views
2

我剛剛實施證書鎖定下面的教程,我發現。但是現在我注意到它忽略了主機名驗證,上帝知道它忽略了什麼。證書鎖定忽略主機名驗證

這裏是我有:

的SSLSocketFactory:

public class PinningSSLSocketFactory extends SSLSocketFactory { 
    SSLContext sslContext = SSLContext.getInstance("TLS"); 

    PubKeyManager pkm; 

    public PinningSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, 
     KeyStoreException, UnrecoverableKeyException { 
     super(truststore); 

     pkm = new PubKeyManager(); 

     TrustManager tm[] = { pkm }; 

     sslContext.init(null, tm, null); 

    } 

    @Override 
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, 
     UnknownHostException { 
     return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); 
    } 

    @Override 
    public Socket createSocket() throws IOException { 
     return sslContext.getSocketFactory().createSocket(); 
    } 

    public void setContext(Context context) { 
     pkm.setContext(context); 
    } 
} 

X509TrustManager:

public class PubKeyManager implements X509TrustManager { 

    public Context mContext; 

    @Override 
    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {} 

    @Override 
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 

     if (chain == null) { 
      throw new IllegalArgumentException("checkServerTrusted: X509Certificate array is null"); 
     } 

     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"); 
     } 

     // Perform customary SSL/TLS checks 
     // get request cert 
     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); 
     } 

     //get stored certificate 

     expected = //compare both certs 

     if (!expected) { 
      throw new CertificateException("checkServerTrusted"); 
     } 
    } 

    @Override 
    public X509Certificate[] getAcceptedIssuers() { 
     return new X509Certificate[0]; 
    } 

    public void setContext(Context context) { 
     mContext = context; 
    } 
} 

獲得的HttpClient:

public DefaultHttpClient getPinningHttpClient(){ 

    try { 
     KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
     trustStore.load(null, null); 

     PinningSSLSocketFactory sf = new PinningSSLSocketFactory(trustStore); 
     sf.setContext(context); 

     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) { 
     e.printStackTrace(); 
    } 

    return new DefaultHttpClient(); 
} 

我的問題是如何解決日缺少主機名驗證以及其他缺失的驗證,這些驗證可能會以這種方式破壞業務。

感謝您給予的任何幫助。

回答

2

證書/ pubkey固定的想法是,您知道特定的主機具有特定的證書或公鑰。只有當您不知道證書應該是什麼時,才需要驗證主機名和證書鏈。釘住是你與預期同行談話的更有力的證據。但是,當然您應該在應用程序中關聯主機名和固定信息,即不要使用來自一個站點的固定信息來驗證其他站點。

除此之外,不要使用「...我找到的教程」。在OWASP上,您可以找到關於該主題以及示例代碼的good information

+0

我已經基本上遵循該頁面上的示例項目來做我現在擁有的東西。問題在於我們將質量證書放在質量服務器上,即使URL與證書上的URL不匹配,它也會接受請求。 Só我假設使用我的'PinningSSLSocketFactory'已經以某種方式忽略了主機名驗證。如果我使用默認的'SSLSocketFactory'由於主機名驗證,它不允許連接。 –

+0

@HugoAlves:再次 - 釘住是更有力的驗證方法,因爲您知道證書或公鑰。只有在您需要檢查您以前未知的證書是否可信時,才需要驗證鏈和主機名。這意味着可以省略主機名檢查。 –

+0

好的,謝謝你的幫助。感覺這是一個我沒什麼專業知識的領域,我擔心通過將用戶的請求重定向到攻擊者的機器並竊取他們的信息,或者我已經打開了其他攻擊方式,這是一種可能的攻擊方式。我認爲主機名驗證會保護這一點。 –