Android _實現SSL解決不受信任的證書問題
介紹
網路安全已成為大家最關心的問題. 如果你利用伺服器儲存客戶資料, 那你應該考慮使用 SSL 加密客戶跟伺服器之間的通訊. 隨著這幾年手機應用迅速崛起. 黑客也開始向手機應用轉移, 原因有下列3點:
-
手機系統各式各樣, 缺乏統一的標準.
-
許多程式設計師缺乏手機應用開發經驗.
-
更嚴重的是, 通過手機應用, 黑客可以得到手機使用者的隱私資料, 如:日程安排, 聯絡人資訊, 網頁瀏覽歷史記錄, 個人資料, 社交資料, 簡訊或者手機使用者所在的地理位置.
最為一個網路安全愛好者的我, 最近花了幾個月的時間對50到60安卓應用進行安全分析, 結果發現這些應用存在許多安全漏洞.
下面我主要講一講, 怎樣才能寫出比較安全的安卓程式碼.
背景
從最基本的開始講.
下列程式碼用來開啟一個 http 連線.
?1 2 3 |
URL urlConnection = new URL( "http://www.codeproject.com/" );
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
|
不要在 http連線中開啟:登陸頁面, 或是傳遞使用者名稱, 密碼, 銀行卡之類的重要個人資料. 這些重要個人資料應該通過 HTTPS 傳輸. (具體參看
HTTPS是什麼?
HTTPS 其實就是個安全版的 http. HTTPS 能保證電子商務的交易安全. 如:網上銀行.
像 IE 或者火狐瀏覽器, 如果出現下面的掛鎖圖示.
同時, 在瀏覽器的位址列中以 https:// 開頭, 這表示, 你的瀏覽器跟這個網站的資料往來都是安全的.
https 跟 http 的最大區別在於 https 多加了一個保障通訊安全的層.
像下列程式碼這樣開啟一個 https 連線, 可以保障這個連線的資料通訊安全.
?1 2 3 4 5 |
URL urlConnection = new URL( "https://www.codeproject.com/" );
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
|
HTTPS 通過 SSL/TLS 傳遞資料.
回到頂部SSL/TLS:
SSL (Secure Sockets Layer) 是一種在客戶端跟伺服器端建立一個加密連線的安全標準. 一般用來加密網路伺服器跟瀏覽器, 或者是郵件伺服器跟郵件客戶端(如: Outlook)之間傳輸的資料.
SSL 能保障敏感資訊(如:銀行卡號, 社保卡號, 登陸憑證等)的傳輸安全. 一般情況下, 資料在瀏覽器跟伺服器之間的傳輸使用的是明文格式, 這種方式存在資料被竊取的風險. 如果黑客能攔截瀏覽器跟伺服器之間的通訊資料, 就能看到通訊的內容.
回到頂部SSL/HTTPS and X.509 證書概述
你要是對 SSL 或 X.509 證書一無所知, 那我大概解釋下. 對於那些打算用自簽名證書(self-signed certificate)的人來說, 需要了解自簽名證書跟花錢購買機構頒發的證書有什麼區別.
首先我們需要了解下 SSL 證書究竟是個什麼東東? 其實它就包含倆部分: 1) 一個身份標識, 一個用來識別身份的東西, 有點類似警察叔叔通過護照或駕照查你的身份; 2) 一個公共金鑰, 這個用來給資料加密, 而且只有證書的持有者才能解密. 簡而言之, SSL 證書就倆個功能, 身份驗證跟保障通訊過程中的資料安全.
另外還有一點很重要. 那就是一個證書可以給另外一個證書“簽字”. 用 layman 的話說就是 Bob 用他自己的證書在別的證書上蓋上 “同意” 兩個紅紅的大字. 如果你信任 Bob (當然還有他的證書), 那麼你也可以信任由他簽發的證書. 在這個例子中, Bob 搖身一變, 成了證書頒發機構(Certificate Authority). 現在主流的瀏覽器都自帶一大堆受信任證書頒發機構(trusted Certificate Authorities)(比如:Thawte, Verisign等).
最後我們講一講瀏覽器是怎麼使用證書的. 籠統的講, 當你開啟下列連線的時候 “https://www.yoursite.com” :
-
伺服器會給瀏覽器發一個證書.
-
瀏覽器會對比證書中的“common name”(有時也叫 “subject”) 跟伺服器的域名是否一樣. 例如, 一個從“www.yoursite.com” 網站發過來的證書就應該有一個內容是 “www.yoursite.com” 的 common name, 否則瀏覽器就會提示該證書有問題.
-
瀏覽器驗證證書真偽, 有點像門衛通過證件上的全息圖辨別你的證件是不是真的. 既然在現實生活中有人偽造別人的身份. 那麼在網路世界也就有人造假, 比如用你的域名“www.yoursite.com” 來偽造一個安全證書. 瀏覽器在驗證的時候, 會檢查這個證書是否是它信任機構頒發的, 如果不是, 那麼瀏覽器就會提示這個證書可能有問題. 當然, 使用者可以選擇無視警告, 繼續使用.
-
一旦證書通過驗證 (或是使用者無視警告, 繼續使用有問題的證書), 瀏覽器就開始利用證書中的公開金鑰加密資料並傳給伺服器.
TLS (SSL)中的加密
一旦伺服器發過來的證書通過驗證, 瀏覽器就會利用證書中包含的公共金鑰加密某個指定的共享金鑰, 然後發給伺服器. 這個加密過的共享金鑰只能用伺服器的私有金鑰才能解密(非對稱加密), 別人無法解密出其中的內容. 伺服器把解密出來的共享金鑰儲存起來, 供本次連線會話專用. 從現在開始, 伺服器跟瀏覽器之間的所有通訊資訊都用這個共享金鑰加密解密(對稱加密).
理論部分就這麼多, 下面我們來看幾個例子.
在瀏覽器中開啟網站 mail.live.com , 位址列中會出現一個綠色圖示, http 也會變成 https.
單擊這個綠色圖示, 然後點證書資訊連線, 就能看到下列內容.
這是個 SSL 證書, 該證書是 Verisign 給 mail.live.cm 頒發的.
Verisign 是一個證書頒發機構, 它提示你的瀏覽器正在連線的網站是: mail.live.com, 需要跟這個網站的伺服器建立一條安全連線進行通訊, 避免他人攔截或篡改瀏覽器跟伺服器之間傳遞的資料.
回到頂部MITM 攻擊
MITM 攻擊(MITMA)是指: 黑客攔截篡改網路中的通訊資料
被動 MITMA 是指黑客只能竊取通訊資料, 而在主動 MITMA 中, 黑客除了竊取資料, 還能篡改通訊資料. 黑客利用 MITMA 方式攻擊手機要比攻擊臺式電腦容易的多. 這主要是因為使用手機的環境在不固定, 有些地方用手機連線上網並不安全, 尤其是那些對公眾免費開放的無線網路熱點.
證書頒發機構(CA)
·Symantec (which bought VeriSign's SSL interests and owns Thawte and Geotrust) 38.1% 市場份額
Jelly bean 版本的安卓系統中, 你可以在下列路徑中找到證書頒發機構:
設定 -> 安全 -> 受信任的憑證.
Https 連線
?1 2 3 |
URL url = new URL( "https://www.example.com/" );
HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
InputStream in = urlConnection.getInputStream();
|
如果你連線的伺服器(www.example.com)傳過來的證書是由機構頒發的, 這段程式碼就能正常執行.
但是如果你連的伺服器用的是自己頒發的證書(self-singed certificate), 那就會出現錯誤.
回到頂部什麼是自簽名證書( self-signed certicates)
自簽名證書就是沒有通過受信任的證書頒發機構, 自己給自己頒發的證書.
SSL 證書大致分三