http 與 https
https 跟 http 的最大區(qū)別在于 https 多加了一個(gè)保障通訊安全的層.
- https協(xié)議需要到ca申請證書,一般免費(fèi)證書很少耘纱,需要交費(fèi).
- http是超文本傳輸協(xié)議艳馒,信息是明文傳輸员寇,https 則是具有安全性的ssl加密傳輸協(xié)議蝶锋。
- http和https使用的是完全不同的連接方式,用的端口也不一樣扳缕,前者是80慌闭,后者是443。
- http的連接很簡單躯舔,是無狀態(tài)的驴剔;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議粥庄,比http協(xié)議安全丧失。
SSL 證書
Transport Layer Security
Secure Sockets Layer 其實(shí)它就包含倆部分:
- 一個(gè)身份標(biāo)識(shí), 一個(gè)用來識(shí)別身份的東西, 有點(diǎn)類似警察叔叔通過護(hù)照或駕照查你的身份;
- 一個(gè)公共密鑰, 這個(gè)用來給數(shù)據(jù)加密, 而且只有證書的持有者才能解密.
SSL 證書就倆個(gè)功能, 身份驗(yàn)證跟保障通訊過程中的數(shù)據(jù)安全.
另外還有一點(diǎn)很重要. 那就是一個(gè)證書可以給另外一個(gè)證書“簽字”. 用 layman 的話說就是 Bob 用他自己的證書在別的證書上蓋上 “同意” 兩個(gè)紅紅的大字. 如果你信任 Bob (當(dāng)然還有他的證書), 那么你也可以信任由他簽發(fā)的證書. 在這個(gè)例子中, Bob 搖身一變, 成了證書頒發(fā)機(jī)構(gòu)(Certificate Authority). 現(xiàn)在主流的瀏覽器都自帶一大堆受信任證書頒發(fā)機(jī)構(gòu)(trusted Certificate Authorities)(比如:Thawte, Verisign等).
瀏覽器是怎么使用證書的
籠統(tǒng)的講, 當(dāng)你打開下列連接的時(shí)候 “https://www.yoursite.com” :
- 服務(wù)器會(huì)給瀏覽器發(fā)一個(gè)證書.
- 瀏覽器會(huì)對(duì)比證書中的“common name”(有時(shí)也叫 “subject”) 跟服務(wù)器的域名是否一樣. 例如, 一個(gè)從“www.yoursite.com” 網(wǎng)站發(fā)過來的證書就應(yīng)該有一個(gè)內(nèi)容是 “www.yoursite.com” 的 common name, 否則瀏覽器就會(huì)提示該證書有問題.
- 瀏覽器驗(yàn)證證書真?zhèn)? 有點(diǎn)像門衛(wèi)通過證件上的全息圖辨別你的證件是不是真的. 既然在現(xiàn)實(shí)生活中有人偽造別人的身份. 那么在網(wǎng)絡(luò)世界也就有人造假, 比如用你的域名“www.yoursite.com” 來偽造一個(gè)安全證書. 瀏覽器在驗(yàn)證的時(shí)候, 會(huì)檢查這個(gè)證書是否是它信任機(jī)構(gòu)頒發(fā)的, 如果不是, 那么瀏覽器就會(huì)提示這個(gè)證書可能有問題. 當(dāng)然, 用戶可以選擇無視警告, 繼續(xù)使用.
- 一旦證書通過驗(yàn)證 (或是用戶無視警告, 繼續(xù)使用有問題的證書), 瀏覽器就開始利用證書中的公開密鑰加密數(shù)據(jù)并傳給服務(wù)器.
TLS (SSL)中的加密
一旦服務(wù)器發(fā)過來的證書通過驗(yàn)證, 客戶端就會(huì)利用證書中包含的公共密鑰加密某個(gè)指定的共享密鑰, 然后發(fā)給服務(wù)器. 這個(gè)加密過的共享密鑰只能用服務(wù)器的私有密鑰才能解密(非對(duì)稱加密), 別人無法解密出其中的內(nèi)容. 服務(wù)器把解密出來的共享密鑰保存起來, 供本次連接會(huì)話專用. 從現(xiàn)在開始, 服務(wù)器跟客戶端之間的所有通訊信息都用這個(gè)共享密鑰加密解密(對(duì)稱加密).
漏洞描述
對(duì)于數(shù)字證書相關(guān)概念、Android 里 https 通信代碼就不再復(fù)述了惜互,直接講問題布讹。缺少相應(yīng)的安全校驗(yàn)很容易導(dǎo)致中間人攻擊,而漏洞的形式主要有以下3種:
- 自定義X509TrustManager载佳。在使用HttpsURLConnection發(fā)起 HTTPS 請求的時(shí)候,提供了一個(gè)自定義的X509TrustManager,未實(shí)現(xiàn)安全校驗(yàn)邏輯,下面片段就是常見的容易犯錯(cuò)的代碼片段。如果不提供自定義的X509TrustManager马靠,代碼運(yùn)行起來可能會(huì)報(bào)異常(原因下文解釋),初學(xué)者就很容易在不明真相的情況下提供了一個(gè)自定義的X509TrustManager,卻忘記正確地實(shí)現(xiàn)相應(yīng)的方法馆匿。本文重點(diǎn)介紹這種場景的處理方式铭拧。
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
//do nothing秕磷,接受任意客戶端證書
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
//do nothing瘟芝,接受任意服務(wù)端證書
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[] { tm }, null);
- 自定義了HostnameVerifier。在握手期間,如果 URL 的主機(jī)名和服務(wù)器的標(biāo)識(shí)主機(jī)名不匹配,則驗(yàn)證機(jī)制可以回調(diào)此接口的實(shí)現(xiàn)程序來確定是否應(yīng)該允許此連接谷异。如果回調(diào)內(nèi)實(shí)現(xiàn)不恰當(dāng)括丁,默認(rèn)接受所有域名,則有安全風(fēng)險(xiǎn)抽诉。代碼示例己单。
HostnameVerifier hnv = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
// Always return true廷痘,接受任意域名服務(wù)器
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hnv);
- 信任所有主機(jī)名。
SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);