HTTPS鏈接過程以及中間人攻擊劫持

一 、HTTPS鏈接過程及中間人攻擊原理

https協議就是http+ssl協議,以下圖所示爲其鏈接過程: 
這裏寫圖片描述
1.https請求 
客戶端向服務端發送https請求; 
2.生成公鑰和私鑰 
服務端收到請求以後,生成公鑰和私鑰。公鑰至關因而鎖,私鑰至關因而鑰匙,只有私鑰纔可以打開公鑰鎖住的內容; 
3.返回公鑰 
服務端將公鑰(證書)返回給客戶端,公鑰裏面包含有不少信息,好比證書的頒發機構、過時時間等等; 
4.客戶端驗證公鑰 
客戶端收到公鑰以後,首先會驗證其是否有效,如頒發機構或者過時時間等,若是發現有問題就會拋出異常,提示證書存在問題。若是沒有問題,那麼就生成一個隨機值,做爲客戶端的密鑰,而後用服務端的公鑰加密; 
5.發送客戶端密鑰 
客戶端用服務端的公鑰加密密鑰,而後發送給服務端。 
6.服務端收取密鑰,對稱加密內容 
服務端收到通過加密的密鑰,而後用私鑰將其解密,獲得客戶端的密鑰,而後服務端把要傳輸的內容和客戶端的密鑰進行對稱加密,這樣除非知道密鑰,不然沒法知道傳輸的內容。 
7.加密傳輸 
服務端將通過加密的內容傳輸給客戶端。 
8.獲取加密內容,解密 
客戶端獲取加密內容後,用以前生成的密鑰對其進行解密,獲取到內容。web

中間人劫持攻擊

https也不是絕對安全的,以下圖所示爲中間人劫持攻擊,中間人能夠獲取到客戶端與服務器之間全部的通訊內容。 
這裏寫圖片描述
中間人截取客戶端發送給服務器的請求,而後假裝成客戶端與服務器進行通訊;將服務器返回給客戶端的內容發送給客戶端,假裝成服務器與客戶端進行通訊。 
經過這樣的手段,即可以獲取客戶端和服務器之間通訊的全部內容。 
使用中間人攻擊手段,必需要讓客戶端信任中間人的證書,若是客戶端不信任,則這種攻擊手段也沒法發揮做用。安全

2、中間人攻擊的預防服務器

形成中間人劫持的緣由是 沒有對服務端證書及域名作校驗或者校驗不完整,爲了方便,直接採用開源框架默認的校驗方式進行https請求網絡

如volleyapp

OKhttp3.0框架

預防方法:優化

預防方式有兩種ui

1 、針對安全性要求比較高的 app,可採起客戶端預埋證書的方式鎖死證書,只有當客戶端證書和服務端的證書徹底一致的狀況下才容許通訊,如一些銀行類的app,但這種方式面臨一個問題,證書過時的問題,因證書有必定的有效期,當預埋證書過時了,只有經過強制更新或者要求用戶下載證書來解決。加密

以volley爲例:校驗的實現方式以下spa

 

經過預埋證書建立 SSLSocketFactory;

private static SSLSocketFactory buildSSLSocketFactory(Context context,
                                                      int certRawResId) {
    KeyStore keyStore = null;
    try {
        keyStore = buildKeyStore(context, certRawResId);
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
    TrustManagerFactory tmf = null;
    try {
        tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    }

    SSLContext sslContext = null;
    try {
        sslContext = SSLContext.getInstance("TLS");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    try {
        sslContext.init(null, tmf.getTrustManagers(), null);
    } catch (KeyManagementException e) {
        e.printStackTrace();
    }

    return sslContext.getSocketFactory();

生成 通過ssl校驗及 域名校驗的connection

2 針對安全性要求通常的app,可採用經過校驗域名,證書有效性、證書關鍵信息及證書鏈的方式

以volley爲例,重寫HTTPSTrustManager 中的checkServerTrusted 方法,同時開啓域名強校驗

 

 

三 Webview的HTTPS安全

 

目前不少應用都用webview加載H5頁面,若是服務端採用的是可信CA頒發的證書,在 webView.setWebViewClient(webviewClient) 時重載 WebViewClient的onReceivedSslError() ,若是出現證書錯誤,直接調用handler.proceed()會忽略錯誤繼續加載證書有問題的頁面,若是調用handler.cancel()能夠終止加載證書有問題的頁面,證書出現問題了,能夠提示用戶風險,讓用戶選擇加載與否,若是是須要安全級別比較高,能夠直接終止頁面加載,提示用戶網絡環境有風險:

不建議直接用handler.proceed()。若是webview加載https須要強校驗服務端證書,能夠在 onPageStarted() 中用 HttpsURLConnection 強校驗證書的方式來校驗服務端證書,若是校驗不經過中止加載網頁。固然這樣會拖慢網頁的加載速度,須要進一步優化,具體優化的辦法不在本次討論範圍,這裏也不詳細講解了。

相關文章
相關標籤/搜索