一、前言
在Android开发过程中,一般都不会太注重app的安全漏洞问题,除非遇到要求比较高的公司或者有对app提供检测的机构进行检测,但是检测和加固的费用比较高,所以一些app就忽略了这个问题,但是我最近做的app安全级别较高,多个安全机构检测后会有如下问题,顺便说一下检测机构有很多,如360、蓝盾、梆梆等。
二、问题总结
应用签名未校验风险 | 高 | 加入签名校验 |
应用数据任意备份风险 | 中 | 在Androidmaifest.xml中加入android:allowBackup="false" |
剪切板敏感信息泄露漏洞 | 中 | 已去掉 |
HTTPS未校验服务器证书漏洞 | 中 | 程序中已配置了服务器证书漏洞 |
HTTPS未校验主机名漏洞 | 中 | 程序中已配置HTTPS未校验主机名漏洞 |
Webview绕过证书校验漏洞 | 中 | 无法绕过 |
截屏攻击风险 | 中 | 已经在登陆页和首页等主要页面禁止了截屏功能 |
键盘输入监听风险 | 高危 | 第三方加固 |
Java代码反编译风险 | 【高危】 | 第三方加固 |
Activity界面劫持 | 【中危】 | 重写了omKeyDown方法和onPause方法 |
三、问题解决方式
1、应用签名未校验风险
解决方式:加入签名校验
在初始换的activity中加入如下代码
//验证签名是否正确
SignTool.CheckSign(InitActivity.this);
SignTool类实现代码:
import java.security.MessageDigest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
/** Tool.java: ----- 2018-12-28 下午4:04:54 scimence
* 1、获取签名信息 getSignature()
* 2、检测签名信息 CheckSign() */
public class SignTool {
/** 检测当前应用的签名信息,若不相同则自动退出 */
public static void CheckSign(Activity activity)
{
String sign = getSignature(activity);
if (!sign.equals("4e98e3f2faa93b0222ecddce420ff94b")) // 修改此处值为游戏包对应签名
{
activity.finish();
System.exit(0); // 退出运行
}
}
/** 获取应用的签名信息 */
public static String getSignature(Context context)
{
String packageName = getPackageName(context);
String sign = getSign(context, packageName);
return sign;
}
/** 获取acitivty所在的应用包名 */
public static String getPackageName(Context activity)
{
ApplicationInfo appInfo = activity.getApplicationInfo();
String packageName = appInfo.packageName; // 获取当前游戏安装包名
return packageName;
}
/** 获取包名对应应用的签名信息 */
public static String getSign(Context paramContext, String packageName)
{
String S = "";
try
{
byte[] array = null;
PackageInfo localPackageInfo = paramContext.getPackageManager().getPackageInfo(packageName, 64);
for (int i = 0; i < localPackageInfo.signatures.length; i++)
{
array = localPackageInfo.signatures[i].toByteArray();
if (array != null) break;
}
S = MD5(array);
}
catch (Exception ex)
{
}
return S;
}
/** 计算MD5值 */
public static String MD5(String data)
{
try
{
String str = MD5(data.getBytes());
return str;
}
catch (Exception ex)
{}
return null;
}
/** 计算MD5值 */
public static String MD5(byte[] data)
{
try
{
// 获取data的MD5摘要
MessageDigest mdInst = MessageDigest.getInstance("MD5");
// mdInst.update(content.getBytes());
mdInst.update(data);
byte[] md = mdInst.digest();
// 转换为十六进制的字符串形式
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < md.length; i++)
{
String shaHex = Integer.toHexString(md[i] & 0xFF);
if (shaHex.length() < 2)
{
hexString.append(0);
}
hexString.append(shaHex);
}
return hexString.toString();
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
}
2、截屏攻击风险
在引用的activity中或者不让截屏的activity中加入如下代码:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,WindowManager.LayoutParams.FLAG_SECURE);
3、Activity界面劫持
重写onkeydown和onpase方法,当屏幕被遮挡时,弹出提示信息
public boolean onKeyDown(int keyCode, KeyEvent event) {
if((keyCode==KeyEvent.KEYCODE_BACK || keyCode==KeyEvent.KEYCODE_HOME) && event.getRepeatCount()==0){
//加的人保健康
Log.i("feng",this.myWebView.getUrl());
needAlarm = false;
return true;
} else {
return super.onKeyDown(keyCode, event);
}
}
@Override
public void onPause() {
//若程序进入后台不是用户自身造成的,则需要弹出警示
if(needAlarm) {
//弹出警示信息
Toast.makeText(getApplicationContext(), "您的界面已运行在后台,请确认环境是否安全", Toast.LENGTH_SHORT).show();
//启动我们的AlarmService,用于给出覆盖了正常Activity的类名
// Intent intent = new Intent(this, AlarmService.class);
// startService(intent);
}
super.onPause();
}
四、总结
其实这个仅仅是基本的安全策略,最终还是需要第三方软件进行加固才可以确保app不被反编译。