Android正確使用HTTPS
前言最近代碼審計,發現很多開發都不會校驗HTTPS證書,通常所看到的錯誤代碼如下:
1、未正確實現校驗服務端證書
2、未正確實現校驗服務端證書中的域名是否相符
3、信任所有域名
一般情況下,在Android中,訪問HTTPS網站通常代碼如下(以URLConnection為例):
URL url = new URL("https://www.baidu.com");
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setConnectTimeout(10*1000);
InputStream inputStream = urlConnection.getInputStream();
//讀取輸入流
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
return result.toString();
以上代碼,訪問CA籤發證書的HTTPS網站是沒問題的,但是,通常程序猿寫代碼是在測試環境下進行測試,測試環境下的HTTPS證書一般都是使用openssl生成的自籤名證書,此時使用上面的代碼訪問,就會報如下錯誤:
當測試人員拿app去測試時,訪問的是自籤名的測試環境,測試人員發現訪問不了,就會報bug,這時開發就去排查,開發找到javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.錯誤,然後程序猿就去百度,
百度的結果如下,這時程序猿會從第一個開始看起。
我們點進去百度搜索的第一個看看,如下:
天吶,博主提供了代碼,然後開發一頓操作,
1
2
3
4
5
Ctrl+C
Ctrl+V
git add .
git commit -m "fix https"
git push
然後大家都這麼做,紛紛感謝博主,啊!!博主愛您!第二種很有用!
於是安全進行代碼審計的時候就難受了。
以上都是我的猜測,也不一定按我這個套路走,看學安全公眾號也就圖一樂,哈哈哈哈。
環境搭建這裡我們用python3搭建簡單的HTTPS網站,
代碼如下:
# coding:utf-8
#
# @author: lyxhh
# @微信公眾號: 學安全
import web
from cheroot.server import HTTPServer
from cheroot.ssl.builtin import BuiltinSSLAdapter
HTTPServer.ssl_adapter = BuiltinSSLAdapter(
certificate='E:\\androidpro\\httpsdemo\\app\\src\\main\\assets\\server.crt',
private_key='E:\\androidpro\\httpsdemo\\app\\src\\main\\assets\\server_private.key')
urls = ("/.*", "lxh")
app = web.application(urls, globals())
class lxh:
def GET(self):
return 'hello, world!'
if __name__ == '__main__':
app.run()
測試:
使用openssl生成server.crt與server_private.key,步驟如下:
1)生成自己的CA根證書
生成CA私鑰文件(ca_private.key):
openssl genrsa -out ca_private.key 2048
生成證書籤名請求CSR文件(ca.csr):
openssl req -new -key ca_private.key -out ca.csr
生成X.509格式的CA根證書ca_public.crt(公鑰證書):
openssl x509 -req -days 365 -in ca.csr -signkey ca_private.key -out ca_public.crt
2)生成服務端證書
先生成伺服器私鑰文件server_private.key:
openssl genrsa -out server_private.key 2048
生成證書籤名請求CSR文件(server.csr):
openssl req -new -key server_private.key -out server.csr
伺服器端用server.csr文件向CA機構申請籤名證書, 籤名過程需要CA的公鑰證書和私鑰參與,最終生成一個帶有CA籤名的伺服器端證書。
openssl x509 -req -CA ca_public.crt -CAkey ca_private.key -CAcreateserial -in server.csr -out server.crt
其中:
Common Name必須和網站域名一致,以便之後進行Host Name校驗。
修改手機hosts文件,
1
192.168.43.240 test.lxhsec.com
1、正確校驗證書是否在有效期內,且證書鏈是否正確。
如果訪問的域名與證書內Common Name的域名一致,則正常訪問:
如果不一致,例如訪問test.lxhsec.com對應的ip192.168.43.240,報錯如下:
2、正確實現HostnameVerifier
再次訪問192.168.43.240,正常請求,如下:
3、主機名驗證策略改成嚴格模式
代碼打包到百度雲盤了,公眾號內回復獲取:HTTPS1
遇到的問題修改/etc/hosts文件
解決:
https://blog.csdn.net/dzkdxyx/article/details/82877755
https://developer.android.com/training/articles/security-ssl