Android应用安全解决方案
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
残留账户密码信息检测
- 核查所有残留的账户和密码信息,删除与业务无关的账户和密码。
- 尽量不要将与客户端业务相关的账户密码信息以硬编码的方式写在应用客户端中。
截屏攻击风险
开发者审查应用中显示或者输入关键信息的界面,在此类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应用安全解决方案的更多相关文章
- Atitti.java android反编译解决方案-----虚拟机方案
Atitti.java android反编译解决方案-----虚拟机方案 哈哈,终极解决方案是虚拟机...c++也可以反编译为汇编代码,但无需担心,因为读懂汇编太麻烦..只要不能拿到c++源码就可.. ...
- Android常见开源解决方案
原文:http://m.pstatp.com/group/6348269082899497218/?iid=6036708044&app=news_article&tt_from=mo ...
- 4种必须知道的Android屏幕自适应解决方案
文章来源:http://blog.csdn.net/shimiso/article/details/19166167 demo下载:http://www.eoeandroid.com/forum.ph ...
- Android视频直播解决方案(rstp、udp)
做局域网视频直播有两种方案,通过rstp或udp协议. 1.rstp协议,网络上有个开源项目,基于Android,且这个项目也是一个服务端,里面也集成了http访问页面,可以通过http或者rstp直 ...
- Android WebView常见问题解决方案汇总
问题目录: 1.为WebView自定义错误显示界面: 2.WebView cookies清理 3.清理cache 和历史记录 4.判断WebView是否已经滚动到页面底端 5.URL拦截 6.处理We ...
- 四种必须知道的Android屏幕自适应解决方案
一.细说layout_weight 目前最为推荐的Android多屏幕自适应解决方案. 该属性的作用是决定控件在其父布局中的显示权重,一般用于线性布局中.其值越小,则对应的layout ...
- Android OOM异常解决方案
一,什么是OOM异常: OOM(out of Memory)即内存溢出异常,也就是说内存占有量超过了VM所分配的最大,导致应用程序异常终止: 二,为什么会产生OOM异常呢? OOM异常是Android ...
- Android ANR异常解决方案
1,ANR异常的解释: ANR(android not response)即应用程序无响应,在用户操作在5秒内没有响应的话就会出现ANR异常: 2,那为什么会出现ANR异常呢? Android系统中处 ...
- Unity打安卓包 Android 所有错误解决方案大全(几乎囊括所有打包错误 )
Unity打包出错解决方案 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享. ...
随机推荐
- linux记录每个用户执行的命令
1.在/etc/profile中添加如下代码: #history USER_IP=`>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'` HISTD ...
- 7_python之路之python计算器
7_python之路之python计算器 1.程序说明:Readme.cmd 1.程序文件及说明: calculator.py 2.python版本:python-3.5.3 3.程序使用:pytho ...
- python值解析excel
原文:http://blog.csdn.net/tomatoandbeef/article/details/52253578 一.安装python和xlrd模块 python下载地址,安装好后要配置环 ...
- leetcode131
深度优先遍历(DFS),先判断前一个部分是否是回文,如果是,则将其加进集合中,然后继续判断后面的回文串. 在回溯的时候,将之前加入集合的串删除,重新选择回文串.每到达一次叶子节点,得到一组结果. pu ...
- linux学习(别人指出来的), 回头有针对性的学下!
应该是 会linux 基本操作吧linux 安装 lamp lnmp php拓展这些基本都得会把知道subversion 和 github 这俩吧windows的代码同步到linux上无需ftp 会跟 ...
- 跟我学算法-tensorflow 实现卷积神经网络
我们采用的卷积神经网络是两层卷积层,两层池化层和两层全连接层 我们使用的数据是mnist数据,数据训练集的数据是50000*28*28*1 因为是黑白照片,所以通道数是1 第一次卷积采用64个filt ...
- maven标签说明
<project xmlns="http://maven.apache.org/POM/4.0.0 " xmlns:xsi="http://www.w3.org/2 ...
- How to Restart Qt Application
How to restart QtApplication As we know, Restarting Application means to exit current application, t ...
- ubuntu 基础环境
一.序言 这里记录了安装ubuntu 系统,以及里面常用的东西,jdk,idea,maven,svn,git 等等工具的安装,因为这些动作不是经常操作的,因此这里做一个记录,方便新手或者忘记的时候看看 ...
- Step By Step Hibernate Tutorial Using eclipse WTP[z]
[shivasoft.in/blog/sql/myqsl/step-by-step-hibernate-tutorial-using-eclipse-wtp/] Hibernate is the O ...