Apk安全解决方案

背景

公司为政府做的App开发完了,需要上一些手段保证安全。这样客户才放心嘛。

防止第三方反编译篡改应用,防止数据隐私泄露,防止二次打包欺骗用户。

目录

Apk需要加固

腾讯乐固

代码混淆及日志关闭

采用proguard

# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html # If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#} # Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable # If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-optimizationpasses 5 # 指定代码的压缩级别
-dontusemixedcaseclassnames # 是否使用大小写混合
-dontpreverify # 混淆时是否做预校验
-verbose # 混淆时是否记录日志 -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 混淆时所采用的算法 -keep public class * extends android.app.Fragment
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.preference.Preference
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.annotation.**
-keep public class * extends android.support.v7.**
-keepclasseswithmembernames class * { # 保持 native 方法不被混淆
native <methods>;
}
-keepclasseswithmembers class * { # 保持自定义控件类不被混淆
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {# 保持自定义控件类不被混淆
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity { # 保持自定义控件类不被混淆
public void *(android.view.View);
}
-keepclassmembers enum * { # 保持枚举 enum 类不被混淆
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable { # 保持 Parcelable 不被混淆
public static final android.os.Parcelable$Creator *;
}
#过滤注解
-keepattributes *Annotation*
-keep class * extends java.lang.annotation.Annotation { *; }
-keep interface * extends java.lang.annotation.Annotation { *; }
#过滤泛型
-keepattributes Signature ##fastjson
-keep public class * implements java.io.Serializable {
public *;
}
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
-dontwarn android.support.**
-dontwarn com.alibaba.fastjson.** -dontskipnonpubliclibraryclassmembers
-dontskipnonpubliclibraryclasses -keep class com.alibaba.fastjson.** { *; } -keepclassmembers class * {
public <methods>;
} ##Gson
-keepattributes Signature
-keepattributes *Annotation*
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over Gson 下面替换成自己的实体类
-keep class com.kuaijiajin.julynovel.bean.** { *; }
#close log
-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(...);
}
#webview
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
public *;
}
-keepclassmembers class * extends android.webkit.webViewClient {
public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
public boolean *(android.webkit.WebView, java.lang.String);
}
-keepclassmembers class * extends android.webkit.webViewClient {
public void *(android.webkit.webView, jav.lang.String);
}
#Butter Knife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}
#Retrofit
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
#Rxjava RxAndroid
-dontwarn sun.misc.**
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
long producerIndex;
long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
rx.internal.util.atomic.LinkedQueueNode consumerNode;
}
#Glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
# Okhttp3的混淆配置
# JSR 305 annotations are for embedding nullability information.
-dontwarn javax.annotation.**
# A resource is loaded with a relative path so the package of this class must be preserved.
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
-dontwarn org.codehaus.mojo.animal_sniffer.*
# OkHttp platform used only on JVM and when Conscrypt dependency is available.
-dontwarn okhttp3.internal.platform.ConscryptPlatform #自定义混淆(部分使用了反射的地方)
-keep class com.kuaijiajin.julynovel.util.BottomNavigationViewUtils

Janus签名机制漏洞

打包时选择v1和v2签名

应用签名未校验

增加签名证书的校验代码,降低App被二次打包的几率。

    /**
* 检测签名
*/
private boolean checkSignature() {
Context context = WXApplication.getInstance();
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
Signature[] signatures = packageInfo.signatures; if (signatures != null) {
for (Signature signature : packageInfo.signatures) {
                //获取MD5或者SHA1
MessageDigest md = MessageDigest.getInstance("SHA1");
md.update(signature.toByteArray()); String currentSignature = bytesToHexString(md.digest()).toUpperCase(); if ("YOUR SIGENATURE".equals(currentSignature)) {
return true;
}
}
} else {
LogUtil.i("signatures ==null");
} } catch (NameNotFoundException e) {
e.printStackTrace();
LogUtil.e(e);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
LogUtil.e(e);
} return false;
} /**
* byte转16进制String
*
* @param src 数据源
* @return string
*/
public String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder();
if (src == null || src.length <= 0) {
return "";
} for (byte by : src) {
int v = by & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}

Webview明文存储密码风险

解决方案

    WebView.getSettings().setSavePassword(false)

Webview File同源策略绕过漏洞

将不必要导出的组件设置为不导出,并显式设置所注册组件的“android:exported”属性为false

如果需要导出组件,禁止使用File域

WebView.getSettings.setAllowFileAccess(false);

应用数据任意备份风险

AndroidManifest.xml内关闭数据允许备份

application android:allowBackup=false

敏感函数调用风险

审核包含敏感行为的函数调用,确保其使用是必要且限制于授权用户的。

restartPackage - 关闭进程

随机数不安全使用漏洞

禁止在生成随机数之前调用setSeed()方法设置随机种子或调用SecureRandom类的构造函数SecureRandom(byte[] seed),建议通过/dev/urandom或者/dev/random获取的熵值来初始化伪随机数生成器。

URL信息检测

在移动应用的程序代码内部,可能存在大量开发人员或其他工作人员无意识留下的信息内容。URL信息检测就是通过检测移动应用程序代码内部所存在的URL地址信息,尽可能呈现出应用中所有的URL信息,便于应用开发者查看并评估其安全性。移动应用发布包中的URL地址信息,可能会被盗取并恶意利用在正式服务器上进行攻击,攻击安全薄弱的测试服务器以获取服务器安全漏洞或者逻辑漏洞。

解决方案

1、核查并评估所有的URL信息,判断是否存在涉及内部业务等敏感信息的URL地址,进行删除;

2、尽量不要将与客户端业务相关的URL信息以硬编码的方式写在应用客户端中,建议以动态的方式生成所需要请求的URL

残留账户密码信息检测

  1. 核查所有残留的账户和密码信息,删除与业务无关的账户和密码。
  2. 尽量不要将与客户端业务相关的账户密码信息以硬编码的方式写在应用客户端中。

截屏攻击风险

开发者审查应用中显示或者输入关键信息的界面,在此类Activity创建时设置WindowManager.LayoutParams.FLAG_SECURE属性,该属性能防止屏幕被截图和录制

public class DemoActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
setContentView(R.layout.main);
}
}

未移除有风险的Webview系统隐藏接口漏洞

开发者显式移除有风险的Webview系统隐藏接口。

以下为修复代码示例:

在使用Webview加载页面之前,执行

webView.removeJavascriptInterface("searchBoxJavaBridge_");
webView.removeJavascriptInterface("accessibility");
webView.removeJavascriptInterface("accessibilityTraversal");

Root设备运行风险

开发者应在应用启动时增加对应用运行环境的检测,当发现运行设备为Root设备时,应禁止应用启动。

    @Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
if(checkRootPathSU() || checkRootWhichSU()){
ToastUtils.showLong(getResources().getString(R.string.illegal_root));
finish();
return;
}
if(!checkSignature()){
ToastUtils.showLong(getResources().getString(R.string.illegal_apk_signatures));
finish();
return;
}
}
//通过检测指定目录下是否存在su程序来检测运行环境是否为Root设备
//当CheckRootPathSU返回值为true时,禁止应用启动
public static boolean checkRootPathSU()
{
File f=null;
final String kSuSearchPaths[] = {"/system/bin/", "/system/xbin/", "/system/sbin/", "/sbin/","/vendor/bin/"};
try{
for(int i=0;i<kSuSearchPaths.length;i++)
{
f=new File(kSuSearchPaths[i]+"su");
if(f!=null&&f.exists())
{
return true;
}
}
}catch(Exception e)
{
e.printStackTrace();
}
return false;
}
//通过which命令检测系统PATH变量指定的路径下是否存在su程序来检测运行环境是否为Root设备
//当CheckRootWhichSU返回值为true时,禁止应用启动
public static boolean checkRootWhichSU() {
String[] strCmd = new String[] {"/system/xbin/which","su"};
ArrayList<String> execResult = executeCommand(strCmd);
if (execResult != null){
return true;
}else{
return false;
}
}
public static ArrayList<String> executeCommand(String[] shellCmd){
String line = null;
ArrayList<String> fullResponse = new ArrayList<String>();
Process localProcess = null;
try {
localProcess = Runtime.getRuntime().exec(shellCmd);
} catch (Exception e) {
return null;
}
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(localProcess.getOutputStream()));
BufferedReader in = new BufferedReader(new InputStreamReader(localProcess.getInputStream()));
try {
while ((line = in.readLine()) != null) {
fullResponse.add(line);
}
} catch (Exception e) {
e.printStackTrace();
}
return fullResponse;
}

不安全的浏览器调用漏洞

开发者需要在应用调用外部浏览器时对引擎版本进行检测,当发现调用Chrome V8引擎并且版本低于4.2时停止调用外部浏览器并且提示用户对调用的系统浏览器进行升级或者修改系统默认的浏览器。

Android应用安全解决方案的更多相关文章

  1. Atitti.java android反编译解决方案-----虚拟机方案

    Atitti.java android反编译解决方案-----虚拟机方案 哈哈,终极解决方案是虚拟机...c++也可以反编译为汇编代码,但无需担心,因为读懂汇编太麻烦..只要不能拿到c++源码就可.. ...

  2. Android常见开源解决方案

    原文:http://m.pstatp.com/group/6348269082899497218/?iid=6036708044&app=news_article&tt_from=mo ...

  3. 4种必须知道的Android屏幕自适应解决方案

    文章来源:http://blog.csdn.net/shimiso/article/details/19166167 demo下载:http://www.eoeandroid.com/forum.ph ...

  4. Android视频直播解决方案(rstp、udp)

    做局域网视频直播有两种方案,通过rstp或udp协议. 1.rstp协议,网络上有个开源项目,基于Android,且这个项目也是一个服务端,里面也集成了http访问页面,可以通过http或者rstp直 ...

  5. Android WebView常见问题解决方案汇总

    问题目录: 1.为WebView自定义错误显示界面: 2.WebView cookies清理 3.清理cache 和历史记录 4.判断WebView是否已经滚动到页面底端 5.URL拦截 6.处理We ...

  6. 四种必须知道的Android屏幕自适应解决方案

    一.细说layout_weight     目前最为推荐的Android多屏幕自适应解决方案.     该属性的作用是决定控件在其父布局中的显示权重,一般用于线性布局中.其值越小,则对应的layout ...

  7. Android OOM异常解决方案

    一,什么是OOM异常: OOM(out of Memory)即内存溢出异常,也就是说内存占有量超过了VM所分配的最大,导致应用程序异常终止: 二,为什么会产生OOM异常呢? OOM异常是Android ...

  8. Android ANR异常解决方案

    1,ANR异常的解释: ANR(android not response)即应用程序无响应,在用户操作在5秒内没有响应的话就会出现ANR异常: 2,那为什么会出现ANR异常呢? Android系统中处 ...

  9. Unity打安卓包 Android 所有错误解决方案大全(几乎囊括所有打包错误 )

    Unity打包出错解决方案 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享. ...

随机推荐

  1. JQuery input file 上传图片

    表单元素file设置隐藏,通过其他元素打开: .imgfile为input file $(".ul").click(function () {return $(".img ...

  2. RESTful API终极版序列化封装

    urls: from django.conf.urls import url from app01 import views urlpatterns = [ # url(r"comment/ ...

  3. 安装Android studio出现'tools.jar' seems to be not in Android Studio classpath......的解决方法

    安装Android studio出现'tools.jar' seems to be not in Android Studio classpath......的解决方法 原创 2015年07月31日 ...

  4. C# 进程(应用程序)间通信

    SendMessage用法: 函数功能:该函数将指定的消息发送到一个或多个窗口.此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回.该函数是应用程序和应用程序之间进行消息传递的主要手段之一. ...

  5. VS2013默认打开HTML文件没有设计视图

    打开VS菜单->工具->选项->文本编辑器->文件扩展名,右侧输入html,再下拉列表选HTML(Web窗体)编辑器,点添加,确定. 第二条是彻底解决VS2013不能编辑HTM ...

  6. sql中纵表变横表

    纵表格式如图所示: 查询sql语句如下: ),content)content,Date from SummerChina ' 变成横表如图所示: 纵表变横表sql语句如下: select Time, ...

  7. C#抽象类与接口的区别【转】

    一.抽象类:      抽象类是特殊的类,只是不能被实例化(可以用派生类实例化基类对象):除此以外,具有类的其他特性:重要的是抽象类可以包括抽象方法(当然它可以有普通方法),这是普通类所不能的.抽象方 ...

  8. 迷你MVVM框架 avalonjs 沉思录 第3节 动态模板

    模板的发明是编程史上的一大里程碑,让我们摆脱了烦锁且易出错的字符串拼接,维护性大大提高. 都在JSP,ASP时代,人们已经学会使用include等语句,将多个页面片断拼接成一个页面. 此外,为了将数据 ...

  9. mac 下 python链接mysql

    安装过程 :http://blog.topspeedsnail.com/archives/6018 注意 报错的话要先装一个东西 http://cdn.mysql.com/Downloads/Conn ...

  10. [转] 移动平台Html5的viewport使用经验

    转自:http://blog.csdn.net/wuruixn/article/details/8591989 问题描述 web页面采用html5技术实现,在系统登录页面中使用frameset.fra ...