zoukankan      html  css  js  c++  java
  • Android安全防护防护———Android 端常见的安全问题

    Android安全防护防护——加密算法:传送门https://www.cnblogs.com/huangjialin/p/9694488.html

    组件安全

    activity劫持

    简单来说就是正常的activity被攻击者替换上一个假冒的activity,但是用户并不知道这是一个假冒的activity,所以用户在输入相关信息后,就直接被攻击者获取到了。通常像登录页面,支付页面,或者是其他数据较为敏感的页面都是很容易被攻击。

     activity劫持的原理有两种

    第1种:手机安装了木马程序,木马程序会注册一个Receiver,响应android.intent.action.BOOT_COMPLETED这个事件,这时候木马程序中的服务就会启动一个定时器,不停的循环当前运行的进程。一旦当前的进程正是我们要劫持的,并且运行在前台,就立刻使用FLAG_ACTIVITY_NEW_TASK来启动自己的木马程序中的页面并且处于栈顶,用户看到这个页面并不知道是木马程序的页面,就将一些信息输入,从而导致泄漏。

    第2种:通常启动一个activity是通过startActivity(),这个方法的参数是intent,intent的设置有两种方式,第一种是通过设置action,让系统找到接收该action的activity,然后启动。第二种是通过包名+类名的方式进行启动。

    当应用通过action来启动activity的时候,木马程序可以创建一个同样的action来接收activity。Android系统中,如果存在多个activity接收同一个action时,会提供一个列表让用户选择,一旦用户选错,就进入到木马程序中的页面。从而导致隐私信息泄漏。

    解决方案

    1、针对第一种情况,当我们的应用程序退到后台的时候,弹出提示信息提示用户,程序已经退出到后台。

    2、自己写一个写一个反劫持程序。当一些敏感的页面时候,启动一个后台服务,然后显示一个悬浮框,我们可以获取到当前运行的进程名称,来提示用户。防止被一些木马程序欺骗。

    3、针对第二种情况,启动activity的时候,通过包名+类名的形式进行启动,不要使用action方式。

    下面用代码简单介绍一下劫持的原理

    1、在恶意程序中启动一个服务,在服务中开启一个定时器,然后不断的获取当前的进程名。

     1 /**获取当前的运行在前台的进程,并且在前台运行*/
     2 public static String getTopAppPackageName(Context context) {
     3         try {
     4             String packageName = "";
     5             ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
     6 
     7             if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
     8                 final long end = System.currentTimeMillis();
     9                 final UsageStatsManager usageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
    10                 if (null == usageStatsManager) {
    11                     return packageName;
    12                 }
    13                 final UsageEvents events = usageStatsManager.queryEvents((end - 60 * 1000), end);
    14                 if (null == events) {
    15                     return packageName;
    16                 }
    17                 UsageEvents.Event usageEvent = new UsageEvents.Event();
    18                 UsageEvents.Event lastMoveToFGEvent = null;
    19                 while (events.hasNextEvent()) {
    20                     events.getNextEvent(usageEvent);
    21                     if (usageEvent.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
    22                         lastMoveToFGEvent = usageEvent;
    23                     }
    24                 }
    25                 if (lastMoveToFGEvent != null) {
    26                     packageName = lastMoveToFGEvent.getPackageName();
    27                 }
    28             }
    29             return packageName;
    30         }catch (Exception e){
    31             return null;
    32         }
    33     }

    这里简单的说明一下,Android不同的系统获取进程的方法是不一样,Google为了提高系统的安全性,不断的封堵,不过,上面的获取当前的进程名在我的魅族7.0是可以获取的,亲测。

    2、然后通过获取到当前进程的显示类名,恶意程序通过监听到当前进程运行的类名是自己想要攻击的页面,就迅速的替换上自己假的activity,从而迷惑用户,窃取到用户的隐私信息。不过目前6.0以上的系统,Google不提供获取其他应用的当前类名。但是在以前的版本是可以获取的。很遗憾,由于我的系统是7.0,所以,我并没有成功的获取到其他进程的topActivity。

    Service劫持,Service拒绝服务

    Service劫持

    Service是Android四大组件之一,没有界面,运行在后台。通常我们用来做一些耗时的任务,但是需要注意的是Service是运行在主线程中的。而通常ComponentName startService(Intent service)我们是通过这样的方式进行启动一个service。其中参数是intent。而intent的使用有两种情况

    第一种:明确的说明好要启动那个服务,也就是说指定好包名和Service的名称。

    第二种:通过设置action,接收到action的service就启动。

    那么问题就来了,如果你设置的action,攻击者弄的service会不会也可以也接收到你的action。在Android系统中多个service接收到同一个action,则看priority值,就是谁的优先级高,谁高就先启动谁。如果priority值一样,则是谁先安装,就先启动谁。所以说如果说攻击者自己弄一个服务,然后接收action,那么很有可能这个启动的service就是伪装的。

    解决方案:startService(),bindService()时直接指定类名,包名。不要使用action启动。

    Service拒绝服务

    如果攻击者以这种方式进行攻击的。那要么是攻击者为了显示自己的技术,要么是那家公司的老板抢了他的老婆。当然也有可能是双方是竞争关系。这种攻击的方式就是让你的程序崩溃,崩溃,崩溃。

    漏洞造成的原因

    Android系统中,主要是通过intent来携带数据进行跳转的。但是系统在内部对intent中数据的并没有进行一些处理,比如数据为空,数据有问题等等,一旦攻击者对intent中的数据进行改动,就导致程序崩溃。

    解决办法

    1、既然是intent数据有问题。那我们获取的时候,就钥先做一些判断处理,还有就是try…catch处理。

    2、在AndroidMenifest.xml中加上android:exported这个属性,设置为false 。即将组件设置为不可导出。

    3、将service设置为私有的

    Content Provider

    四大组件之一的ContentProvider,在应用中扮演是应用间数据共享桥梁的角色。如果ContentPrevider组件对外暴露,攻击者很容易通过该暴露的组件的openFile接口,对文件目录进行遍历,从而导致数据泄漏。那么该如何判断ContentPrevider是否暴露这个接口呢?通过对所有的openFile方法,如果未对传入的uri技能型安全判断,则就认为有漏洞风险

    解决方法

    1、将不必要暴露的ContentPrivider组件设置为私有的。

    2、去除没必要的openFile接口

    3、对目标的uri进行有效的判断。

    WebView安全

    webView是Android原生提供的一个实现H5页面的控件。除了具有一般view的属性和设置外,还可以URL请求,页面加载,渲染,页面交互等进行处理。

    漏洞产生原因

    1、js调用Android原生代码,可以通过WebView的addJavaScriptInterface()方法进行对象的映射。当拿到该对象的时候,就可以对该对象中的方法进行调用。攻击可以通过拿到该对象,然后调用对象中的任意方法。

    2、在Android应用中,webview开启了file域的访问,且允许file域对http域进行访问,同时未对file域的路径做限制。攻击者通过URLScheme的方式,可远程打开并加载恶意的html文件,获取到app中的一些信息。这个漏洞触发的条件是1、webview中setAllowFileAccessFromFileURLs或者是setAllowUniversalAccessFromFileURLsAPI配置为true。2、webview可以直接被外部调用,并能够加载外部可控的HTML文件。

    解决方案

    1、针对第一个漏洞,Google也给出解决方案,在Android4.2之前规定,被调用的方法必须要加上@javascriptInterface这个注解。才能够调用。在4.2之前采用拦截prompt()方法来进行漏洞的修复。

    2、针对第二个漏洞,前面说了漏洞触发条件有两个,所以主要办法就是对这两个条件进行修复。1、setAllowFileAccessFromFileURLs或setAllowUniversalAccessFromFileURLs两个API为false。(Android4.1版本之前这两个API默认是true,需要显式设置为false)2、如果需要开启file域的访问,则要对file域的访问范围要严格控制。

    SharePreferences存储风险和SDCard存储风险

    1、SharePreferences存储是一种轻量级的基于XML文件存储的键值对形式进行数据的存储的。存储的数据一般是比较小的。

    存在风险:现在很多人将登录相关的信息明文存储到sp中,过度的依赖Android系统本身提供的安全存储机制。导致攻击者可以通过root手机来查看敏感的信息。

    解决方案:一些敏感的信息不要明文进行存储,先使用加密算法进行加密,在存储。

    2、SDCard

    Android系统中存放的文件存储卡分为内置存储卡和外部存储卡

    内置存储卡,是有权限控制的,现在Android系统如果要读区内置存储卡,必须要用户手动给予权限,否则的话不能够读取。相对来说比较安全。

    外部存储卡,有点类似于U盘,这个是没有权限控制,所以说如果只要有SDCard的读写操作权限,就可以进行读写操作,电脑也可以读取。

    存在风险:如果数据存在外部存储卡中,攻击者很容易就读取到里面的数据,造成数据泄漏。

    解决方案:敏感的数据不要存储到SDCard中,防止数据被修改或者是数据泄漏。推荐存储在/data/data/packagename/目录下应用数据任意备份风险

    当AndroidManifest.xml配置文件中没有设置allowBackup这个属性,或者是设置这个属性为true的时候(默认是true),应用程序的数据可以被任意的备份和恢复。攻击者就可以通过adb工具备份复制应用程序的数据。

    解决方案:在AndroidManifest.xml文件中设置application的属性 android:allowBackup=”false”

    密码软键盘安全问题

    现在很多应用的键盘,特别是输入支付密码的键盘,都是自己写的一个键盘。虽然从性能上或者是用户体验上来说,系统键盘或者第三方的键盘都要由于我们自己写的。但是如果用系统键盘或者是第三方键盘,我们输入的数据很容易就被泄漏,比如输入数据监听攻击,键盘截屏攻击,输入数据篡改攻击等。

    解决方案

    1、自定义输入键盘。自定义键盘,网上有很多案例,这里就不具体了。

    2、防截屏。在activity中的onCreate()方法中,在setContentView之前加上getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);就可以防止屏幕截屏了。设置这个flag后,系统会把当前窗口的内容视为安全隐私内容,系统会阻止这些内容被截屏或者在不安全可靠的场景显示出来。

    其他

    前面说了存在的安全问题及解决方案,在这里还提一下提高安全性的两个方案。

    1、混淆。系统提供有proguard文件来将我们要定义的混淆规则定义在里面。被混淆过的项目通过反编译工具,如ApkTool ,dex2jar , jd-gui等编译出来后,一些代码是显示为a,b,c这样的形式,无法知道具体的类名或者其他。虽然混淆不能保证安全多少。但是,至少能够增强反编译的难度。再说了没有什么事百分之百的,我们所做的安全防护,都只是让攻击者不能这么轻易的就破解而已。

    2、第三方加固工具

    现在市场上用的比较多的第三方工具有阿里聚安全,腾讯云应用加固,360加固保,梆梆加固,爱加密第三方加固工具相当于在在我们自己的应用上加了一层壳,让攻击者没有这么简单的拿到我们的数据。

     第三方加固的原理

     

    我们拿到需要加密的Apk和自己的壳程序Apk,然后用加密算法对源Apk进行加密在将壳Apk进行合并得到新的Dex文件,最后替换壳程序中的dex文件即可,得到新的Apk,那么这个新的Apk我们也叫作脱壳程序Apk.他已经不是一个完整意义上的Apk程序了,他的主要工作是:负责解密源Apk.然后加载Apk,让其正常运行起来。

    主要步骤:我们拿到需要加密的apk和自己的壳apk,然后用加密算法对源apk进行加密在壳apk进行合并得到新的dex文件,最后替换壳程序中的dex文件就可以了。得到新的apk,这个新的apk主要工作是:负责解密源apk,然后加载apk,让其正常的运行起来。

    加固工具的对比

    体积(体积小的为优):360 > 腾讯 > 爱加密 > 阿里 > 梆梆

    兼容性: 阿里 > 腾讯 > 360 = 梆梆 > 爱加密

    启动速度(时间短为优): 阿里 > 爱加密 > 360 = 梆梆 > 腾讯

    漏洞: 腾讯 > 爱加密 > 360 > 梆梆 > 阿里

  • 相关阅读:
    Activity之间的数据传递
    解析JSON
    使用HTTP协议访问网路
    WebView的初体验
    Alarm机制用于定时服务
    IntentService和Service执行子线程对比
    前台服务
    Android四大组件之服务
    异步消息处理机制,UI更新
    Git学习
  • 原文地址:https://www.cnblogs.com/huangjialin/p/9694515.html
Copyright © 2011-2022 走看看