source:citizenlab.org
QQ瀏覽器是騰訊開發的一款網絡瀏覽器,面向Android,Windows,Mac和iOS等平臺。相較于內置瀏覽器,QQ瀏覽器提供了更豐富的功能,例如,增加了標簽窗口,并且整合了聊天平臺等。
報告中詳細的分析了Windows和Android版本的QQ瀏覽器是如何傳輸用戶數據。這兩個版本的QQ瀏覽器在傳輸用戶的身份數據時,要么直接不使用加密,要么使用的加密算法簡直形同虛設。完整的討論內容請參閱我們的報告《Baidu’s and Don’ts: Privacy and Security Issues in Baidu Browser》。
由于這種數據傳輸方式非常不安全,所以只要能介入數據傳輸路徑(比如,用戶的ISP,連接了咖啡店的WiFi網絡,或入侵了相應網絡的黑客),收集并解密數據流量,就能夠截獲到這些個人數據。
除了數據傳輸方式不夠安全,這兩版QQ瀏覽器的更新方式也有漏洞,會導致任意代碼執行。也就是說,攻擊者可以偽造一個軟件更新,將惡意代碼安裝到用戶的設備上。
這份報告屬于《Privacy and Security of Mobile Applications in Asia》系列。此前,我們已經確認了移動版的UC瀏覽器和百度瀏覽器也存在類似的問題。斯諾登也曾經曝光說,五眼情報聯盟(NSA,GCHQ,CSE,ASD,GCSB)利用了UC瀏覽器中的安全問題來識別和跟蹤用戶身份。在已經公布的《The Many Identifiers in Our Pockets》報告中,我們列出了哪些個人數據是經常被收集和傳輸的。
另外,我們研究了TOM-Skype和UC上的密碼審核機制,對比分析了一些在亞洲風靡的移動聊天工具,包括微信,LINE和KakaoTalk。除此之外,我們還檢查了微信上的密碼審核機制。這次研究的主要目的是通過一種綜合性的方法,包括逆向工程和其他技術分析方法,讓用戶意識到這些應用中的安全和隱私問題,同時,希望相關的軟件公司,承擔起應有的責任,保護用戶的權益。
2016年3月17日,我們詢問了騰訊為什么要收集用戶數據,并且還要通過一種不安全的方式將這些數據傳輸到QQ服務器。這里是我們提出的具體問題。直至截稿,我們沒有收到任何答復。在最后,我們討論了一些可能的深層原因,為什么中國的這三款瀏覽器會出現類似的問題。
我們分析了兩個版本的QQ瀏覽器,分別是安卓版6.3.01920和Windows版9.2.5478。在分析過程中,我們使用了大量的工具。比如,我們使用了tcpdump和Wireshark來捕捉和分析網絡流量,也使用了機器代碼和字節碼反匯編工具,反編譯器和調試工具來分析程序行為,包括,JD, JADX和IDA。
我們發現這兩個瀏覽器都使用了一種通用機制與服務器通訊,而這種機制會導致個人信息的泄露,并且,這些瀏覽器的更新過程中也存在多個安全漏洞。
我們的技術分析分為三部分,第一部分介紹了一個基本結構,這兩個版本的QQ瀏覽器都會通過這個結構向QQ服務器傳輸數據。第二部分分析了被采集的個人用戶數據,以及安卓版的軟件更新過程。第三部分分析了相應的Windows版功能。
安卓和Windows版的QQ瀏覽器都使用了一種WUP請求與QQ服務器通訊。
WUP請求是一種二進制格式,可以包含不同類型的值,例如,整數,浮點數,列表,字符串和遞歸結構。有時候,這些請求首先要經過加密,然后再嵌入到一個HTTP POST請求的主體中,最后,隨著這個HTTP POST請求發送到目的URL。我們寫了一個Python腳本來解密并解析這些請求,從而將其轉換成人類可讀格式。在這個腳本的代碼中,還包含了在接下來解密數據時需要用到的其他腳本。
Q-GUID,Q-UA和Q-UA2字段出現在WUP請求的HTTP標頭中。在接下來介紹WUP請求時,如果某個字段的對應值出現在了WUP請求的有效載荷中,我們就用這個字段來代指一個相應的實例。在HTTP標頭中,這些字段都不會經過加密,但是,當這些字段出現在WUP請求中時,其格式會發生變化。
Q-GUID字段中填充的值是在初始化時,通過一個WUP請求從QQ服務器上獲取的,并且在接收到這個值后,瀏覽器就會保留這個值,并且將其添加到后續請求的HTTP標頭中,沒有加密。在很多WUP請求的有效載荷中,也包含有這個值。下面就是一個Q-GUID:caed22d728efa6127d53bc0412f888cb
GUID可能表示的是“全局唯一標示符”,是一個128位數字,通常是隨機生成的。
Q-UA和Q-UA2值中包含有與QQ瀏覽器版本和硬件平臺相關的硬編碼信息。雖然,UA很可能指的是“User Agent”,并且包含有與HTTP user agent字符串相似的信息,但是其格式卻不同于QQ瀏覽器在HTTP標頭中使用的user agent HTTP字段。
我們分析的安卓版QQ瀏覽器是6.3.01920版本,下載于http://mb.qq.com/。在啟動后,或執行了某些事件時,比如,瀏覽網頁或檢查更新,瀏覽器就會向http://wup.imtt.qq.com:8080/
發送WUP請求。這些請求使用了下面的這種加密方式。
對于每個加密的WUP請求,會根據下面的Java代碼來生成一個AES秘鑰:
#!java
int i = 10000000 + new Random().nextInt(89999999);
int j = 10000000 + new Random().nextInt(89999999);
return (String.valueOf(i) + String.valueOf(j)).getBytes();
所以說,這個秘鑰是一個128位秘鑰,由16個ASCII數字組成。而且,第1個和第9個字節永遠不可能是0,前8個和最后8個字節不可以全都是9,所以,秘鑰空間并不是常規的2^128
,而是89999999^2 < 2^53
。
隨后,這個秘鑰會用于通過AES+ECB模式來加密WUP請求。AES秘鑰會使用一個128位的RSA公鑰加密,系數:245406417573740884710047745869965023463,指數:65537。加密后的AES秘鑰會被納入到HTTP請求的qbkey HTTP標頭中。
RSA是一種非對稱加密算法,也就是說,在解密時需要使用另一個不同的私鑰,上面提到的RSA秘鑰無法直接用于解密AES秘鑰和WUP請求。但是,RSA的安全程度取決于加密秘鑰的系數分解難度。一旦分解,解密秘鑰就很容易獲得了。上述的RSA公鑰只有128位,分解起來并不難。(RSA秘鑰一般建議至少2018位)。使用Wolfram Aplpha這個在線計算引擎,用不了1秒就可以分解秘鑰的系數:
http://www.wolframalpha.com/input/?i=factor+245406417573740884710047745869965023463
分解后,得到了下面兩個質因數:
14119218591450688427 x 17381019776996486069
有了這些質因數,任何在監控流量的中間人都可以解密出每個WUP請求使用的AES秘鑰,然后再使用AES秘鑰解密WUP請求。
我們一直監控著瀏覽器發送的流量,并且使用這個秘鑰解密了所有的WUP請求。多數WUP請求中傳輸的是一些很容易解密的個人信息。在圖1中,是一個解密后的WUP請求,通過我們的腳本,可以將其解析成可讀的形式。
圖1-解密后的WUP請求。我們用“#”替代了敏感數字。
下面是我們識別出的一些重要請求,以及每個請求傳輸的個人信息:
WUP請求 | 發送時間 | 加密程度 |
---|---|---|
profileInfo.profileInfo | 瀏覽器啟動時 | 簡單加密 |
hotword.getAssociationalWords | 輸入地址欄時 | 不加密 |
Security.doSecurityReqest [sic] | 瀏覽網頁時 | 簡單加密 |
proxyip.getIPListByRouter | 瀏覽器啟動時 | 簡單加密 |
pkgcenternew.checkUpdate | 檢查更新時 | 簡單加密 |
數據點 | 數據點描述 | 加密程度 | WUP請求 |
---|---|---|---|
IMEI | 國際移動設備標識碼,每臺設備對應一個唯一的字符串 | 簡單加密 | profileInfo.profileInfoSecurity.do SecurityReqest proxyip.getIPListByRouter pkgcenternew.checkUpdate |
IMSI | 國際移動用戶標識碼,每個用戶對應一個唯一的數字 | 簡單加密 | profileInfo.profileInfo |
Q-GUID | QQ瀏覽器使用這個唯一字符串來識別用戶身份 | 不加密 | hotword.getAssociationalWords Security.doSecurityReqest proxyip.getIPListByRouter |
Q-UA2 | QQ瀏覽器使用這個值來識別應用版本和硬件平臺的類型 | 不加密 | hotword.getAssociationalWords Security.doSecurityReqest |
QQ username | QQ用戶名 | 簡單加密 | profileInfo.profileInfo |
Screen pixel dimensions | 用戶設備的屏幕尺寸 | 簡單加密 | profileInfo.profileInfo |
WiFi MAC address | 媒體訪問控制地址,識別無線傳輸器的唯一標識,比如,設備上的藍牙芯片和WiFi芯片 | 簡單加密 | profileInfo.profileInfo* |
In-range WiFi access point MAC addresses | 所有周邊WiFi訪問點的媒體訪問控制地址 | 簡單加密 | profileInfo.profileInfo proxyip.getIPListByRouter |
SSID of connected WiFi access point | 用戶連接的WiFi名稱 | 簡單加密 | proxyip.getIPListByRouter |
Android ID | 在OS首次運行時,生成的一個唯一數字,用于追蹤用戶 | 簡單加密 | pkgcenternew.checkUpdate |
Address bar contents | 用戶在地址欄中輸入的內容(比如,搜索請求) | 不加密 | hotword.getAssociationalWords |
Full page URL | 每個訪問頁面的完整URL | 簡單加密 | Security.doSecurityReqest |
WiFi MAC地址通過DES+ECB模式加密,使用的秘鑰是“\x25\x92\x3c\x7f\x2a\xe5\xef\x92
”。
WUP請求的響應也很容易解密。WUP響應并沒有使用前面提到的非對稱加密算法,而是單純使用了一種對稱性算法,所以我們不需要分解任何秘鑰的質因數。換句話說,其加密模式是MTEA+MCBC,使用的硬編碼ASCII加密秘鑰是:“sDf434ol*123+-KD
”
很有趣的是,QQ瀏覽器的加密過程是非標準的MTEA+MCBC模式,和百度瀏覽器一樣(見圖4)。
因為這種算法是對稱的,所以這些響應的加密和解密秘鑰是同一個。任何中間人都可以利用這個秘鑰,主動偽造一個來自QQ服務器的響應。我們通過攻擊QQ瀏覽器的更新過程證實了這一點。
通過pkgcenternew.checkUpdate請求的存在來看,軟件更新是可用的。在這個請求的響應中可能會包含有下載新APK文件的鏈接,APK的MD5哈希和更新日志。在安卓上,如果APK更新使用的簽名與當前安裝的版本不符,那么APK更新就會失敗;雖然,這種攻擊方式無法將QQ瀏覽器替換成任意的APK;但是,這種方法可以用來安裝新App,通過使用QQ瀏覽器的名稱和圖標,誘騙用戶安裝惡意的APK。
圖2-中間人攻擊QQ瀏覽器的更新過程。在左圖中,我們可以插入任意的更新日志。在右側,更新下載完成后,瀏覽器會提示用戶安裝憤怒的小鳥APK(攻擊者可以將這個App的名稱修改為“QQ瀏覽器”,使用與QQ瀏覽器相似的圖標,從而誘使用戶安裝這個APK)
目前,由于Google Play商店無法在中國使用,所以中國的安卓用戶必須通過其他途徑來更新應用。因為無法使用Google Play商店的更新過程,所以,開發者必須自己實現自動更新機制,而這樣則會導致程序的更新過程出現漏洞。據稱,中國版的Google Play商店會在2016年上線。
我們分析的Windows版QQ瀏覽器是9.2.5478版本,下載于http://browser.qq.com/。雖然,Windows版的QQ瀏覽器也是通過WUP請求與服務器通訊,但是,采用了不同于安卓版本的加密方式和加密時間。而且,Windows版本使用了MTEA+MCBC算法來加密WUP請求,這是一種對稱加密算法,而不是安卓版本上的非對稱RSA算法(WUP響應都是采用了MTEA+MCBC算法進行加密,無論是安卓版本還是Windows版本)。
我們還發現,安卓版本的WUP請求都是發給了http://wup.imtt.qq.com:8080/
,而Windows版本則是向多個URL發送了WUP請求,包括http://qbwup.imtt.qq.com
,http://wup.html5.qq.com
和http://wup.imtt.qq.com:8080
。
通過WUP請求來看,Windows版QQ瀏覽器還會跟蹤設備的硬件指紋。這里的硬件指紋指的是下列項目的MD5哈希:
比如:md5(“080027B09CC2” + “VB7c666e15-ef97c40b” + “VBOX HARDDISK” + “1.0”)
因為MTEA+MCBC是完全對稱的,所以,任何能觀察到流量的中間人都可以利用硬編碼的加密秘鑰,輕易地解密所有的WUP請求。和前面一樣,我們監控了瀏覽器發送的流量并解密了所有的WUP請求。其中有多個WUP請求會泄露可解密的個人信息。下面是我們識別出的一些重要請求,以及每個請求傳輸的個人信息:
WUP請求 | 發送時間 | 加密程度 |
---|---|---|
devicesniffer.DeviceSnifferHandle | 瀏覽器啟動時 | 簡單加密 |
login.login | 瀏覽器啟動時 | 簡單加密 |
qbkpireportbak.stat | 瀏覽器啟動時 | 簡單加密 |
qbpcstat.stat | 瀏覽器啟動時 | 簡單加密 |
qbindexblacklist.testUrl | 在地址欄中發起搜索請求或輸入URL時 | 不加密 |
WUP請求本身是沒有加密的,但是其中的WUP有效載荷使用了DES+ECB算法進行加密(一種對稱性的加密算法,解密起來很簡單),使用的秘鑰是“\x62\xe8\x39\xac\x8d\x75\x37\x79
”。
數據點 | 數據點描述 | 加密程度 | WUP請求 |
---|---|---|---|
Hardware fingerprint | 網絡MAC地址,硬盤序列號,硬盤型號,硬盤控制器版本號的哈希 | 不加密 | login.login qbkpireportbak.stat qbpcstat.stat qbindexblacklist.testUrl |
Q-GUID | QQ瀏覽器使用這個唯一字符串來識別用戶身份 | 不加密 | devicesniffer.DeviceSnifferHandle login.login* qbkpireportbak.statqbpcstat.stat qbindexblacklist.testUrl |
Q-UA | QQ瀏覽器使用這個值來識別應用版本和硬件平臺的類型 | 不加密 | login.login qbindexblacklist.testUrl |
Machine IP Address | 用戶設備的互聯網協議地址 | 簡單加密 | devicesniffer.DeviceSnifferHandle |
Machine hostname | 用戶的Windows主機名稱 | 簡單加密 | devicesniffer.DeviceSnifferHandle |
Gateway MAC address | 用戶計算機上,網關的媒體訪問控制地址。 | 簡單加密 | devicesniffer.DeviceSnifferHandle |
Windows version and build | 用戶計算進上的Windows版本和編譯號 | 不加密 | qbkpireportbak.stat qbpcstat.stat qbindexblacklist.testUrl |
Internet Explorer version | 用戶計算機上的IE版本 | 簡單加密 | qbkpireportbak.stat Qbpcstat.stat |
QQ Browser version | 用戶計算機上的QQ瀏覽器版本 | 不加密 | qbindexblacklist.testUrl |
Hard drive serial number | 用戶硬盤的唯一序列號 | 簡單加密 | qbkpireportbak.stat qbpcstat.stat |
Windows user security identifier | 隨機生成的Windows用戶唯一標示符 | 簡單加密 | qbkpireportbak.stat qbpcstat.stat |
Full page URL | 在地址欄中輸入的每個頁面的完整URL | 未加密 | qbindexblacklist.testUrl |
Q-GUID使用了3DES+ECB加密算法,使用的秘鑰是“\x63\xd7\x90\x63\x3c\x0e\x2f\xc3\x46\xef\x85\x37\x42\x1f\x9d\x4a\x46\x3d\x58\xf3\x8a\x95\xec\x84
”明文字節和隨機字節交替出現,也就是說,第一個,第三個,第五個等字節是Q-GUID的第一個,第二個和第三個字節,而明文的第二,第四,第六等字節是隨機選擇的。
當用戶訪問了一個網頁后,Windows版QQ瀏覽器也會通過WUP請求泄露用戶信息。每個被訪問頁面的完整URL,無論是輸入到地址欄,通過鏈接跳轉,還是其他方式訪問,都會經過MTEA+MCBC加密,發送到http://masterconn.qq.com/
,使用的秘鑰是“\x8a\x0d\x75\x73\x90\x03\x4a\xd2\xb5\x25\xab\xe2\x31\xe2\x9f\x6f
”。
軟件更新檢查是通過JSON發送給http://update.browser.qq.com/qbrowser
。與安卓版本一樣,更新請求和服務器返回的后續請求都沒有經過加密,我們發現,Windows版本和安卓版本的區別在于,Windows版會驗證更新包的數字簽名。但是,我們發現了兩種針對更新過程的攻擊活動,任何中間人都可以通過主動攻擊,在安裝了QQ瀏覽器的設備上遠程執行代碼。
第一種攻擊是目錄遍歷攻擊。通常,當有更新時,QQ的服務器會在響應中給出EXE文件的下載鏈接,MD5哈希,新功能和修復簡介,EXE的文件名和保存位置。我們發現文件名中出現了目錄,通過目錄遍歷,攻擊者可以覆蓋用戶有權限寫入的任何文件。例如,將文件命名為../../../../../../../../../program files/tencent/qqbrowser/qqbrowser.exe
,我們就可以用任意程序替換QQ瀏覽器,這樣用戶在下次執行QQ瀏覽器時,實際執行的就是我們的程序。攻擊者可以利用這種攻擊方式來安卓隱藏的間諜軟件或木馬。
第二種攻擊方式說明了僅僅是驗證數字簽名還不足以認證軟件更新的安全性。數字簽名驗證只是判斷下載的EXE是不是由騰訊簽名的,但是不會判斷這個EXE會不會更新QQ瀏覽器-這個EXE可以是任何一個騰訊簽名的程序。我們發現,舊版的QQ瀏覽器安裝程序不會執行簽名檢查(這個安裝程序本身只使用了對稱加密),在更新時也是這樣,我們使用了漏洞版本的QQ瀏覽器在線安裝服務來“更新”用戶的QQ瀏覽器,然后下載和執行我們選擇一個EXE(圖3)。
圖3-中間人攻擊QQ瀏覽器的更新程序,首先注入一個有漏洞的在線安裝程序,然后注入我們的程序。有效載荷是顯示為“Oh Hai There”,但是,可以注入任意軟件,比如間諜程序或木馬。
在這份報告中,我們指出了QQ瀏覽器中存在的一些很嚴重的安全漏洞。這個應用會收集和傳輸用戶的身份數據,從而導致第三方可以監控到這些數據。另外,軟件更新缺陷致使攻擊者可以在用戶設備上執行任意代碼,比如第三方可以在用戶的設備上插入惡意的間諜程序并執行。最讓人討厭的是用戶還不一定能意識到風險的存在-沒有意識到自己的數據會被收集,也可能不會意識到自己的設備上會被安裝惡意代碼。
但是,我們已經研究發現,這一問題并不僅限于某個特定的應用,操作系統或公司。我們分析的QQ瀏覽器,百度瀏覽器和UC瀏覽器-這三家世界知名科技公司-都爆出了相似的安全漏洞。所以說,不只有QQ瀏覽器會收集這些敏感的用戶數據,并且不加密或簡單加密就傳輸。考慮到這些相似性,需要從更廣泛的移動安全和應用安全層面來評估這些安全問題,而不是集中在某一家公司或某個應用。
用戶信任web瀏覽器會安全地處理用戶輸入的敏感信息并安全地將這些信息傳輸給web服務器。但是,QQ瀏覽器和其他的瀏覽器背棄了用戶的信任,這些軟件不僅僅在收集用戶數據,還采用了一種不安全的傳輸方式。即使是使用了非對稱加密,也沒有能夠堅持。安卓版的QQ瀏覽器使用了非對稱的RSA算法,但是使用的秘鑰太小,沒有滿足建議的2048位大小。這一缺陷要求開發者必須要使用經過考驗的協議,比如OpenSSL這種廣泛使用的方法能夠更加安全地傳輸敏感數據。
除了批評這些應用的數據傳輸方式不夠安全,更大的問題在于為什么要收集和傳輸這類個人數據。經由移動設備傳輸的個人身份數據成千上萬,收集這些信息會導致嚴重的用戶安全和隱私問題。然而,正是因為用戶設備上的這些數據,開發者才能夠提供高效的,高度定制化的服務,這些移動版瀏覽器收集的數據范圍過大,很可能會引起用戶的擔憂-尤其是當廠商沒有辦法保證數據的安全。收集與用戶身份,用戶設備和用戶在線行為相關的信息,很可能是為了監控高風險用戶,在中國,可能包括民主人士,記者,人權支持者,律師等。