作者:瘦蛟舞
公眾號:小米安全中心
0x01 SSL收益
安全性提升,有效對抗絕大部分中間人攻擊。

-
中間人攻擊部分場景
-
HTTP劫持
-
DNS劫持
-
ARP欺騙
-
釣魚WIFI
-
偽基站
TLS的主要目標是使SSL更安全,并使協議的規范更精確和完善,本文統一使用SSL泛指。
0x02 IoT分類
設備ROM發版相對app發版要復雜許多,所以設備的證書驗證場景復雜度更高,先將設備抽象成兩大類:
- 系統自帶證書的通用操作系統比如AndroidTV
- 系統沒有預制證書的實時操作系統(RTOS)
如果設備是第一類通用操作系統比較好處理
-
如果證書是CA簽發的,只需信任系統證書即可,最好同時開啟系統分區保護。
-
如果證書是自簽發的,除了信任系統證書以外額外只信任此自簽發證書即可,切勿為了跑通業務盲目信任所有證書。一些業務剛開發的時候可能還沒買證書,所以初期代碼是信任所有證書,后來買正式證書后忘記修復證書信任代碼。例如沒買證書之前curl使用了-k參數,買完證書后忘記統一除去此參數。
-k, --insecure Allow connections to SSL sites without certs (H)
如果設備是第二類RTOS,首先得確認其是否支持SSL,其上運行的業務是否需要SSL。如果需要且支持,則可以通過自行預制根證書。
0x03 錯誤示范
0x02中已經有一個ssl的簡單錯誤示范了,接下來再講一個錯誤開發案例。
ssl相關開發的時候遇到如下錯誤提示,就是證書驗證不通過:
curl_easy_perform failed : SSL peer certificate or SSH remote key was not OK
項目著急上線,就使用網上的提示的方法解決這個報錯。看似解決問題,實際上留下了安全隱患:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
因為將verify參數設置為0,此時會忽略所有的證書相關錯誤,也就意味著會對所有的證書都信任。如果有攻擊者進行證書注入劫持,那么他將能看到明文通信,SSL失去了其本來的作用:
#include <curl/curl.h>CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_VERIFYPEER, long verify);
被劫持的后的效果如下,設備的通信的信息完全暴露給攻擊者。

我們是如何快速定位這個漏洞的呢?這里安利一下小米安全開發的MiEye自動化IoT安全測試系統,可以完全捕獲此類漏洞。https://eye.dun.mi.com/

最后匯總下此類錯誤操作:
- curl使用 -k參數
- wget使用 --no-check-certificate參數
- libcurl中把 CURLOPT_SSL_VERIFYPEER 和 CURLOPT_SSL_VERIFYHOST設置為false
- 覆蓋X509TrustManager類中的checkServerTrusted方法且不進行證書鏈驗證,常見表現形式就是將此方法置空
- 信任所有主機名setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
0x04 解決問題
上面的錯誤操作會使設備處于安全等級0,這里建議IoT設備應根據業務處于2或3的等級。

本文不是理論向文章,但是方便大家抓住重點,還是提一些基本知識點。
SSL握手過程(RSA)如下圖,根據使用的密鑰交換算法的不同協商細節略有不同但總體類似:

信任鏈的關鍵:雙方共有的根證書保證了秘鑰協商的可靠性。
同理API的使用關鍵就在證書的處理環節。
正確的SSL證書驗證設置如下,默認就是如此,若要對其進行修改需要十分謹慎:
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
如果設備內沒有對應的根證書,需要先找到對應域名的根證書,可以通過瀏覽器觀察。比如這個case里的證書是Godaddy的,之后下載GoDaddy Root Certificate Authority - G2這個根證書并埋入設備。

Godaddy根證書下載地址:https://ssl-ccp.godaddy.com/repository?origin=CALLISTO
若參考curl文檔中的方法拿到的證書是站點證書,有效期較短.而IoT設備的發版周期較長,易造成可用性降低。故本文一直是圍繞根證書展開。
注意:下面命令拿到的是有效期較短的站點證書而非根證書。
openssl s_client -servername www.example.com -connect www.example.com:443 < /dev/null | sed -n "/-----BEGIN/,/-----END/p" > www.example.com.pem
當然一個設備可能訪問很多個域,然后需要預制很多個根,假設另一個常用根是DigiCert,再去DigiCert下載對應根證書埋入設備。
DigiCert根證書下載地址:https://www.digicert.com/digicert-root-certificates.htm
可以通過CURLOPT_CAINFO來指定一個根證書:
CURLOPT_CAINFO - path to Certificate Authority (CA) bundle

This option is by default set to the system path where libcurl's cacert bundle is assumed to be stored, as estab-lished at build time.
瀏覽器和操作系統中一般都會自帶大量可信CA根證書,例如:

除此之外還有類似aosp.pem,apple.pem,microsoft.pem,java.pem,mozilla.pem等作為補充。Firefox的內置證書如下: https://wiki.mozilla.org/CA/Included_Certificates
可以把缺失的證書追加到證書的列表,也可以考慮直接用Mozilla的證書列表:
cat newcert.pem >> /etc/pki/tls/certs/ca-bundle.crt
還可以通過CURLOPT_CAPATH來指定對應根證書目錄,如果有多個ca需要添加可以考慮它(新增):
CURLOPT_CAPATH - specify directory holding CA certificates
#include <curl/curl.h> CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CAPATH, char *capath);
0x05 一般不推薦leaf certificate證書鎖定
SSL pinning新增對抗場景:
-
客戶端安裝惡意證書,IoT上這種情景極少
-
一些WiFi需要你添加根證書信任才能使用互聯網
-
一些網站需要你添加根證書信任才能不反復紅叉提示
-
其他CA惡意簽發站點證書
WoSign和Symantec都有過一段時期簽發的證書不受信任的歷史
https://news.mindynode.com/zh/events/50(還有StartCom和CNNIC)
最常見的就是HTTPS用SSL和TLS作為通信進行加密,然后再進行http的傳輸。除了http外SSL/TLS也可以用保護其他的協議:FTP,IMAP, POP3,SMTP等等。
不過一般不推薦使用CURLOPT_PINNEDPUBLICKEY,其他庫同理不推薦在IoT設備上做站點證書鎖定。前面也提到過了站點證書有效期太短,而IoT設備發版周期漫長,做一套可靠證書指紋更新的方案性價比極低,稍有不慎就會導致業務不可用。
NAME CURLOPT_PINNEDPUBLICKEY - set pinned public keySYNOPSIS #include <curl/curl.h> CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PINNEDPUBLICKEY, char *pinnedpubkey);
看文檔沒說支持intermediate & root certificate pin,所以curl自帶的鎖定只支持leaf certificate pin
https://curl.haxx.se/docs/todo.html
13.11 Support intermediate & root pinning for PINNEDPUBLICKEY
CURLOPT_PINNEDPUBLICKEY does not consider the hashes of intermediate & root certificates when comparing the pinned keys. Therefore it is not compatible with "HTTP Public Key Pinning" as there also intermediate and root certificates can be pinned. This is very useful as it prevents webadmins from "locking themself out of their servers".
更多的證書鎖定的細節可以去參考我的另一篇文章:SSL.Pinning.Practice
0x06 參考文章
-
https://github.com/WooyunDota/DroidDrops/blob/master/2018/SSL.Pinning.Practice.md
-
https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.jmbmsq.com/1157/
暫無評論