吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 11398|回复: 37
收起左侧

[Android 原创] Android App开发安全的一些浅见

  [复制链接]
amew 发表于 2018-12-4 11:34
本帖最后由 amew 于 2018-12-4 13:04 编辑

Android App开发安全的一些浅见

国内的许多app,在安全方面除了使用常规的混淆/加固策略以外,很多基本的安全策略并没有很好的得到执行。相对于论坛中Craker们的矛而言,Developer们的盾是不是也该更新一下了?本人菜鸟一枚,水平有限,只针对自己在开发中自己遇到的一些常规漏洞做一些阐述,希望能抛砖引玉,大神请指正不足。

1.AllowBackup漏洞
  • AllowBackup漏洞是远古时代为了便于刷机时恢复数据启用的一个功能,但是这个功能也造成了用户数据可以轻易地被轻易盗取(复制备份然后拷贝到新手机上)
    • adb back -nosystem -f [backup name] com.xxx.xxx
    • adb restore [backup name]
  • 由于allowbackup属性在AS中默认是开启的状态,这个很久之前就存在的漏洞在很长的一段时间里面都存在着,未加注意就有个人信息被泄露的风险,如果在数据持久化上也存在问题的话,可能账号密码什么的就这么不小心被人看见了
  • 解决方法很简单:ManifestApplication里面加上:
    • allowbackup=false
2.运行环境校验
  • 虚拟机

    • 对于已经打包上架的app而言,在虚拟机环境下运行一般不会有什么好事,许多真机上无法获取的数据/操作能够在虚拟机里面实现,因此我自己的习惯一般是不允许已经releaseapp在虚拟机中运行的
    • 对于虚拟机的判定,我用的是下面的3个方法(三个都为false时认定为虚拟机。主流真机(三星``华为``小米``oppo``一加)/虚拟机(夜神``Genymotion``原生虚拟机)亲测有效)

      private static String[] known_pipes = {
          "/dev/socket/qemud",
          "/dev/qemu_pipe"
      };
      public static boolean checkPipes() {
      for (int i = 0; i < known_pipes.length; i++) {
          String pipes = known_pipes[i];
          File qemu_socket = new File(pipes);
          if (qemu_socket.exists()) {
              return true;
          }
      }
      return false;
      }
      private static String[] known_qemu_drivers = {
          "goldfish"
      };
      public static Boolean checkQEmuDriverFile() {
      File driver_file = new File("/proc/tty/drivers");
      if (driver_file.exists() && driver_file.canRead()) {
          byte[] data = new byte[1024];  //(int)driver_file.length()
          try {
              InputStream inStream = new FileInputStream(driver_file);
              inStream.read(data);
              inStream.close();
          } catch (Exception e) {
              // TODO: handle exception
              e.printStackTrace();
          }
          String driver_data = new String(data);
          for (String known_qemu_driver : known_qemu_drivers) {
              if (driver_data.indexOf(known_qemu_driver) != -1) {
                  return true;
              }
          }
      }
      return false;
      }
      private static String[] known_files = {
          "/system/lib/libc_malloc_debug_qemu.so",
          "/sys/qemu_trace",
          "/system/bin/qemu-props"
      };
      public static boolean checkEmulatorFiles() {
      for (int i = 0; i < known_files.length; i++) {
          String file_name = known_files[i];
          File qemu_file = new File(file_name);
          if (qemu_file.exists()) {
              return true;
          }
      }
      return false;
      }
  • root环境

    • root环境对于app来讲绝对是一个重大的威胁,在su用户下所有的私有文件都没有了意义,因此,对于安全要求较高的app,在业务允许的前提下,我们可以判定在root环境下禁止运行,或者提示使用者注意安全风险.
    • Android系统本质上就是一个去除了su管理员程序的linux系统。root的获取也就是想办法强行写入su的过程,因此推论:检测root环境也就是检测是否在系统关键位置有su程序文件

      public static boolean checkSuFile() {
      Process process = null;
      try {
          process = Runtime.getRuntime().exec(new String[]{"which", "su"});
          BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
          return in.readLine() != null;
      } catch (Throwable t) {
          return false;
      } finally {
          if (process != null) process.destroy();
      }
      }
      public static boolean checkRootFile() {
      File file = null;
      String[] paths = {"/sbin/su", "/system/bin/su", "/system/xbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/system/sd/xbin/su",
              "/system/bin/failsafe/su", "/data/local/su"};
      for (String path : paths) {
          file = new File(path);
          if (file.exists()) return true;
      }
      return false;
      }
3.签名校验
  • 二次打包的危害相信每一个移动开发者都能理解,所以在条件允许的条件下,这一步的工作能做一定是要做的。
  • 签名校验最直接的逻辑,就是判断当前APP的签名MD5值是否与我们打包时使用的签名MD5值一致。最简单直接的逻辑示例如下:

    ```

    public static void apkVerifySignature(Activity activity) {
    String packageName = activity.getPackageName();
    PackageManager pm = activity.getPackageManager();
    PackageInfo pi;
    String md5;
    try {
    pi = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
    Signature[] s = pi.signatures;
    MessageDigest msgDigest = MessageDigest.getInstance("MD5");
    msgDigest.reset();
    msgDigest.update(s[0].toByteArray());
    BigInteger bInt = new BigInteger(1, msgDigest.digest());
    md5 = bInt.toString(16);
    if (!“我的签名MD5值”.equalsIgnoreCase(md5)) {
    activity.finish();
    Process.killProcess(Process.myPid());
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

  • 上面的方法最为简单,但是由于自身是Java代码中的一个判断,被破解篡改也十分容易。更进一步的方法是把这个判定链接到.so文件中,利用JNI来增强安全性,为了进一步保证代码安全,可以在执行时在.so文件中直接放入逻辑判定:如果判定签名不一致,直接制造一个Crash来造成程序崩溃。
  • 以上两种判定都只是静态代码的本地判断,只能略微增加Cracker们的破解难度而已,最保险的方法依然是加入网络判定,让服务器来进行校验签名的正确性,服务端可以拒绝非法服务,也可以返回报文让客户端结束程序自身
4.防截屏
  • 二维码本质其实就是一串字符串。其中的信息是在互联网交互时代极容易获得且极容易泄漏的部分。很多场景,如个人信息/支付等,我们是不希望这些信息被轻易获取的,加入二维码防截屏的必要性也因此而来。同样的,密码在输入时被截屏也是一种密码被窃取的路径之一
  • Android加入防截屏的方法很简单,只需在相应页面加入一行代码即可:

    ```
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
    
    ```
5.密钥
  • 密钥不要放在本地
  • 密钥不要放在本地
  • 密钥不要放在本地
  • 重要的事情说三遍。无论采用以下何种方式进行存储,包括但不限于
    • 硬编码在Java文件中
    • 硬编码在.so文件中
    • 存储为文件
    • 存储到SharedPreference
    • 存储到DataBase
  • 都是不安全的
  • RSA交互加密为例,相对安全的交互方式如下:
    1. 请求服务器获取获取服务器公钥
    2. 客户端动态生成一对公私钥,将公钥利用服务器的公钥加密传输给服务器
    3. 服务器使用服务器私钥解密报文,将真正的钥匙利用客户端公钥加密传输给客户端
    4. 客户端利用客户端私钥解密response,得到真正的钥匙,开始业务交互
6.防重放
  • 重放攻击是一种常用攻击手段,简单有效。可以是截取客户端的请求后对服务器进行重放攻击,也可以是截取服务器的报文后对客户端进行重放攻击。其中以第一种情况为多(事件响应型交互模型)
  • 防止重放攻击的手段也比较多,只需要判定每次交互的报文都不会完全一致就可以了。最通常的做法是利用时间戳+随机数字生成随机码,并入交互报文中即可
小结

以上这些只是个人对App安全的一些肤浅见解而已,本地文件的存储加密/上传下载文件交互加密/密码键盘防窃听/深度混淆/SSL双向认证等,都没有提及。软件安全的攻与防从来都是矛与盾的共同体,再次希望各路大神能够指正不足

免费评分

参与人数 19吾爱币 +15 热心值 +17 收起 理由
jaforest + 1 + 1 用心讨论,共获提升!
a2f88 + 1 确实写的很详细
OCISILY + 1 + 1 我很赞同!
Siriusol + 1 + 1 用心讨论,共获提升!
又红又专 + 1 热心回复!
无痕软件 + 2 + 1 我很赞同!
醉饮千觞 + 1 + 1 用心讨论,共获提升!
凌风者 + 1 谢谢@Thanks!
猫主任 + 1 + 1 用心讨论,共获提升!
WelcomeWorld + 1 + 1 谢谢@Thanks!
samvon + 1 + 1 我很赞同!
Airom + 1 + 1 我很赞同!
LivedForward + 1 谢谢@Thanks!
这是一团毛球 + 1 热心回复!
壁咚东 + 1 + 1 热心回复!
lylzy + 1 + 1 用心讨论,共获提升!
cgrass + 1 + 1 thanks
许小诺always + 1 鼓励转贴优秀软件安全工具和文档!
lookerJ + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| amew 发表于 2018-12-5 08:52
LivedForward 发表于 2018-12-4 23:09
这些安全防护措施目前差不多都可以被轻易hook掉!感谢作者的分享!

恩,多数还都是在代码里面的静态实现,一旦被hook都是无所遁形,只是增加一些破解成本而已,那么怎样才能更安全呢,或者说怎样的破解难度更大呢,诚心请教
 楼主| amew 发表于 2018-12-4 15:24
cy5520 发表于 2018-12-4 14:53
多按几下Tab就会好看多了

还真不是几个Tab的问题,这个网页模板对md的支持有点问题,我本地排版好好的,放到自己的个人node.js网站上也是好好的
wikiyc 发表于 2018-12-4 12:17
13551494196 发表于 2018-12-4 12:48
排版好乱
wisoft 发表于 2018-12-4 12:48
非常感谢,在分析时也可以从这些方面入手呢。
知常容 发表于 2018-12-4 13:01 来自手机
谢谢 小白很需要
头像被屏蔽
cy5520 发表于 2018-12-4 14:53
提示: 作者被禁止或删除 内容自动屏蔽
cgrass 发表于 2018-12-4 17:21
东西很清晰,谢谢分享
hc010634 发表于 2018-12-4 19:03
非常感谢,认真学习学习
龍龙科 发表于 2018-12-4 19:34
看不懂啊啊啊啊
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 00:23

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表