随着国内移动互联网大潮的愈发凶猛,各APP在线用户数量的急剧膨胀,APP客户端安全也逐渐引起各厂商的重视。 在日常工作中,发现某些类似的APP安全问题很多程序员都会不约而同的中枪。为了避免以后再出现类似错误,小编提炼了7种程序员们常犯的错误,以供大家交流探讨。
第一种:代码中泄露敏感信息
结合实例:我们在这里找一个平日里最易见的错误——在AndroidManifest.xml或者配置java代码中泄露微信AppSecret,微博conusemer_key等第三方应用平台密钥,如下图1,图2: 图1:某APP微信AppSecret在AndroidManifest.xml泄露
图2:某app微博conusemer_key在java配置文件中泄露 对于以上的问题,程序员也许只想在APP内嵌appid和app_key,结果疏忽大意将微信app_secret复制到代码里了。
友情提醒:代码上线前需多多检查secret,passwd等敏感关键字,切勿在发现后再选择删除;此外还提醒APP的开发人员切勿大意将自己的测试登录账户写在代码中,时刻做好代码检查工作 。
第二种:AndroidManifest.xml中allowBack = true或不显示声明为flase 危害指数: 如下是app备份开启常见的2种错误,例如AndroidManifest.xml如下配置,android:allowBackup=”true”
图3:安卓allowBack错误开启
或
图4:安卓allowBack隐式不声明为默认开启状态 如图所示,allowBack是默认开启的,必须声明为false。
第三种:重要activity权限设计不当 很多程序员误以为APP有登陆密码或者手势密码,就忽略了对app内部某些activity的敏感功能做权限限制,导致未登陆的用户也可以进行敏感操作。 下面我们看一个实例: 某款APP有手势密码,正常启动必须手势密码验证通过后,才可以进行某些敏感操作, 然而通过直接启动activity,就可以输入员工姓名进行模糊查询,返回结果得到员工姓名部门分机号等等,手势密码形同虚设。
图5: adb shell绕过手势密码启动某敏感activity 如果是一些在线查询的操作,小编建议手势密码验证通过后必须下发一个有效的令牌。
第四种:通用签名风险 常见指数: 恶意假冒APP之所以不能替换我们原有的packageName相同的应用,是因为有安卓应用签名校验机制(在应用安装时会校验包名(package name)和签名,如果系统中已经存在了一个相同的包名和签名的应用,将会用新安装的应用替换旧的;如果包名相同但是签名不同,则会安装失败)。 设想如果多款APP使用同一个数字证书签名,那么会带来的危害则不言而喻。 另外如果目标应用的自定义权限android:protectionlevel为“signature”或者“signatureOrSystem”时,如果使用了同源签名,那么对前者的保护就形同虚设,比如其他app就可以随意的启动APP自身本应受保护的activity。 小编还发现某些研发在使用自己随机生成的android.keystore时,存在命名不规范的问题,或者干脆使用默认的信息。
图6:keystore命名不规范 最后想强调一下的是,如果真的犯了通用签名的错误,带来的麻烦就是修复上的困难,想更换签名签发APP可能涉及到需要卸载旧的app,这将会导致用户的流失。 参考:http://www.freebuf.com/articles/terminal/111363.html
第五种:手势密码可被还原 如今越来越多的APP使用了手势密码来校验用户身份。至于手势密码的保存,大多数是保存在本地配置文件或者db里面。 之前我们看到部分APP手势密码明文存储在本地配置文件里,有些用户的卸载APP后手势密码可以重新设置,来绕过 。 这里我们简单介绍加密的手势密码被还原的案例: 某款APP,使用了手势密码, 通过查看源码得知其手势按键排序如下: 图7:手势密码键盘图 程序员将手势密码保存在本地某文件里面,加密后展示为user_Gesture":"4q2Zys9ead73yxe3CBVoqw==\n" ,现在问题就是如何解密这串字符, 小编通过研究发现代码里程序员居然打印出了手势密码明文和加解密密钥。 图8:ddms日志泄露密钥 其中85210367是手势明文。调查发现部分程序员还会将登陆密码的加密密钥硬编码在java代码中。某些情况下即使做了代码混淆,攻击者也可以做动态调试或者插桩打印还原密钥。小编提醒开发者尽量在SO中妥善保管好密钥,且做好防二次打包,APP加固等必要工作。
第六种:本地校验可绕过 常见指数: 遇见的问题主要有:
APP内置js校验手势密码:如下所示。
图9:js本地校验手势密码 我们极力反对使用js来本地校验手势密码。假设被恶意人员捡到手机,root后修改一下存储在客户端APP里的js本地文件,那此款APP就可以随便登入了。 图形验证码本地验证,游戏会员软件的本地破解:一般很多本地离线的APP,有会员充值等功能,高级功能普通用户无法使用。其实破解的方法无外乎于修改smali文件,改变逻辑或者变量值
第七种:本地数据存储安全 打开DDMS或者adb shell进入,我们可以看到/data/data下面存有各个packageName命名的目录。 其中比较敏感的目录有databases, files, shared_prefs,分别对应安卓的几种数据存储方案: sqlite数据库存储数据,文件存储数据,SharedPreferences存储数据。我们可以使用DDMS的File Explorer来方便排查存储在本地的明文密码。 对于SharedPreferences存储,我们最常使用的Context类中的getSharedPreferences()方法来创建一个SharedPreferences对象,请不要使用MODE_WORLD_READABLE,MODE_WORLD_WRITEABLE(安卓4.2.2已废弃)来定义其操作模式,这样会导致其他应用也可以读取修改APP自己的SharedPreferences存储文件,一般情况下我们使用默认属性就好。
图10:SharedPreferences存储默认属性
小编提醒:实际开发中不同APP遇到的安全场景不尽相同,所以还需要具体加以分析,最好能够从功能设计上入手,遵照SDL安全开发的流程,尽可能将风险降到最低。
|