前段时间为了应对银联的安全监测,在处理一些app安全问题,这篇文章就把我自己对Android应用的安全问题的认知给出一些问题和解决办法。
一.为了应对APP日志暴露风险,我们需要通过混淆将应用里打印日志的代码给去掉:
①在build文件中设置混淆文件
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
②混淆文件添加混淆
#删除普通日志
-assumenosideeffects class android.util.Log {
public static boolean isLoggable(java.lang.String, int);
public static int v(...);
public static int i(...);
public static int w(...);
public static int d(...);
public static int e(...);
}
# 删除自定义的日志提示类提示语句
-assumenosideeffects class com.test.utils.LogUtils {
public static *** v(...);
public static *** i(...);
public static *** w(...);
public static *** d(...);
public static *** e(...);
public static *** vTag(...);
public static *** iTag(...);
public static *** wTag(...);
public static *** dTag(...);
public static *** eTag(...);
public static *** json(...);
public static *** file(...);
public static *** xml(...);
}
二.通过root手机等方式SharedPreferences文件暴露:
对SharedPreferences文件进行加密存储,具体方式可以自由发挥:aes,rsa都行
可以参考:https://github.com/iamMehedi/Secured-Preference-Store
三.App和后台接口交互的加密;
针对应用的类型和用户的不同,对接口加密要求也不一样;
介绍下用RSA+AES加密结合的方式针对接口数据进行处理的流程:
1.客户端拿到和后台约定好的RSA公钥
2.用rsa公钥加密客户端本地生成生成的key;,在登录接口传给后台。
3.后台经过rsa私钥解密之后,保存后台;
4.客户端发起其他请求接口时,用key对请求参数进行AES加密和加签处理;
5.后台通过加签对比,然后利用key进行AES解密参数,将包装好的数据进行AES加密加签传给客户端;
6.客户端拿到数据再进行加签对比,解密数据后使用。
四.安全键盘处理
安全键盘的标准不同于普通的自定义键盘:
1.数字,符合 乱序处理;(随机生成数字的位置)
2.不可被截屏,录屏;(getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
3.键盘要逐位加密。
五.组件暴露风险
打开manifest文件将暴露的组件 改为
android:exported="false"
六.手机系统环境校验
// 检查是否root
public static boolean isDeviceRooted() {
boolean ret = false;
String path = null;
Map<String, String> env = System.getenv();
if (env != null && (path = env.get("PATH")) != null) {
String[] dirs = path.split(":");
for (String dir : dirs) {
String suPath = dir + "/" + "su";
File suFile = new File(suPath);
if (suFile != null && suFile.exists()) {
ret = true;
}
}
}
return ret;
}
// 检查是否是在模拟器中运行
public static boolean checkEmulator() {
try {
boolean goldfish = getSystemProp("ro.hardware").contains("goldfish");
boolean emu = getSystemProp("ro.kernel.qemu").length() > 0;
boolean sdk = getSystemProp("ro.product.model").equals("sdk");
if (sdk || goldfish || emu) {
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
private static String getSystemProp(String prop) throws Exception {
Class sysPropClazzClass = Class.forName("android.os.SystemProperties");
return (String) sysPropClazzClass.getMethod("get",
new Class[]{String.class}).invoke(sysPropClazzClass,
new Object[]{prop});
}
七.https证书双向认证
通过okhttp+Retrofit 实现证书认证还是有许多内容的,这里就不详细展开。
八.界面劫持风险
应用跳转到非本App页面,要给用户以提示;
九.webview铭文存储
webSettings.setSavePassword(false);