Android WebView Vulnerabilities

今天专门总结一下Android Webview漏洞,因为这是一个安全大坑,我也被坑了…郁闷,平时复习一下就好了

1 基本开发知识:

If you want to deliver a web application (or just a web page) as a part of a client application, you can do it using WebView。顾名思义就是开发web app之类的,用处很多,不详细讲了,看开发文档写得很清楚

  • 添加Webview,步骤为写配置文件到layout,建立Webview类,然后取得Internet权限,一目了然
写配置文件:
<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
新建类:
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadUrl("http://www.example.com");
申请Internet权限:
<manifest ... >
<uses-permission android:name="android.permission.INTERNET" />
...
</manifest>
  • 使用JavaScript(JavaScript is disabled in a WebView by default)
通过Websettings开启JavaScript
WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
  • 通过绑定JavaScript和你指定的android代码,让JavaScript可以调用你指定的代码,例如你定义了一个WebAppInterface类
public class WebAppInterface {
Context mContext;

/** Instantiate the interface and set the context */
WebAppInterface(Context c) {
mContext = c;
}

/** Show a toast from the web page */
@JavascriptInterface /*新的要求,加注解,API17以上*/
public void showToast(String toast) {
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
}
}


WebView webView = (WebView) findViewById(R.id.webview);
webView.addJavascriptInterface(new WebAppInterface(this), "Android");
  • 到此,JavaScript就可以调用你定义的函数了
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />

<script type="text/javascript">
function showAndroidToast(toast) {
Android.showToast(toast); /*There's no need to initialize the Android interface from JavaScript. The WebView automatically makes it available to your web page
}
</script>

2 存在的安全问题:

1 Webview 任意代码执行漏洞

  1. 问题方法”addJavascriptInterface()”,上文基础部分中提到这个方法让JavaScript调用你定义的JAVA函数
mWebView.addJavascriptInterface(new TestAddJsInterface(), “myjs”);
  1. 在API17之前,上面的“addJavascriptInterface()”方法会导致出现问题,网页中的JS脚本可以利用接口“myjs”调用App中的Java代码,而Java对象继承关系会导致很多Public的函数及getClass函数都可以在JS中被访问,结合Java的反射机制,攻击者还可以获得系统类的函数,进而可以进行任意代码执行

类似的攻击代码如下:

function execute(cmdArgs)  
{
// 步骤1:遍历 window 对象
// 目的是为了找到包含 getClass()的对象
// 因为Android映射的"myjs"对象也在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);

// 从执行命令后返回的输入流中得到字符串,有很严重暴露隐私的危险。
// 如执行完访问文件的命令之后,就可以得到文件名的信息了。
}
}
}
  1. 当一些 APP 通过扫描二维码打开一个外部网页时,攻击者就可以执行这段 js 代码进行漏洞攻击

  2. 关键的JAVA反射思路如下:

  • JAVA中的对象有一公共的方法:getClass() ;
  • 该方法可以获取到当前类的Class对象
  • 该类有一关键的方法: Class.forName;
  • 该方法可以加载一个类(可加载 java.lang.Runtime 类)
  • 而该类是可以执行本地命令的
  1. 解决方案:

Google在API_17中规定允许被调用的函数必须以@JavascriptInterface进行注解,理论上如果APP依赖的API为17或者以上,就不会受该问题的影响。所以检查API的版本和关键函数的注解可以有效识别漏洞

2 WebView域控制不严格漏洞

这个漏洞主要出现在了对file协议的控制不当上,通过4个API来理解WebView中file协议的安全性,下面的代码是新建一个Webview,通过发送Intent调用这个export的activity,把intent中的data作为url传入Webview,这个data是攻击者可控的

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.webView1);
//webView.getSettings().setAllowFileAccess(false); (1)
//webView.getSettings().setJavaScriptEnabled(true); (2)
//webView.getSettings().setAllowFileAccessFromFileURLs(true); (3)
//webView.getSettings().setAllowUniversalAccessFromFileURLs(true); (4)
Intent i = getIntent();
String url = i.getData().toString();
webView.loadUrl(url);
}
}

/Mainifest.xml/
// 将该 WebViewActivity 在Mainifest.xml设置exported属性
// 表示:当前Activity是否可以被另一个Application的组件启动
android:exported=”true”

  1. setAllowFileAccess

设置是否允许 WebView 使用 File 协议 ,默认设置为true,即允许在 File 域下执行任意 JavaScript 代码 ,使用 file 域加载的 js代码能够使用进行同源策略跨域访问,从而导致隐私信息泄露,如果不允许使用 file 协议,则不会存在上述的威胁;但同时也限制了 WebView 的功能,使其不能加载本地的 html 文件

  1. setAllowFileAccessFromFileURLs

设置是否允许通过 file url 加载的 Js代码读取其他的本地文件,当这个方法为true时,攻击者可以读取本地敏感文件
在Android 4.1前默认允许
在Android 4.1后默认禁止

  1. setAllowUniversalAccessFromFileURLs
    设置是否允许通过 file url 加载的 Javascript 可以访问其他的源(包括http、https等源)
    在Android 4.1前默认允许(setAllowFileAccessFromFileURLs()不起作用)
    在Android 4.1后默认禁止

  2. setJavaScriptEnabled

设置是否允许 WebView 使用 JavaScript(默认是不允许)
但很多应用(包括移动浏览器)为了让 WebView 执行 http 协议中的 JavaScript,都会主动设置为true,不区别对待是非常危险的。

  1. 符号链接跨源攻击 (不看)

  2. 最佳设置

  • 对于不需要使用 file 协议的应用,禁用 file 协议;

  • 对于需要使用 file 协议的应用,禁止 file 协议加载 JavaScript。

明文保存密码

  1. WebView默认开启密码保存功能 :
mWebView.setSavePassword(true)

开启后,在用户输入密码时,会弹出提示框:询问用户是否保存密码;
如果选择”是”,密码会被明文保到 /data/data/com.package.name/databases/webview.db 中,这样就有被盗取密码的危险

  1. 关闭密码保存提醒
WebSettings.setSavePassword(false)

SSL Error Handling

直接忽略了SSL错误的处理方法,让程序继续运行,让程序有机会收到Mitm

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler,
SslError error)
{
handler.proceed();
}

refer link:

https://pentestlab.blog/2017/02/12/android-webview-vulnerabilities/

https://developer.android.com/guide/webapps/webview.html

https://www.jianshu.com/p/3a345d27cd42

https://www.jianshu.com/p/5b3acad0f025

http://blogs.360.cn/360mobile/2014/09/22/webview%E8%B7%A8%E6%BA%90%E6%94%BB%E5%87%BB%E5%88%86%E6%9E%90/