Third-party libraries, especially ad libraries, are widely used in Android apps. Unfortunately, many of them have security and privacy issues. In this blog, we summarize our findings related to the insecure usage of JavaScript binding in ad libraries.
First, we describe a widespread security issue with using JavaScript
binding (addJavascriptInterface
) and loading WebView
content over HTTP, which allows a network attacker to take control of
the application by hijacking the HTTP traffic. We call this the
JavaScript-Binding-Over-HTTP (JS-Binding-Over-HTTP) vulnerability. Our
analysis shows that, currently, at least 47 percent of the top 40 ad
libraries have this vulnerability in at least one of their versions
that are in active use by popular apps on Google Play.
Second, we describe a new security issue with the JavaScript binding
annotation, which we call JavaScript Sidedoor. Starting with Android
4.2, Google introduced the @JavascriptInterface
annotation to explicitly designate and limit which public methods in
Java objects are accessible from JavaScript. If an ad library uses
@JavascriptInterface
annotation to expose
security-sensitive interfaces, and uses HTTP to load content in the
WebView, then an attacker over the network could inject malicious
content into the WebView to misuse the exposed interfaces through the
JS binding annotation. We call these exposed JS binding annotation
interfaces JS sidedoors.
Our analysis shows that these security issues are widespread, have affected popular apps on Google Play accounting for literally billions of app downloads. The parties we notified about these issues have been actively addressing them.
Security Issues with JavaScript Binding over HTTP
Android uses the JavaScript binding method
addJavascriptInterface
to enable JavaScript code running
inside a WebView to access the app’s Java methods. However, it is
widely known that this feature, if not used carefully, presents a
potential security risk when running on Android 4.1 or below. As noted
by Google: “Use of this method in a WebView containing untrusted
content could allow an attacker to manipulate the host application in
unintended ways, executing Java code with the permissions of the host
application.” [1]
In particular, if an app running on Android 4.1 or below uses the
JavaScript binding method addJavascriptInterface
and
loads the content in the WebView over HTTP, then an attacker over the
network could hijack the HTTP traffic, e.g., through WiFi or DNS
hijacking, to inject malicious content into the WebView – and thus
take control over the host application. We call this the
JavaScript-Binding-Over-HTTP (JS-Binding-Over-HTTP) vulnerability. If
an app containing such vulnerability has sensitive Android permissions
such as access to the camera, then a remote attacker could exploit
this vulnerability to perform sensitive tasks such as taking photos or
record video in this case, over the Internet, without a user’s consent.
We have analyzed the top 40 third-party ad libraries (not including
Google Ads) used by Android apps. Among the apps with over 100,000
downloads each on Google Play, over 42 percent of the free apps
currently contain at least one of these top ad libraries. The total
download count of such apps now exceeds 12.4 billion. From our
analysis, at least 47 percent of these top 40 ad
libraries have at least one version of their code in active
use by popular apps on Google Play, and contain the
JS-Binding-Over-HTTP vulnerability. As an example, InMobi versions
2.5.0 and above use the JavaScript binding method
addJavascriptInterface
and load content in the WebView
using HTTP.
Security Issues with JavaScript Binding Annotation
Starting with Android 4.2, Google introduced the
@JavascriptInterface
annotation to explicitly designate
and limit which public Java methods in the app are accessible from
JavaScript running inside a WebView. However, note that the
@JavascriptInterface
annotation does not provide any
protection for devices using Android 4.1 or below, which is still
running on more than 80 percent of Android devices worldwide.
We discovered a new class of security issues, which we call
JavaScript Sidedoor (JS sidedoor), in ad libraries.
If an ad library uses the @JavascriptInterface
annotation
to expose security-sensitive interfaces, and uses HTTP to load content
in the WebView, then it is vulnerable to attacks where an attacker
over the network (e.g., via WIFI or DNS hijacking) could inject
malicious content into the WebView to misuse the interfaces exposed
through the JS binding annotation. We call these exposed JS binding
annotation interfaces JS sidedoors.
For example, starting with version 3.6.2, InMobi added the
@JavascriptInterface
JS binding annotation. The list of
exposed methods through the JS binding annotation in InMobi includes:
createCalendarEvent
(version 3.7.0 and above)makeCall
(version 3.6.2 and above)postToSocial
(version 3.7.0 and above)sendMail
(version 3.6.2 and above)sendSMS
(version 3.6.2 and above)takeCameraPicture
(version 3.7.0 and above)getGalleryImage
(version 3.7.0 and above)registerMicListener
(version 3.7.0 and above)InMobi also provides JavaScript wrappers to these methods in the JavaScript code served from their ad servers, as shown in Appendix A.
InMobi also loads content in the WebView using HTTP. If an app has
the Android permission CALL_PHONE, and is using InMobi versions 3.6.2
to 4.0.2, an attacker over the network (for example, using Wi-Fi or
DNS hijacking) could abuse the makeCall
annotation in the
app to make phone calls on the device without a user’s consent –
including to premium numbers.
In addition, without requiring special Android permissions in the
host app, attackers over the network, via HTTP or DNS hijacking, could
also misuse the aforementioned exposed methods to misguide the user to
post to the user’s social network from the device
(postToSocial
in version 3.7.0 and above), send email to
any designated recipient with a pre-crafted title and email body
(sendMail
in version 3.6.2 and above), send SMS to
premium numbers (sendSMS
in version 3.6.2 and above),
create calendar events on the device (createCalendarEvent
in version 3.7.0 and above), and to take pictures and access the photo
gallery on the device (takeCameraPicture
and
getGalleryImage
in version 3.7.0 and above). To complete
these actions, the user would need to click on certain consent
buttons. However, as generally known, users are quite vulnerable to
social engineering attacks through which attackers could trick users
to give consent.
We have identified more than 3,000 apps on Google Play that contain versions 2.5.0 to 4.0.2 of InMobi – and which have over 100,000 downloads each as of December, 2013. Currently, the total download count for these affected apps is greater than 3.7 billion.
We have informed both Google and InMobi of our findings, and they have been actively working to address them.
New InMobi Update after FireEye Notification
After we notified the InMobi vendor about these security issues, they promptly released new SDK versions 4.0.3 and 4.0.4. The 4.0.3 SDK, marked as “Internal release”, was superseded by 4.0.4 after one day. The 4.0.4 SDK made the following changes:
makeCall
) to require user’s consent.storePicture
interface to download and
save specified files from the Internet to the user’s Downloads
folder. Despite the name, it can be used for any file, not just images.Compared with InMobi’s earlier versions, we consider change No. 1 as an improvement that addresses the aforementioned issue of an attacker making phone calls without a user’s consent. We are glad to see that InMobi made this change after our notification.
InMobi recently released a new SDK version 4.1.0. Compared with SDK version 4.0.4, we haven't seen any changes to JS Binding usage from a security perspective in this new SDK version 4.1.0.
Moving Forward: Improving Security for JS Binding in Third-party Libraries
In summary, the insecure usage of JS Binding and JS Binding annotations in third-party libraries exposes many apps that contain these libraries to security risks.
App developers and third-party library vendors often focus on new features and rich functionalities. However, this needs to be balanced with a consideration for security and privacy risks. We propose the following to the mobile application development and library vendor community:
Since customers may have different requirements regarding security and privacy, apps with JS-Binding-Over-HTTP vulnerabilities and JS sidedoors can introduce risks to security-sensitive environments such as enterprise networks. FireEye Mobile Threat Prevention provides protection to our customers from these kinds of security threats.
Acknowledgement
We thank our team members Adrian Mettler and Zheng Bu for their help in writing this blog.
Appendix A: JavaScript Code Snippets Served from InMobi Ad Servers
a.takeCameraPicture = function () {utilityController.takeCameraPicture()
};
a.getGalleryImage = function () {
utilityController.getGalleryImage()
};
a.makeCall = function (f) {
try {
utilityController.makeCall(f)
} catch (d) {
a.showAlert("makeCall: " + d)
}
};
a.sendMail = function (f, d, b) {
try {
utilityController.sendMail(f, d, b)
} catch (c) {
a.showAlert("sendMail: " + c)
}
};
a.sendSMS = function (f, d) {
try {
utilityController.sendSMS(f, d)
} catch (b) {
a.showAlert("sendSMS: " + b)
}
};
a.postToSocial = function (a, c, b, e) {
a = parseInt(a);
isNaN(a) && window.mraid.broadcastEvent("error", "socialType must be an integer", "postToSocial");
"string" != typeof c && (c = "");
"string" != typeof b && (b = "");
"string" != typeof e && (e = "");
utilityController.postToSocial(a, c, b, e)
};
a.createCalendarEvent = function (a) {
"object" != typeof a && window.mraid.broadcastEvent("error",
"createCalendarEvent method expects parameter", "createCalendarEvent");
"string" != typeof a.start || "string" != typeof a.end ?
window.mraid.broadcastEvent("error",
"createCalendarEvent method expects string parameters for start and end dates",
"createCalendarEvent") :
("string" != typeof a.location && (a.location = ""),
"string" != typeof a.description && (a.description = ""),
utilityController.createCalendarEvent(a.start, a.end, a.location, a.description))
};
a.registerMicListener=function() {
utilityController.registerMicListener()
};
Click to Open Code Editor