本文将分为三部分进行详细讲解:
JavaScript 和 webView 通信的基本使用方法;
通过反编译, 快速定位攻击路径, 调用 JS 接口获取用户信息, 植入钓鱼网站;
解决办法; 结果如下:
众所周知, H5+JS 接口 + Webview 这种混合开发模式十分普遍, 市场上面绝大部分应用或多或少都是用了.
本文实例讲解的是当前市场上用户量较大的一款互联网金融 App, 注册用户数几百万, 流水达几十亿. 在本文之前已经将漏洞告知对方, 这里为了保密不提及应用名称, 包名.
优点如下:
1. 开发快捷, 维护方便, 由于页面采用的是 H5, 所以版本兼容性也比较好;
2. 有效的减小 apk 的大小, 别小看这点, 当项目 apk 大小达到 100M 左右, 减小 apk 体积就是一个很重要的 KPI 了;
3. 适合数据开放, 接入合作方的 H5 页面, 在 APK 内调用对外的 JS 接口获取 apk 内的开放数据;
4. 如果在 webview 里面设置好缓存, 离线包等加载方式加载速度体验也挺好的;
缺点:
虽然讲述了需多优点, 但是有一个致命的安全问题需要引起大家的格外注意, 那就是对外暴露的 JS 接口如果没有严格的健全机制很容易被恶意调用, 泄漏用户的隐私数据, 或者调用接口植入钓鱼网站.
JavaScript 和 WebView 通信的基本使用方法;
webview 的设置
- // 首先允许 webview 执行 JS 脚本
- settings.setJavaScriptEnabled(true);
- // 给 webview 注入一个 java 对象供 H5 的 JS 调用其对外的方法
- mWebView.addJavascriptInterface(new JSObject(),"JavascriptInterface");
注入的 java 对象里面增加 H5 调用的方法
- public class JSObject {
- @JavascriptInterface
- public void getAppInfo(String param1,String param2){
- }
- }
H5 调用 Native 方法示例:
- <script type="text/javascript">
- // 提供给 Native 侧调用
- function say(text) {
- alert(text)
- }
- function getResult(message) {
- return message;
- }
- // 调用 Native 侧的接口
- function getNativeAppInfo(){
- Windows.JavascriptInterface.getAppInfo()
- }
- </script>
Native 调用 H5 的函数进行传值
方法一:
webView.loadUrl("javascript:say(\"" + "xxxxxxxxxx" + "\")");
方法二:
- webView.evaluateJavascript("getResult(\""+"xxxxx'"+"\")", new ValueCallback<String>() {
- @Override
- public void onReceiveValue(String value) {
- Log.i(TAG, "onReceiveValue value=" + value);
- }
- });
以上就是 JavaScript 和 WebView 通信的基本使用方法
通过反编译, 快速定位攻击路径, 调用 JS 接口获取用户信息, 植入钓鱼网站
反编译步骤:
1.java -jar apktool_2.3.3.jar d -f xxx.apk
使用 apktool 这个工具将一个 apk 反编译得到图片, xml 配置, 语言资源等文件.
2. sh d2j-dex2jar.sh classes.dex
获取 classes-dex2jar.jar
3. 使用 java -jar jd-gui-1.4.0.jar 查看源码
我们通过反编译查看 AndroidManifest 文件, 查找 scheme 关键字, 看下该应用对外暴露了哪些组件同时可以通过 scheme 拉起来. 和大部分 App 一样, 该金融 App 的 Splash 页面允许被外部拉起.
- <activity Android:name="com.xxxxx.SplashScreenActivity" Android:screenOrientation="portrait" Android:theme="@style/SplashTheme">
- <intent-filter>
- <action Android:name="android.intent.action.MAIN"/>
- <category Android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- <intent-filter>
- <action Android:name="android.intent.action.VIEW"/>
- <category Android:name="android.intent.category.DEFAULT"/>
- <category Android:name="android.intent.category.BROWSABLE"/>
- <data Android:host="xxxhost" Android:pathPrefix="/openwith" Android:scheme="xxxschemeapp"/>
- </intent-filter>
- <intent-filter>
- <action Android:name="android.intent.action.VIEW"/>
- <category Android:name="android.intent.category.DEFAULT"/>
- <category Android:name="android.intent.category.BROWSABLE"/>
- <data Android:scheme="xxxscheme"/>
- </intent-filter>
- </activity>
然后我们反编译查看代码, 虽然代码被混淆过了, 但是并不阻碍我们阅读它的逻辑:
我们发现在识别出 scheme 头之后, 进行了 url 的加载, gotoUrl() 函数. 然后我们再看下加载 Url 的 webview 部分代码是否有注入 Java 对象, 是否有提供数据的 JS 接口:
果不其然, 注入了 JsObject 类, 我们查看该类:
基本上该类对外提供了一个 JS 接口, 然后通过第一个参数执行不同的代码逻辑, 类似命令模式; 然后我们找到想要的接口第一个参数是什么
下面这个接口就是文章的第一个截图, 获取 App 的用户数据其中还包括手机号码
下面这个截图即是分享弹出分享按钮, 分享 url 的接口, 通过此接口可以植入一个钓鱼网站分享到微信, 微博, QQ 等, 由于有官方的应用 icon, 用户很容易被欺骗到, 输入敏感数据:
最后我们只需要在在 H5 代码中调用这两个接口即可, 这里参考第一部分的基本原理, 不贴示例代码了.
另外: 由于 scheme 是可以被浏览器拉起的, 还可以直接将组装好的 scheme 链接加入到一些网页的超链接, 用户点击之后直接拉起该应用, 具有远程攻击的可行性.
其实整体的思路就是找到暴露的组件, 反编译之后如何传参, 然后找到相关的 JS 接口, 这样一个攻击路径就找到了.
解决办法 1. 对于 webview 来说, 添加 url 白名单, 不在白名单里面的地址不加载或者不进行注入 java 对象; 2. 对接口的访问权限进行分级, 添加鉴权功能; 3. 暴露的组件也可以对传入的 scheme url 进行校验, 增加攻击者的难度等等
如果您还有更好的解决办法, 欢迎留言.
来源: https://juejin.im/post/5c5556686fb9a049e413238a