转载自 http://blog.youkuaiyun.com/carson_ho/article/details/64904635
目录
1. 类型
WebView中,主要漏洞有三类:
- 任意代码执行漏洞
- 密码明文存储漏洞
- 域控制不严格漏洞
2. 具体分析
2.1 WebView 任意代码执行漏洞
出现该漏洞的原因有三个:
- WebView 中
addJavascriptInterface()
接口 - WebView 内置导出的
searchBoxJavaBridge_
对象 - WebView 内置导出的
accessibility
和accessibilityTraversal
Object 对象
2.1.1 addJavascriptInterface 接口引起远程代码执行漏洞
A. 漏洞产生原因
JS调用Android的其中一个方式是通过addJavascriptInterface
接口进行对象映射:
- 1
- 2
- 3
- 4
所以,漏洞产生原因是:当JS拿到Android这个对象后,就可以调用这个Android对象中所有的方法,包括系统类(java.lang.Runtime 类),从而进行任意代码执行。
如可以执行命令获取本地设备的SD卡中的文件等信息从而造成信息泄露
具体获取系统类的描述:(结合 Java 反射机制)
- Android中的对象有一公共的方法:getClass() ;
- 该方法可以获取到当前类 类型Class
- 该类有一关键的方法: Class.forName;
- 该方法可以加载一个类(可加载 java.lang.Runtime 类)
- 而该类是可以执行本地命令的
以下是攻击的Js核心代码:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 当一些 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代码如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
关于该方法的其他细节
细节1:加载上述JS代码的时机
- 由于当 WebView 跳转到下一个页面时,之前加载的 JS 可能已经失效
- 所以,通常需要在以下方法中加载 JS:
- 1
- 2
- 3
- 4
- 5
- 6
细节2:需要过滤掉 Object 类的方法
- 由于最终是通过反射得到Android指定对象的方法,所以同时也会得到基类的其他方法(最顶层的基类是 Object类)
- 为了不把 getClass()等方法注入到 JS 中,我们需要把 Object 的共有方法过滤掉,需要过滤的方法列表如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
总结
- 对于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_
接口
- 1
- 2
2.1.3 accessibility
和 accessibilityTraversal
接口引起远程代码执行漏洞
问题分析与解决方案同上,这里不作过多阐述。
2.2 密码明文存储漏洞
2.2.1 问题分析
WebView默认开启密码保存功能 :
- 1
- 开启后,在用户输入密码时,会弹出提示框:询问用户是否保存密码;
- 如果选择”是”,密码会被明文保到 /data/data/com.package.name/databases/webview.db 中,这样就有被盗取密码的危险
2.2.2 解决方案
关闭密码保存提醒
- 1
2.3 域控制不严格漏洞
2.3.1 问题分析
先看Android里的WebViewActivity.java:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
即 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()
- 1
- 2
- 3
使用 file 域加载的 js代码能够使用进行同源策略跨域访问,从而导致隐私信息泄露
- 同源策略跨域访问:对私有目录文件进行访问
- 针对 IM 类产品,泄露的是聊天信息、联系人等等
- 针对浏览器类软件,泄露的是cookie 信息泄露。
如果不允许使用 file 协议,则不会存在上述的威胁;
- 1
但同时也限制了 WebView 的功能,使其不能加载本地的 html 文件,如下图:
移动版的 Chrome 默认禁止加载 file 协议的文件
解决方案:
- 对于不需要使用 file 协议的应用,禁用 file 协议;
- 1
- 对于需要使用 file 协议的应用,禁止 file 协议加载 JavaScript。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
2. setAllowFileAccessFromFileURLs()
- 1
- 2
- 3
- 4
当AllowFileAccessFromFileURLs()
设置为 true 时,攻击者的JS代码为:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
解决方案:设置setAllowFileAccessFromFileURLs(false);
当设置成为 false 时,上述JS的攻击代码执行会导致错误,表示浏览器禁止从 file url 中的 javascript 读取其它本地文件。
3. setAllowUniversalAccessFromFileURLs()
- 1
- 2
- 3
- 4
- 5
当AllowFileAccessFromFileURLs()
被设置成true时,攻击者的JS代码是:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
解决方案:设置setAllowUniversalAccessFromFileURLs(false);
4. setJavaScriptEnabled()
- 1
- 2
- 3
- 4
即使把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
- Google 没有进行修复,只是让Chrome 最新版本默认禁用 file 协议,所以这一漏洞在最新版的 Chrome 中并不存在
- 但是,在日常大量使用 WebView 的App和浏览器,都有可能受到此漏洞的影响。通过利用此漏洞,容易出现数据泄露的危险
如果是 file 协议,禁用 javascript 可以很大程度上减小跨源漏洞对 WebView 的威胁。
- 但并不能完全杜绝跨源文件泄露。
- 例:应用实现了下载功能,对于无法加载的页面,会自动下载到 sd 卡中;由于 sd 卡中的文件所有应用都可以访问,于是可以通过构造一个 file URL 指向被攻击应用的私有文件,然后用此 URL 启动被攻击应用的 WebActivity,这样由于该 WebActivity 无法加载该文件,就会将该文件下载到 sd 卡下面,然后就可以从 sd 卡上读取这个文件了
最终解决方案
- 对于不需要使用 file 协议的应用,禁用 file 协议;
- 1
- 2
- 3
- 4
- 对于需要使用 file 协议的应用,禁止 file 协议加载 JavaScript。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13