Android WebView Js object injection vulnerability Solution

Source: Internet
Author: User

Directory
1. Use Cases
2. Vulnerability description
3 vulnerability proof
4 solutions
5. Some Thoughts
A serious security vulnerability was found in a project recently, which was reported by wooyun platform.
1. application scenarios
We often use WebView to display a webpage. Many applications now use web pages instead of local implementation to control the server, which has many advantages, for example, you do not need to re-release the new version of the interface, but simply modify it on the Server. A webpage is used to display interfaces. Generally, interfaces are more or less interactive with Java code. For example, if you click a button on the webpage, you need to know the button click event, or we need to call a method to let the page execute some action. To achieve these interactions, we usually use JS to implement it. WebView already provides the following method:

 

mWebView.getSettings().setJavaScriptEnabled(true);mWebView.addJavascriptInterface(new JSInterface(), "jsInterface");

We register an object named "jsInterface" with WebView, and then we can access the jsInterface object in JS to call some methods of this object and finally call it in Java code, thus, the interaction between JS and Java code is realized.
Let's take a look at the description of addJavascriptInterface on the Android Website:

· This method can be used to allow JavaScript to control the host application. this is a powerful feature, but also presents a security risk for applications targeted to API level JELLY_BEAN or below, because JavaScript cocould use reflection to access an injected object's public fields. use of this method in a WebView containing untrusted content cocould allow an attacker to manipulate the host application in unintended ways, executing Java code with the permissions of the host application. use extreme care when using this method in a WebView which cocould contain untrusted content.
· JavaScript interacts with Java object on a private, background thread of this WebView. Care is therefore required to maintain thread safety.
· The Java object's fields are not accessible.
 
Simply put, using addJavascriptInterface may lead to insecurity, because JS may contain malicious code. Today we are talking about this vulnerability. When JavaScript contains malicious code, it can do anything.
 
2. Vulnerability description
With JavaScript, you can access anything on the SD card of the current device, including contact information and text messages. This is disgusting, grack. Okay. Let's take a look at how this error occurs. Let's take a look at this bug description on wooyun platform: click here
1. WebView adds JavaScript objects and the current application has the permission to read and write SDCard, that is, android. permission. WRITE_EXTERNAL_STORAGE.
2. JS can traverse the window object, find the object with the "getClass" method, get the Runtime object through the reflection mechanism, and then call the static method to execute some commands, for example, the command to access a file.
3. Then, obtain the file name information from the input stream returned after the command is executed. It's dangerous to do what you want. The core JS Code is as follows:

 
function execute(cmdArgs){    for (var obj in window) {        if ("getClass" in window[obj]) {            alert(obj);            return  window[obj].getClass().forName("java.lang.Runtime")                 .getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);        }    }}  

3. Vulnerability proof
Example 1: A demo is provided to illustrate this vulnerability. I just load a local webpage containing malicious JS Code. The HTML code is as follows:
<Html> 

The running effect of this section of HTML is as follows:

Figure 1: Expected running result
 
, Click the button, and pass a piece of text in JS to the Java code. A toast is displayed. Click the image and upload the URL, width, and height of the image to the Java layer, it is also displayed with toast.
To implement such a function, you need to note the Java object.
 
Brief Description
1. See the execute () method. it traverses all the window objects, finds the objects containing the getClass method, and uses the class of this object to find the java. lang. runtime object, then call the "getRuntime" static method to obtain the Runtime instance, and then call the exec () method to execute a certain command.
2. The getContents () method reads content from the stream and displays it on the interface.
3. The key code is the following two sentences:
return window[obj].getClass().forName("java.lang.Runtime").                    getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);

Java code implementation is as follows:
 
mWebView = (WebView) findViewById(R.id.webview);mWebView.getSettings().setJavaScriptEnabled(true);mWebView.addJavascriptInterface(new JSInterface(), "jsInterface");mWebView.loadUrl("file:///android_asset/html/test.html");

 
Permissions to be added:
 
<uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

After clicking the LOAD menu, run the following command: (in theory, Figure 1 is displayed)

Figure 2: the actual running result lists the objects in the SDCard.
 
Example 2: this problem also exists in the 360 browser. The android 4.0.2 and 360 browser versions are 4.8.7.
In the browser input box, enter http://bitkiller.duapp.com/jsobj.html.

Figure 3: 360 browser running result
Note: searchBoxJavaBridge _ is not a 360 injection object, but a WebView internal injection object, which is added on Android systems after 3.0.
 
After closing this dialog box, it lists all the files on the current SDCard, as shown in

Figure 4: error results
 
4. Solution
1. Android 4.2 and later Systems
In Android 4.2 and later versions, google corrected the problem by declaring a @ JavascriptInterface on the Java remote method, as shown in the following code:
class JsObject {   @JavascriptInterface   public String toString() { return "injectedObject"; }}webView.addJavascriptInterface(new JsObject(), "injectedObject");webView.loadData("", "text/html", null);webView.loadUrl("javascript:alert(injectedObject.toString())");

2. Android 4.2 or lower Systems
This problem is hard to solve, but it cannot be solved.
First, we certainly cannot call the addJavascriptInterface method. The core of this issue is to know the JS event action. We know that JS interacts with Java, such as prompt and alert, this action will correspond to the corresponding methods in the WebChromeClient class. for prompt, the corresponding method is the onJsPrompt method. The declaration of this method is as follows:
 
public boolean onJsPrompt(WebView view, String url, String message,     String defaultValue, JsPromptResult result)

Through this method, JS can transmit information (text) to Java, while Java can also transmit information (text) to JS. Can we find a solution to notify this idea?
After some attempts and analysis, find a feasible solution. See the following points:
[1] Let JS call a Javascript method. In this method, the prompt method is called, and the information in JS is passed through prompt. This information should be a piece of meaningful text we combine, it may include specific identifiers, method names, parameters, etc. In the onJsPrompt method, We parse the passed text, get the method name, parameters, and so on, and then call the specified method through the reflection mechanism to call the method of the Java object.
[2] return values can be returned through prompt, so that the processing results of methods in Java can be returned to Js.
[3] We need to dynamically generate a Javascript script that declares the Javascript method and load it through loadUrl to register it on the html page. The specific code is as follows:
javascript:(function JsAddJavascriptInterface_(){    if (typeof(window.jsInterface)!='undefined') {            console.log('window.jsInterface_js_interface_name is exist!!');}     else {        window.jsInterface = {                    onButtonClick:function(arg0) {                 return prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onButtonClick',args:[arg0]}));            },                        onImageClick:function(arg0,arg1,arg2) {                 prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onImageClick',args:[arg0,arg1,arg2]}));            },        };    }})()

Note:
1. The jsInterface in the above Code is the name of the object to be registered. It registers two methods: onButtonClick (arg0) and onImageClick (arg0, arg1, arg2). If there is a return value, add return.
2. prompt is the agreed string. It contains the specific Identifier MyApp:, followed by a string of JSON strings, including method names, parameters, and object names.
3. When JS calls onButtonClick or onImageClick, it calls back to the onJsPrompt method in the Java layer. We then parse the method name, parameter, object name, and then reflect the call method.
4. window. jsInterface indicates that a Js object is declared on the window. The method declaration form is: Method Name: function (parameter 1, parameter 2)
 
5. Some Thoughts
The following are some of the problems and thoughts encountered during the implementation of this solution:
[1] After the Js method is generated, what is the loading time for this Js method?
At the beginning, when the WebView loads the URL normally and loads Js, it finds that there will be problems. If the WebView jumps to the next page, the previously loaded Js may be invalid, so you need to load it again. After trying to solve this problem, we need to load Js in the following methods: WebChromeClient and WebViewClient:
· onLoadResource· doUpdateVisitedHistory· onPageStarted· onPageFinished· onReceivedTitle· onProgressChanged

I have tested these areas and there is no problem. I cannot make sure there is no problem here.
 
[2] Methods for filtering out Object classes
Because the method of the specified Object is obtained through reflection, the method of the base class is also obtained. The base class at the top is the Object, therefore, in order not to inject the getClass method into Js, We need to filter out the public method of the Object. Strictly speaking, there should be a list of filtering methods. Currently, in my implementation, the following methods need to be filtered:
        "getClass",        "hashCode",        "notify",        "notifyAll",        "equals",        "toString",        "wait",

 
[3] manually loadUrl to load a piece of js. Isn't the object in js not in window? That is to say, by traversing the window object, cannot we find the js object we inject through loadUrl?
Our method is declared in Js and injected to the page in the form of loadUrl, in essence, it is equivalent to writing the dynamically generated JavaScript code directly to the Html page. Therefore, although the windows in these Js files contain the objects we declare, they are not Java objects, they are declared through Js syntax, so there are no methods such as getClass. Essentially, they are Js objects.
 
[4] Under Android 3.0, the system adds a Js interface called searchBoxJavaBridge _. To solve this security problem, we also need to delete this interface and call the removeJavascriptInterface method. The searchBoxJavaBridge _ seems to be related to the google search box.
 
[5] in the implementation process, we need to determine whether the system version is earlier than 4.2, because Android has fixed this security issue. We only need to fix the system below 4.2.
 
 
Please specify the source for reprinting. Thank you !!!
 
Source code download
 
Original article: http://blog.csdn.net/leehong2005/article/details/11808557

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.