Android安全性浅谈

765 阅读4分钟

对于一款成熟的App,一定会开始涉及安全和性能的问题,这里就先说一下安全性的问题,今天突然收到我们线上某app的安全性检测报告,一看一千多个安全隐患感觉这app完全无安全性可言,仔细一看其实都是我们开发过程的一个规范问题,虽然这款app不是我开发的,但是有很多安全隐患我也的确是没有考虑过,这里就不得不赶紧拓展补充能量了。

ProGuard

在Android Studio当中混淆APK,借助SDK中自带的Proguard工具,只需要修改build.gradle中的一行配置即可。这个就很简单了,基本都在用混淆。之前有些过基本混淆规

Log

开发过程中相信大家都会打印一下log查看信息的,特别是接口数据类的日志,这些日志同样会泄露app中的信息,因此release版本的日志屏蔽是非常重要的。使用原生的Log大家可以自行封装一个工具类,在打印日志之前判断是否是debug,debug模式下打印日志。现在log框架也有很多,都有这样的配置。debug模式判断:

		if(BuildConfig.DEBUG){
			//is debug
		}else{
			//is release 
		}

组件安全(exported)

Android中的四大组件 Activity,Service,Provider,Receiver 四大组件中都会一个共同的属性:android:exported。而组件安全主要在于android:exported这个属性,android:exported决定组件是否允许被其他APP调用。

  • android:exported 当Android sdk 的最小版本为16或者更低时或组件设置了intent-filter他的默认值是true。如果是17和以上的版本默认值是false。
  • 组件访问权限:如果需要被其他app唤起建议加入自定义的权限,只有有权限才能调用。
  • intent传输:跳转使用显示跳转,隐式跳转可能存在被未知的第三方应用劫持的风险

自定义权限方法如下:

	//定义权限
 <permission android:name="com.yz.permission.INTENT_OTHER"
        android:protectionLevel="normal" />

	//申请权限
    <uses-permission android:name="com.yz.permission.INTENT_OTHER"/>


<activity
    android:name=".TestActivity"
    android:exported="true"
    android:permission="com.yz.permission.INTENT_OTHER" />
	//指定权限

注:四大组件自定义权限方法相同,protectionLevel属性是指权限的类型。官网给出的说明如下:

  • normal:这是最低风险的权限,如果应用声明了此权限,也不会提示安装应用的用户授权(例如,如果声明了定位权限,则应用到定位功能时,会明确提示用户,是否授予定位权限,但是protectionLevel为normal的不会明确提示,直接默认授予),系统直接默认该应用有此权限
  • dangerous:这种级别的权限风险更高,拥有此权限可能会访问用户私人数据或者控制设备,给用户带来负面影响,这种类型的权限或许不会默认授权
  • signature: 这种权限级别,只有当发请求的应用和接收此请求的应用使用同一签名文件,才会授权,并且是默认授权,不会提示用户
  • signatureOrSystem:这种权限应该尽量避免使用,偏向系统级,签名保护级别应该足够对于大多数需求和工作

调试安全

release版本应该禁止调试,application的android:debuggable属性设置为true时,攻击者可以通过动态调试来窥探客户端的数据流和工作流,增加核心程序逻辑被破解的风险。

  • Android提供了isDebuggerConnected()方法,判断是否有调试器连接
  • debuggable属性判断,release版本debuggable设置为false,在程序中判断debuggable值是否被修改 判断debuggable代码如下:
 if (0!=(getApplicationInfo().flags&= ApplicationInfo.FLAG_DEBUGGABLE)) {
        //程序被修改为可调试状态!!!
        android.os.Process.killProcess(android.os.Process.myPid());
  }

签名安全

签名是Andriod软件一种有效的身份标识,签名时推荐V1和v2全部勾选,签名说明参考《AS打包签名》,防止二次打包,判断签名是否一致。 获取apk的签名hash值与apk的签名文件的hash值进行判断,不一致说明apk被二次打包。 获取签名hash值的代码如下:

public int getSignature(String packageName) {        
        PackageManager pm = this.getPackageManager();  
        PackageInfo pi = null;  
        int sig = 0;  
        try {  
            pi = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);  
            Signature[] s = pi.signatures;  
            sig = s[0].hashCode();    
        } catch (Exception e1) {  
            sig = 0;  
            e1.printStackTrace();  
        }  
        return sig;  
}