公司一款 App 有将近两年没有更新了, 虽然用户量不大, 但是因为与第三方有合作, 出现问题时需要进行维护; 没想到最近第三方对他们所有的软件进行了网络安全扫描, 这款 Android App 也未能幸免...
因为 App 是 13 年左右开发的, 维护也只是到 16,17 年左右就终止了, 所以, 扫描出不少漏洞; 因为是采用了 webview+html 混合开发, 因此, 需要解决一些 webview 相关的问题:
一, webview 隐藏接口问题 (任意命令执行漏洞)
Android webview 组件包含 3 个隐藏的系统接口: searchBoxJavaBridge_, accessibilityTraversal 以及 accessibility, 恶意程序可以通过反射机制利用它们实现远程代码执行; 该问题在 Android4.4 以下版本出现. 于是, 在 Android3.0 到 4.4 之间的版本, 我们通过移除这些隐藏接口, 来解决该问题:
- // 19 4.4 Build.VERSION.KITKAT
- // 11 3.0 Build.VERSION_CODES.HONEYCOMB
- if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.HONEYCOMB
- && Build.VERSION.SDK_INT < 19 && webView != null) {
- webView.removeJavascriptInterface("searchBoxJavaBridge_");
- webView.removeJavascriptInterface("accessibility");
- webView.removeJavascriptInterface("accessibilityTraversal");
- }
二, addJavascriptInterface 任何命令执行漏洞
在 webview 中使用 JS 与 HTML 进行交互是一个不错的方式, 但是, 在 Android4.2(16, 包含 4.2) 及以下版本中, 如果使用 addJavascriptInterface, 则会存在被注入 JS 接口的漏洞; 在 4.2 之后, 由于 Google 增加了 @JavascriptInterface, 该漏洞得以解决.
解决该问题, 最彻底的方式是在 4.2 以下放弃使用 addJavascriptInterface, 采用 onJsPrompt 或其它方法替换. 或者使用一些方案来降低该漏洞导致的风险: 如使用 https 并进行证书校验, 如果是 http 则进行页面完整性校验, 如上面所述移除隐藏接口等.
- public boolean onJsPrompt(WebView view, String url, String message,String defaultValue, JsPromptResult result) {
- result.confirm(CGJSBridge.callJava(view, message));
- Toast.makeText(view.getContext(),"message="+message,Toast.LENGTH_LONG).show();
- return true;
- }
三, 绕过证书校验漏洞
webviewClient 中有 onReceivedError 方法, 当出现证书校验错误时, 我们可以在该方法中使用 handler.proceed() 来忽略证书校验继续加载网页, 或者使用默认的 handler.cancel() 来终端加载. 因为我们使用了 handler.proceed(), 由此产生了该 "绕过证书校验漏洞". 如果确定所有页面都能满足证书校验, 则不必要使用 handler.proceed()
- @SuppressLint("NewApi")
- @Override
- public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
- //handler.proceed();// 接受证书
- super.onReceivedSslError(view, handler, error);
- }
四, allowFileAccess 导致的 File 域同源策略绕过漏洞
如果 webview.getSettings().setAllowFileAccess(boolean) 设置为 true, 则会面临该问题; 该漏洞是通过 WebView 对 JavaScript 的延时执行和 HTML 文件替换产生的. 解决方案是禁止 WebView 页面打开本地文件, 即
webview.getSettings().setAllowFileAccess(false);
或者更直接的禁止使用 JavaScript
webview.getSettings().setJavaScriptEnabled(false);
由于业务上的原因, 这个解决方案其实并不怎么理想, 如果有更好的解决方案, 欢迎指教!
来源: https://juejin.im/post/5c7b6de56fb9a049dc02f7b0