返回

互联网金融APP反编译攻防

Android

众所周知,H5+JS接口+Webview这种混合开发模式十分普遍,市场上面绝大部分应用或多或少都是用了。

本文实例讲解的是当前市场上用户量较大的一款互联网金融APP,注册用户数几百万,流水达几十亿。在本文之前已经将漏洞告知对方,这里为了保密不提及应用名称,包名。

虽然讲述了需多攻击技术,但本文重点还是放在攻防结合上面,在漏洞披露之前修复掉了。

漏洞发现

1. 环境搭建

反编译工具

Apktool 2.5.0
jd-gui
JEB
AndroidKiller

2.反编译

1)使用apktool反编译

java -jar apktool_2.5.0.jar d -f 80090041.apk

2)解压classes.dex文件

java -jar dex2jar-2.0.jar classes.dex

3)使用jd-gui打开jar文件

jd-gui classes-dex2jar.jar

3. 调试

正常情况下APP和Webview是通过JSInterface来调用的,在目标项目代码里搜寻关键词:

addJavascriptInterface

找到相关代码:

this.webview.addJavascriptInterface(new JSBridge(this), "JSBridge");

一般情况下,JS代码都可以直接通过WebviewClient的shouldOverrideUrlLoading回调函数拦截到,但是在APP里却没有这个回调,换句话说,这些JS代码都是在WebView内部执行的。

没办法只能用传统方法,断点调试,查看JSBridge具体做了什么。

1)加载需要用到的工具

AndroidKiller 2.0.2

2)用AndroidKiller定位到WebView控件

AKViewFinder finder = new AKViewFinder(this);
WebView view = (WebView) finder.findViewById("com.package.name", "id/webview");

3)找到并打开对应的smali文件

0002:invoke-virtual/range {v1 .. v1}, Landroid/webkit/WebView;->getSettings:()Landroid/webkit/WebSettings;
0003:const/4 v2, 0x1
0004:invoke-virtual/range {v1 .. v2}, Landroid/webkit/WebSettings;->setJavaScriptEnabled:(Z)V
0005:const/4 v2, 0x1
0006:invoke-virtual/range {v1 .. v2}, Landroid/webkit/WebSettings;->setJavaScriptCanOpenWindowsAutomatically:(Z)V
0007:invoke-virtual/range {v1 .. v1}, Landroid/webkit/WebView;->addJavascriptInterface:()Landroid/webkit/WebChromeClient;

WebView相关代码比较简单,主要核心在JSBridge这个类,具体代码如下:

public class JSBridge {

    private Context context;

    public JSBridge(Context context) {
        this.context = context;
    }

    @JavascriptInterface
    public void getUerInfo(String callback) {
        UserInfo userInfo = new UserInfo();
        userInfo.setUserName("XX");
        userInfo.setNickName("XX");
        userInfo.setSex("XX");
        userInfo.setPhone("XX");
        String json = JSON.toJSONString(userInfo);
        callback(json);
    }

    @JavascriptInterface
    public void callback(String json) {
        Log.e("JSBridge", json);
    }

}

这个JSBridge类一共有两个方法,分别是getUerInfocallback

4.利用

1)JS注入

在需要调用接口的页面使用DomInspector注入JS代码:

var getUerInfo = document.createElement('script');
getUerInfo.type = 'text/javascript';
getUerInfo.textContent = "(function(){JSBridge.getUerInfo('callback');})()";
document.body.appendChild(getUerInfo);

注入完代码后,当页面加载完成就会自动调用getUerInfo方法,然后在callback方法打印出来的就是用户的信息,这些信息也就可以上传到服务器。

2)钓鱼网站

和普通的钓鱼网站差不多,使用一个和APP一样的登录页面,然后注入JS代码去调用接口,用户在访问钓鱼网站时,先输入账号密码登录,登录后触发JS脚本,获取到用户信息后,传给钓鱼网站,钓鱼网站就可以通过这些信息来登录APP,进而操作用户账户。

漏洞修复

1.代码审计

  • 审计JSBridge类中的代码,发现getUerInfo方法没有做任何参数验证,直接把用户信息传给了JS,这就存在注入的风险。
  • 审计WebView相关代码,发现并没有对JS代码进行任何拦截或限制,这就导致JS代码可以在WebView内部任意执行。

2.代码修复

  • 修改getUerInfo方法,对参数进行验证,只允许传入白名单中的参数。
  • 在WebView中添加JS代码拦截和限制,只允许执行白名单中的JS代码。

3.修复效果验证

  • 重新编译、打包、安装APP。
  • 运行APP,访问需要调用接口的页面,发现注入的JS代码无法执行了。
  • 使用DomInspector工具,发现JSBridge类中的getUerInfo方法的参数已经受限了,只能传入白名单中的参数。