• 安全检测风险


    Root 设备运行风险

    su 是 Linux 下切换用户的命令,在使用时不带参数,就是切换到超级用户。通常我们获取 root 权限,就是使用 su 命令来实现的,所以可以检查这个命令是否存在

    1)检测在常用目录下是否存在 su

    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()) {
                        //Log.i(LOG_TAG, "find su in : " + kSuSearchPaths[i]);
                        return true;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    CheckRootPathSU 返回值为 true 时,禁止应用启动应用

    这个方法是检测常用目录,那么就有可能漏过不常用的目录。所以就有了第二个方法,直接使用shell下的命令来查找

    2)使用 which 命令查看是否存在 su

    which 是 linux 下的一个命令,可以在系统 PATH 变量指定的路径中搜索某个系统命令的位置并且返回第一个搜索结果,这里,我们就用它来查找 su

     //使用which命令查看是否存在su
        public static boolean checkRootWhichSU() {
            String[] strCmd = new String[] {"/system/xbin/which","su"};
            ArrayList<String> execResult = executeCommand(strCmd);
            if (execResult != null){
                //Log.i(LOG_TAG,"execResult="+execResult.toString());
                return true;
            }else{
                //Log.i(LOG_TAG,"execResult=null");
                return false;
            }
        }
    
        public static ArrayList<String> executeCommand(String[] shellCmd){
            String line = null;
            ArrayList<String> fullResponse = new ArrayList<String>();
            Process localProcess = null;
            try {
                //Log.i(LOG_TAG,"to shell exec which for find su :");
                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) {
                    //Log.i(LOG_TAG,"–> Line received: " + line);
                    fullResponse.add(line);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            //Log.i(LOG_TAG,"–> Full response was: " + fullResponse);
            return fullResponse;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    CheckRootWhichSU 返回值为 true 时,禁止应用启动

    所以综合 1 和 2,我们可以这样判断

    	//判断设备是否root
        public static boolean isDeviceRooted() {
            //find su in some path
            if (checkRootPathSU()) {
                return true;
            }
            //find su use 'which'
            if (checkRootWhichSU()) {
                return true;
            }
            return false;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在 SplashActivity.java 的 onCreate 时,判断,如果是 root 设备弹出提示即可

    		//Root设备不能运行
        if(Utils.isDeviceRooted()){
        	showNormalDialog();
            return;
        }
            
    	private void showNormalDialog() {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("运行提示");
            builder.setMessage("检测到当前运行环境存在安全风险,无法使用。");
    
            builder.setPositiveButton("确定", (dialogInterface, i) -> finish());
            builder.setCancelable(false);
            AlertDialog alertDialog = builder.create();
            alertDialog.show();
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    效果如下:
    在这里插入图片描述

    参考:Android root检测方法小结

    Janus 签名机制漏洞

    测评目的:检测 App 程序是否存在 Janus 签名机制漏洞
    危险:Google 披露了一个名为“Janus”的安卓漏洞(漏洞编号:CVE-2017-13156),该漏洞可以让攻击者绕过安卓系统的 Signature scheme V1 签名机制,用篡改过的 APK 覆盖原有的应用,并可访问原应用所有的数据,直接对 App 进行篡改。由于安卓系统的其他安全机制也是建立在签名和校验基础上的,所以可以说该漏洞相当于绕过了安卓系统的整个安全机制。
    该漏洞的影响范围:安卓 5.0-8.0 的各个版本系统;使用安卓 Signaturescheme V1 签名的 App APK 文件。
    该漏洞的危害:对存储在原手机上的数据进行读取;对用户的输入做各种监听、拦截、欺诈,引导用户输入密码,转账;更新 Android 的系统 APP,从获得更高的系统权限,甚至 root/越狱,为其他攻击做准备

    解决办法:对应用同时使用 Signature scheme V1 和 Signature scheme V2 签名机制

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    检测项九:实名认证页面
    软件涉及收集个人敏感信息,未取得个人的单独同意。

    3.5.7.4 Broadcast Receiver 组件导出风险
    如果设置了导出权限,都可能被系统或者第三方的应用程序直接调出并使用。组件导出可能导致本地拒绝服务、越权、恶意调用等风险。

    a. 主动设置android:exported为true
    b. 组件存在IntentFilter,存在IntentFilter时android:exported属性默认值为true
    c. 当组件是ContentProvider并且minSdkVersion或者targetSdkVersion小于等于16时,android:exported默认为true ,当大于等于17时,android:exported默认为false

    在app上的具体表现是:比如游戏登陆时调用微信的Activity登陆组件,微信的Activity登陆组件就是可被导出的。简单来讲就是导出的组件可以被第三方app调用(唤醒)

    https://blog.csdn.net/qq_35993502/article/details/118102715

    3.5.7.2 Activity 组件导出

    3.5.4.3界面劫持风险
    第三方支持:使用第三方的专业防界面劫持 SDK,防止应用界面被劫持

    3.5.3.26动态调试攻击风险
    第三方支持:使用具有反动态调试功能的第三方专业加固方案,防止应用被动态调试。

    3.5.3.22代码残留 URL 信息检测
    开发者自查: 1、核查并评估所有的 URL 信息,判断是否存在涉及内部业务等敏感信息的
    URL 地址,进行删除; 2、尽量不要将与客户端业务相关的 URL 信息以硬编码的方式写在
    应用客户端中,建议以动态的方式生成所需要请求的 UR

    该 App 存在剪切板敏感信息泄露的
    尽量不使用剪切板。若必须要使用剪切板,确保敏感信息不会被存入。

    该 App 中的应用数据存在被外部调用备份的风险。
    AllowBackup是在Android 2.2中引入的一个系统备份的功能。允许用户备份系统应用和第三方应用的apk安装包和应用数据,以便在刷机或者数据丢失后恢复应用,用户即可通过adb backup和adb restore来进行对应用数据的备份和恢复。第三方应用开发者需要在应用的 AndroidManifest.xml 文件中配置 allowBackup 标志(默认为 true )来设置应用数据是否能能够被备份或恢复。

    https://blog.csdn.net/mysimplelove/article/details/84073013

    3.5.2.13 Root 设备运行风险
    该 App 可以在被 Root 的手机中运行

    3.5.2.8未使用编译器堆栈保护技术风险
    https://www.cnblogs.com/zhouyong0330/p/14277980.html

    3.5.1.5资源文件泄露风险
    第三方支持:使用具有资源文件保护功能的第三方专业加固方案,防止资源文件泄露。

    3.5.1.4 Janus 签名机制漏洞

    开发者自查: 1.及时校验 App APK 文件的开始字节,以确保 App 未被篡改; 2.对应用
    同时使用 Signature scheme V1 和 Signature

    3.5.1.3 So 文件破解风险
    第三方支持:使用具有 so 文件保护功能的第三方专业加固方案,防止 so 文件被破解。

    可保护应用远离恶意破解、反编译、二次打包,内存抓取等威胁
    1月3000,12个月5折 1w8

    3.4.5.1 Activity 组件导出风险

  • 相关阅读:
    Kubernetes日志收集常用套路盘点
    SpringBoot通过配置读取json文件
    传奇服务端:GOM GeeM2引擎更新时必须要修改哪些地方?
    qt 消息(事件)机制
    如何查找linux指令或者资料的说明
    使用docker-compose部署,宿主机可链接使用的redis cluster
    POSTGRESQL中的groupping函数详解
    移动端的布局
    JVM的生命周期
    icepak求解报错“internal error in fan domain error argument not in valid range”
  • 原文地址:https://blog.csdn.net/u010356768/article/details/125993864