前言

  • 如今非常多App里都内置了Web网页(Hyprid App),比方说非常多电商平台。淘宝、京东、聚划算等等。例如以下图

  • 上述功能是由 Android的WebView 实现的。可是 WebView 使用过程中存在很多漏洞,easy造成用户数据泄露等等危急,而非常多人往往会忽视这个问题
  • 今天我将全面介绍 Android WebView的使用漏洞 及其修复方式

阅读本文前请先阅读:

Android开发:最全面、最易懂的Webview详细解释

最全面 & 最详细的 Android WebView与JS的交互方式 汇总


文件夹

imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="文件夹" title="">


1. 类型

WebView中。主要漏洞有三类:

  • 随意代码运行漏洞
  • password明文存储漏洞
  • 域控制不严格漏洞

2. 详细分析

2.1 WebView 随意代码运行漏洞

出现该漏洞的原因有三个:

  • WebView 中 addJavascriptInterface() 接口
  • WebView 内置导出的 searchBoxJavaBridge_对象
  • WebView 内置导出的 accessibilityaccessibilityTraversalObject 对象

2.1.1 addJavascriptInterface 接口引起远程代码运行漏洞

A. 漏洞产生原因

JS调用Android的当中一个方式是通过addJavascriptInterface接口进行对象映射:

 webView.addJavascriptInterface(new JSObject(), "myObj");
// 參数1:Android的本地对象
// 參数2:JS的对象
// 通过对象映射将Android中的本地对象和JS中的对象进行关联,从而实现JS调用Android的对象和方法

所以,漏洞产生原因是:当JS拿到Android这个对象后。就能够调用这个Android对象中全部的方法,包含系统类(java.lang.Runtime 类)。从而进行随意代码运行。

如能够运行命令获取本地设备的SD卡中的文件等信息从而造成信息泄露

详细获取系统类的描写叙述:(结合 Java 反射机制)

  • Android中的对象有一公共的方法:getClass() ;
  • 该方法能够获取到当前类 类型Class
  • 该类有一关键的方法: Class.forName。
  • 该方法能够载入一个类(可载入 java.lang.Runtime 类)
  • 而该类是能够运行本地命令的

下面是攻击的Js核心代码:

function execute(cmdArgs)
{
// 步骤1:遍历 window 对象
// 目的是为了找到包含 getClass ()的对象
// 因为Android映射的JS对象也在window中,所以肯定会遍历到
for (var obj in window) {
if ("getClass" in window[obj]) { // 步骤2:利用反射调用forName()得到Runtime类对象
alert(obj);
return window[obj].getClass().forName("java.lang.Runtime") // 步骤3:以后,就能够调用静态方法来运行一些命令。比方訪问文件的命令
getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs); // 从运行命令后返回的输入流中得到字符串。有非常严重暴露隐私的危急。 // 如运行完訪问文件的命令之后,就能够得到文件名称的信息了。
}
}
}
  • 当一些 APP 通过扫描二维码打开一个外部网页时。攻击者就能够运行这段 js 代码进行漏洞攻击。
  • 在微信盛行、扫一扫行为普及的情况下。该漏洞的危急性非常大

B. 解决方式

B1. Android 4.2版本号之后

Google 在Android 4.2 版本号中规定对被调用的函数以 @JavascriptInterface进行注解从而避免漏洞攻击

B2. Android 4.2版本号之前

在Android 4.2版本号之前採用拦截prompt()进行漏洞修复。

详细过程例如以下:

  • 继承 WebView ,重写 addJavascriptInterface 方法,然后在内部自己维护一个对象映射关系的 Map;

    将须要加入的 JS 接口放入该Map中

  • 每次当 WebView 载入页面前载入一段本地的 JS 代码,原理是:

    • 让JS调用一Javascript方法:该方法是通过调用prompt()把JS中的信息(含特定标识。方法名称等)传递到Android端;
    • 在Android的onJsPrompt()中 。解析传递过来的信息。再通过反射机制调用Java对象的方法,这样实现安全的JS调用Android代码。

关于Android返回给JS的值:可通过prompt()把Java中方法的处理结果返回到Js中

详细须要载入的JS代码例如以下:

javascript:(function JsAddJavascriptInterface_(){
// window.jsInterface 表示在window上声明了一个Js对象 // jsInterface = 注冊的对象名
// 它注冊了两个方法,onButtonClick(arg0)和onImageClick(arg0, arg1, arg2)
// 假设有返回值,就加入上return
if (typeof(window.jsInterface)!='undefined') {
console.log('window.jsInterface_js_interface_name is exist!!');}
else {
window.jsInterface = { // 声明方法形式:方法名: function(參数)
onButtonClick:function(arg0) {
// prompt()返回约定的字符串
// 该字符串可自定义
// 包含特定的标识符MyApp和 JSON 字符串(方法名,參数。对象名等)
return prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onButtonClick',args:[arg0]}));
}, onImageClick:function(arg0,arg1,arg2) {
return
prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onImageClick',args:[arg0,arg1,arg2]}));
},
};
}
}
)() // 当JS调用 onButtonClick() 或 onImageClick() 时。就会回调到Android中的 onJsPrompt ()
// 我们解析出方法名,參数,对象名
// 再通过反射机制调用Java对象的方法

关于该方法的其它细节

细节1:载入上述JS代码的时机

  • 因为当 WebView 跳转到下一个页面时,之前载入的 JS 可能已经失效
  • 所以,通常须要在下面方法中载入 JS:
onLoadResource()。
doUpdateVisitedHistory();
onPageStarted()。
onPageFinished();
onReceivedTitle();
onProgressChanged()。

细节2:须要过滤掉 Object 类的方法

  • 因为终于是通过反射得到Android指定对象的方法。所以同一时候也会得到基类的其它方法(最顶层的基类是 Object类)
  • 为了不把 getClass()等方法注入到 JS 中,我们须要把 Object 的共同拥有方法过滤掉,须要过滤的方法列表例如以下:
getClass()
hashCode()
notify()
notifyAl()
equals()
toString()
wait()

总结

  • 对于Android 4.2曾经,须要採用拦截prompt()的方式进行漏洞修复
  • 对于Android 4.2以后,则仅仅须要对被调用的函数以 @JavascriptInterface进行注解
  • 关于 Android 系统占比,Google发布的数据:截止 2017 .1 .8 。Android4.4 之下占有约15%。所以须要重视。

    详细数据例如以下:

2.1.2 searchBoxJavaBridge_接口引起远程代码运行漏洞

A. 漏洞产生原因

  • 在Android 3.0下面,Android系统会默认通过searchBoxJavaBridge_的Js接口给 WebView 加入一个JS映射对象:searchBoxJavaBridge_对象
  • 该接口可能被利用。实现远程随意代码。

B. 解决方式

删除searchBoxJavaBridge_接口

// 通过调用该方法删除接口
removeJavascriptInterface();

2.1.3 accessibilityaccessibilityTraversal接口引起远程代码运行漏洞

问题分析与解决方式同上,这里不作过多阐述。

2.2 password明文存储漏洞

2.2.1 问题分析

WebView默认开启password保存功能 :

mWebView.setSavePassword(true)`
  • 开启后,在用户输入password时,会弹出提示框:询问用户是否保存password;
  • 假设选择”是”,password会被明文保到 /data/data/com.package.name/databases/webview.db 中,这样就有被盗取password的危急

2.2.2 解决方式

关闭password保存提醒

WebSettings.setSavePassword(false) 

2.3 域控制不严格漏洞

2.3.1 问题分析

先看Android里的WebViewActivity.java

public class WebViewActivity extends Activity {
private WebView webView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_webview);
webView = (WebView) findViewById(R.id.webView); //webView.getSettings().setAllowFileAccess(false); (1)
//webView.getSettings().setAllowFileAccessFromFileURLs(true); (2)
//webView.getSettings().setAllowUniversalAccessFromFileURLs(true); (3)
Intent i = getIntent();
String url = i.getData().toString(); //url = file:///data/local/tmp/attack.html
webView.loadUrl(url);
}
} /**Mainifest.xml**/
// 将该 WebViewActivity 在Mainifest.xml设置exported属性
// 表示:当前Activity能否够被还有一个Application的组件启动
android:exported="true"

即 A 应用能够通过 B 应用导出的 Activity 让 B 应用载入一个恶意的 file 协议的 url,从而能够获取 B 应用的内部私有文件,从而带来数据泄露威胁

详细:当其它应用启动此 Activity 时。 intent 中的 data 直接被当作 url 来载入(假定传进来的 url 为 file:///data/local/tmp/attack.html ),其它 APP 通过使用显式 ComponentName 或者其它相似方式就能够非常轻松的启动该 WebViewActivity 并载入恶意url。

下面我们着重分析WebView中getSettings类的方法对 WebView 安全性的影响:

  • setAllowFileAccess()
  • setAllowFileAccessFromFileURLs()
  • setAllowUniversalAccessFromFileURLs()

1. setAllowFileAccess()

// 设置是否同意 WebView 使用 File 协议
webView.getSettings().setAllowFileAccess(true);
// 默认设置为true。即同意在 File 域下运行随意 JavaScript 代码

使用 file 域载入的 js代码能够使用进行同源策略跨域訪问,从而导致隐私信息泄露

  1. 同源策略跨域訪问:对私有文件夹文件进行訪问
  2. 针对 IM 类产品,泄露的是聊天信息、联系人等等
  3. 针对浏览器类软件,泄露的是cookie 信息泄露。

假设不同意使用 file 协议,则不会存在上述的威胁;

webView.getSettings().setAllowFileAccess(true);     

但同一时候也限制了 WebView 的功能,使其不能载入本地的 html 文件,例如以下图:

移动版的 Chrome 默认禁止载入 file 协议的文件

imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="Paste_Image.png" title="">

解决方式:

  • 对于不须要使用 file 协议的应用,禁用 file 协议。
setAllowFileAccess(false); 
  • 对于须要使用 file 协议的应用,禁止 file 协议载入 JavaScript。
setAllowFileAccess(true); 

// 禁止 file 协议载入 JavaScript
if (url.startsWith("file://") {
setJavaScriptEnabled(false);
} else {
setJavaScriptEnabled(true);
}

2. setAllowFileAccessFromFileURLs()

// 设置是否同意通过 file url 载入的 Js代码读取其它的本地文件
webView.getSettings().setAllowFileAccessFromFileURLs(true);
// 在Android 4.1前默认同意
// 在Android 4.1后默认禁止

AllowFileAccessFromFileURLs()设置为 true 时。攻击者的JS代码为:


<script>
function loadXMLDoc()
{
var arm = "file:///etc/hosts";
var xmlhttp;
if (window.XMLHttpRequest)
{
xmlhttp=new XMLHttpRequest();
}
xmlhttp.onreadystatechange=function()
{
//alert("status is"+xmlhttp.status);
if (xmlhttp.readyState==4)
{
console.log(xmlhttp.responseText);
}
}
xmlhttp.open("GET",arm);
xmlhttp.send(null);
}
loadXMLDoc();
</script> // 通过该代码可成功读取 /etc/hosts 的内容数据

解决方式:设置setAllowFileAccessFromFileURLs(false);

当设置成为 false 时。上述JS的攻击代码运行会导致错误,表示浏览器禁止从 file url 中的 javascript 读取其它本地文件。

3. setAllowUniversalAccessFromFileURLs()

// 设置是否同意通过 file url 载入的 Javascript 能够訪问其它的源(包含http、https等源)
webView.getSettings().setAllowUniversalAccessFromFileURLs(true); // 在Android 4.1前默认同意(setAllowFileAccessFromFileURLs()不起作用)
// 在Android 4.1后默认禁止

AllowFileAccessFromFileURLs()被设置成true时,攻击者的JS代码是:

// 通过该代码可成功读取 http://www.so.com 的内容
<script>
function loadXMLDoc()
{
var arm = "http://www.so.com";
var xmlhttp;
if (window.XMLHttpRequest)
{
xmlhttp=new XMLHttpRequest();
}
xmlhttp.onreadystatechange=function()
{
//alert("status is"+xmlhttp.status);
if (xmlhttp.readyState==4)
{
console.log(xmlhttp.responseText);
}
}
xmlhttp.open("GET",arm);
xmlhttp.send(null);
}
loadXMLDoc();
</script>

解决方式:设置setAllowUniversalAccessFromFileURLs(false);

4. setJavaScriptEnabled()

// 设置是否同意 WebView 使用 JavaScript(默认是不同意)
webView.getSettings().setJavaScriptEnabled(true); // 但非常多应用(包含移动浏览器)为了让 WebView 运行 http 协议中的 JavaScript,都会主动设置为true,不差别对待是非常危急的。

即使把setAllowFileAccessFromFileURLs()setAllowUniversalAccessFromFileURLs()都设置为 false,通过 file URL 载入的 javascript 仍然有方法訪问其它的本地文件:符号链接跨源攻击

前提是同意 file URL 运行 javascript。即webView.getSettings().setJavaScriptEnabled(true);

这一攻击能奏效的原因是:通过 javascript 的延时运行和将当前文件替换成指向其它文件的软链接就能够读取到被符号链接所指的文件

详细攻击步骤:

1. 把恶意的 js 代码输出到攻击应用的文件夹下,随机命名为 xx.html,改动该文件夹的权限;

2. 改动后休眠 1s,让文件操作完毕;

3. 完毕后通过系统的 Chrome 应用去打开该 xx.html 文件

4. 等待 4s 让 Chrome 载入完毕该 html,最后将该 html 删除,而且使用 ln -s 命令为 Chrome 的 Cookie 文件创建软连接

注:在该命令运行前 xx.html 是不存在的;运行完这条命令之后,就生成了这个文件。而且将 Cookie 文件链接到了 xx.html 上。

于是就可通过链接来訪问 Chrome 的 Cookie

  1. Google 没有进行修复,仅仅是让Chrome 最新版本号默认禁用 file 协议。所以这一漏洞在最新版的 Chrome 中并不存在
  2. 可是,在日常大量使用 WebView 的App和浏览器,都有可能受到此漏洞的影响。

    通过利用此漏洞。easy出现数据泄露的危急

假设是 file 协议,禁用 javascript 能够非常大程度上减小跨源漏洞对 WebView 的威胁。

  1. 但并不能全然杜绝跨源文件泄露。
  2. 例:应用实现了下载功能,对于无法载入的页面。会自己主动下载到 sd 卡中;因为 sd 卡中的文件全部应用都能够訪问。于是能够通过构造一个 file URL 指向被攻击应用的私有文件。然后用此 URL 启动被攻击应用的 WebActivity,这样因为该 WebActivity 无法载入该文件,就会将该文件下载到 sd 卡下面,然后就能够从 sd 卡上读取这个文件了

终于解决方式

  • 对于不须要使用 file 协议的应用,禁用 file 协议;
// 禁用 file 协议;
setAllowFileAccess(false);
setAllowFileAccessFromFileURLs(false);
setAllowUniversalAccessFromFileURLs(false);
  • 对于须要使用 file 协议的应用,禁止 file 协议载入 JavaScript。
// 须要使用 file 协议
setAllowFileAccess(true);
setAllowFileAccessFromFileURLs(false);
setAllowUniversalAccessFromFileURLs(false); // 禁止 file 协议载入 JavaScript
if (url.startsWith("file://") {
setJavaScriptEnabled(false);
} else {
setJavaScriptEnabled(true);
}

3. 总结


请帮顶或评论点赞!

因为你们的鼓舞是我写作的最大动力!

Android:你不知道的 WebView 使用漏洞的更多相关文章

  1. Android中WebView的JavaScript代码和本地代码交互的三种方式

    一.Android中WebView的漏洞分析最近在开发过程中遇到一个问题,就是WebView使用的时候,还是需要解决之前系统(4.2之前)导致的一个漏洞,虽然现在这个系统版本用户很少了,但是也不能忽视 ...

  2. Android安全之WebViewUXSS漏洞

    Android安全 WebView UXSS app开发 漏洞分析 移动安全 0X01 前言 XSS是我们比较熟悉的一种攻击方式,包括存储型XSS.反射型XSS.DOM XSS等,但UXSS(通用型X ...

  3. Android 使用WebView显示网页

    构建WebView就可以显示Web信息.因为我觉得这里会讲述很多方式来实现WebView,所以我决定为每一种方式创建一个对应的Activity,MainActivity通过Button可以点击进入对应 ...

  4. Android的WebView有哪些坑?

    今天逛知乎的时候,看到一个有关Android应用开发中,WebView 的问题,算是开发中比较常见的问题了吧,而且赞同数比较多的答案,确实回答得还不错,这里小编就整理了一下,分享出来大家借鉴借鉴,避免 ...

  5. Android的WebView通过JS调用java代码

    做项目时候会遇到我们用WebView 打开一个web,希望这个web可以调用自己的一些方法,比如我们在进一个web页面,然后当我们点击web上的某个按钮时,希望能判断当前手机端是否已经登录,如果未登录 ...

  6. Android中webView和网页的交互

     Android中webView和网页的交互 Android中webView跟网页的交互式通过JavaScript进行的.具体步骤: 1.创建JavaScript,在点击的时候调用JavaScript ...

  7. Android 显示 WebView ,加载URL 时,向webview的 header 里面传递参数

    1.主要布局 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:and ...

  8. Android中Webview使用自定义的javascript进行回调

    先说为什么需要讨论这个问题. 现在很多的手机应用,都可能会直接嵌入一个web页面.这样做的好处:一个是功能更新方便,维护起来容易,只需要维护服务器的页面即可,不需要更新客户端:另一个是功能通用,不仅a ...

  9. android使用Webview上传图片

    package com.example.webview; import java.io.File; import android.net.Uri;import android.os.Bundle;im ...

随机推荐

  1. Jmeter-Maven-Plugin高级应用:Remote Server Configuration

    Remote Server Configuration Pages 12 Home Adding additional libraries to the classpath Advanced Conf ...

  2. 一个简单RPC框架是怎样炼成的(IV)——实现RPC消息的编解码

    之前我们制定了一个非常easy的RPC消息 的格式,可是还遗留了两个问题,上一篇解决掉了一个.还留下一个 我们并没有实现对应的encode和decode方法,没有基于能够跨设备的字符串传输,而是直接的 ...

  3. Mapreduce实例-分组排重(group by distinct)

    public class GroupComparator implements RawComparator<MyBinaryKey> { @Override public int comp ...

  4. C-main函数剖析。

    对于main函数.我想不论什么一个接触到C语言的都不会陌生,可是说起main()函数有參数,你可能会产生非常多疑问了. 首先,我们来看下msdn,这个里面对main()函数有具体的说明. 在这里,我们 ...

  5. tarfile模块可以方操作tar归档文件

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #Python自带的tarfile模块可以方便读取tar归档文件 #http://www.open-open. ...

  6. java Socket Udp聊天

    import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import jav ...

  7. Loadrunner脚本编程(2)-VuGen脚本文件的开发过程

    http://www.360doc.com/content/10/0806/13/1698198_44076570.shtml 1.定义测试项目的目标,环境,脚本,测试数据,硬件等.脚本应该符合编码规 ...

  8. java线上应用问题排查方法和工具

    linux性能监测点 CPU, Memory, IO, Network Linux性能监测工具-cpu 基本概念: 上下文切换(Context Switches): 如果可运行的线程数大于CPU的数量 ...

  9. iOS-启动动态页跳过设计思路

    概述 根据UIBezierPath和CAShapeLayer自定义倒计时进度条,适用于app启动的时候设置一个倒计时关闭启动页面.可以设置进度条颜色,填充颜色,进度条宽度以及点击事件等. 详细 代码下 ...

  10. 【laravel5.4】laravel5.4系列之生成_ide_helper.php文件

    在laravle中使用代码自动补全,比较方便开发,于是这边找到了相关的办法 在laravel配置完好的情况下,同时安装好了composer. 进入代码的根目录执行 composer require b ...