【APK安全】Android 权限校验核心风险与防御指南

文章目录

    • 前言
    • [一、Android 权限校验的核心风险场景](#一、Android 权限校验的核心风险场景)
      • [1. 风险 1:AndroidManifest 滥用 uid=1000(系统 UID 提权与兼容性崩溃)](#1. 风险 1:AndroidManifest 滥用 uid=1000(系统 UID 提权与兼容性崩溃))
        • [风险本质(uid=1000 的特殊性)](#风险本质(uid=1000 的特殊性))
        • [典型案例 1:普通 APP 误配置系统 UID 导致安装失败](#典型案例 1:普通 APP 误配置系统 UID 导致安装失败)
        • [典型案例 2:恶意 APP 伪造系统 UID 试图提权](#典型案例 2:恶意 APP 伪造系统 UID 试图提权)
      • [2. 风险 2:权限校验依赖不安全方法](#2. 风险 2:权限校验依赖不安全方法)
      • [3. 风险 3:checkCallingUriPermission 使用不当(URI 权限校验失效)](#3. 风险 3:checkCallingUriPermission 使用不当(URI 权限校验失效))
        • [风险本质(URI 权限校验的核心逻辑)](#风险本质(URI 权限校验的核心逻辑))
        • [典型案例:未指定 Uri 类型导致私有数据被非法访问](#典型案例:未指定 Uri 类型导致私有数据被非法访问)
    • 二、权限校验安全防御方案
      • [1. uid=1000 的安全管控:禁止普通 APP 配置 + 系统 APP 权限收敛](#1. uid=1000 的安全管控:禁止普通 APP 配置 + 系统 APP 权限收敛)
        • 核心措施
        • [安全实现代码(检测系统 UID 与权限校验)](#安全实现代码(检测系统 UID 与权限校验))
      • [2. 规范使用 checkCallingPermission:跨进程权限校验的唯一可靠方案](#2. 规范使用 checkCallingPermission:跨进程权限校验的唯一可靠方案)
      • [3. checkCallingUriPermission 正确用法:明确 Uri 与权限类型](#3. checkCallingUriPermission 正确用法:明确 Uri 与权限类型)
        • 核心措施
        • [代码示例(ContentProvider URI 权限校验)](#代码示例(ContentProvider URI 权限校验))
      • [4. 禁用不安全的校验方法:替代方案与风险规避](#4. 禁用不安全的校验方法:替代方案与风险规避)
    • 三、权限校验安全测试方法
      • [1. 静态测试(配置与代码审核)](#1. 静态测试(配置与代码审核))
      • [2. 动态测试(权限绕过模拟)](#2. 动态测试(权限绕过模拟))
    • 四、总结:权限校验的核心原则

⚠️本博文所涉安全渗透测试技术、方法及案例,仅用于网络安全技术研究与合规性交流,旨在提升读者的安全防护意识与技术能力。任何个人或组织在使用相关内容前,必须获得目标网络 / 系统所有者的明确且书面授权,严禁用于未经授权的网络探测、漏洞利用、数据获取等非法行为。

前言

Android 权限机制是保障 APP 与系统安全的 "第一道闸门"------ 通过 AndroidManifest 声明权限、运行时校验权限,限制 APP 仅能访问其 "必要功能" 对应的资源(如相机、位置、跨进程数据)。但权限校验的安全性依赖两大关键:配置的合法性 (uid=1000 的系统 UID 不可滥用)与校验方法的正确性(如必须使用 checkCallingPermission 而非包名判断)。

实际开发中,开发者常因对 "uid=1000 的特殊性" 认知不足、误用不安全的校验方法(如仅通过包名判断可信来源),导致权限绕过漏洞 ------ 攻击者可伪造系统 UID、伪装可信 APP 包名,非法获取高权限(如读取系统数据)或访问私有资源(如用户隐私文件)。

本文将拆解三大核心权限风险,提供规范的校验方案与测试方法。

一、Android 权限校验的核心风险场景

Android 权限校验的风险本质是 "权限边界失控"------ 要么配置突破系统限制(如普通 APP 试图使用系统 UID),要么校验方法无法抵御伪造(如仅判断包名),最终导致权限机制失效。以下结合实际案例解析:

1. 风险 1:AndroidManifest 滥用 uid=1000(系统 UID 提权与兼容性崩溃)

风险本质(uid=1000 的特殊性)

Android 系统中,每个 APP 安装后会被分配唯一的 "用户 ID(UID)",用于隔离不同 APP 的资源访问权限:

  • 普通 APP 的 UID:默认从 10000 开始(如 com.example.app 的 UID 可能为 10045),仅拥有自身私有目录与声明的普通权限;

  • 系统 UID(uid=1000):仅系统进程(如 SystemUI、Settings)、带系统签名的 APP 可使用,拥有 "访问系统核心资源" 的高权限(如修改系统设置、读取所有 APP 数据);

  • 配置方式:需在 AndroidManifest 中声明<manifest android:sharedUserId="android.uid.system">,且必须使用系统签名编译,否则无法安装。

风险点在于:

  • 普通 APP 误配置:未了解 uid=1000 的系统属性,盲目添加sharedUserId="android.uid.system",导致 APP 因无系统签名而安装失败;

  • 恶意 APP 试图提权:通过伪造系统签名、修改 AndroidManifest,试图获取 uid=1000 权限,若系统存在签名漏洞,可能成功提权并窃取系统数据。

典型案例 1:普通 APP 误配置系统 UID 导致安装失败

某工具类 APP 开发者为 "获取系统级文件访问权限",在 AndroidManifest 中误配置系统 UID:

xml 复制代码
<!-- 风险配置:普通APP声明系统UID,无系统签名 -->
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.toolapp"
    android:sharedUserId="android.uid.system"> <!-- 错误配置:普通APP使用系统UID -->

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <!-- 其他配置... -->
</manifest>

后果:

  1. APP 编译后无系统签名(普通开发者无法获取厂商系统签名);

  2. 安装时系统校验发现 "声明系统 UID 但无系统签名",直接拒绝安装,提示 "安装失败:应用未获得系统授权";

  3. 即使通过 root 设备强制推送 APK,启动时系统也会因 UID 权限不匹配,触发SecurityException导致 APP 崩溃。

典型案例 2:恶意 APP 伪造系统 UID 试图提权

某恶意 APP 利用 Android 7.0 以下的签名校验漏洞,伪造系统签名并配置 uid=1000:

xml 复制代码
<!-- 恶意配置:伪造系统UID与签名 -->
<manifest
    package="com.example.malicious"
    android:sharedUserId="android.uid.system">

    <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <!-- 系统级权限 -->
</manifest>

攻击流程:

  1. 利用系统签名漏洞(如旧版本signapk.jar工具缺陷),生成伪造的系统签名文件;

  2. 用伪造签名编译恶意 APP,安装到 Android 7.0 以下设备;

  3. 因系统漏洞,APP 成功获取 uid=1000,拥有系统级权限;

  4. 调用Settings.System.putInt()修改系统设置(如禁用 WiFi、篡改屏幕亮度),或读取/data/system/users/0/settings_ssaid.xml获取所有 APP 的 SSAID(设备唯一标识)。

2. 风险 2:权限校验依赖不安全方法

风险本质(不安全校验方法的共性问题)

Android 跨进程调用(如 Service、ContentProvider)时,需校验调用者是否拥有合法权限。系统推荐的唯一可靠方法是checkCallingPermission(String permission),但部分开发者会使用 "看似可行" 的替代方法,这些方法存在 "可伪造性" 缺陷:

  • 不安全方法 1:getCallingPackage()判断包名 ------ 调用者可通过动态代理、Hook 等手段伪造包名(如将恶意 APP 包名伪装成 "com.example.trusted");

  • 不安全方法 2:getCallingUid()判断 UID 范围 ------ 普通 APP 的 UID 可通过修改系统配置(root 设备)篡改,且无法区分 "合法 APP" 与 "恶意 APP" 的同范围 UID;

  • 不安全方法 3:忽略校验直接执行 ------ 跨进程接口未做任何权限校验,任何 APP 均可调用。

这些方法的核心问题是 "未依赖系统权限机制的底层校验",仅通过上层可篡改的标识(包名、UID)判断,易被攻击者绕过。

典型案例:依赖 getCallingPackage () 判断可信 APP 导致权限绕过

某金融 APP 的跨进程服务(PaymentService),通过判断调用者包名是否为 "com.example.official" 来允许支付操作,未使用 checkCallingPermission

java 复制代码
// 风险代码:依赖包名判断可信来源,无权限校验
public class PaymentService extends Service {
    private static final String TRUSTED_PACKAGE = "com.example.official";

    @Override
    public IBinder onBind(Intent intent) {
        return new PaymentBinder();
    }

    public class PaymentBinder extends IPaymentService.Stub {
        @Override
        public void submitPayment(String orderId, String password) throws RemoteException {
            // 不安全校验:仅判断调用者包名
            String callingPackage = getCallingPackage();
            if (TRUSTED_PACKAGE.equals(callingPackage)) {
                // 无权限校验,直接执行支付操作
                executePayment(orderId, password);
            } else {
                throw new SecurityException("非法调用者:" + callingPackage);
            }
        }
    }
}

攻击者通过伪造包名绕过校验:

  1. 开发恶意 APP,使用动态代理 Hook getCallingPackage()方法,使其返回 "com.example.official";
  2. 绑定金融 APP 的 PaymentService,调用submitPayment("hacker_order", "fake_pwd");
  3. 服务的getCallingPackage()被 Hook 返回可信包名,跳过校验;
  4. 服务执行支付操作,将伪造的 "hacker_order" 标记为 "已支付",导致金融 APP 财务对账异常。

3. 风险 3:checkCallingUriPermission 使用不当(URI 权限校验失效)

风险本质(URI 权限校验的核心逻辑)

checkCallingUriPermission(Uri uri, int modeFlags)用于校验 "调用者是否拥有访问特定 URI 资源的权限",常见于 ContentProvider 场景(如 APP 通过 ContentProvider 向其他 APP 共享数据)。风险点在于:

  • 未指定具体 Uri:校验时使用Uri.parse("content://*")(通配符 URI),导致调用者可访问所有 URI 资源;

  • 错误设置 modeFlags:modeFlags(如Intent.FLAG_GRANT_READ_URI_PERMISSION)与实际所需权限不匹配(如需要读权限却校验写权限);

  • 忽略返回值判断:未检查checkCallingUriPermission的返回值(PackageManager.PERMISSION_GRANTED/DENIED),直接允许访问。

这些问题会导致 "URI 权限隔离失效",调用者可访问未授权的私有数据(如用户通讯录、短信)。

典型案例:未指定 Uri 类型导致私有数据被非法访问

某社交 APP 的 ContentProvider(UserProvider),用于共享用户资料,但 checkCallingUriPermission 使用通配符 URI:

java 复制代码
// 风险代码:URI权限校验使用通配符,未指定具体Uri
public class UserProvider extends ContentProvider {
    private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
    static {
        // 注册合法URI:content://com.example.social/user/profile(用户资料)
        URI_MATCHER.addURI("com.example.social", "user/profile", 1);
        // 注册敏感URI:content://com.example.social/user/message(用户私信)
        URI_MATCHER.addURI("com.example.social", "user/message", 2);
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        // 风险1:使用通配符URI校验,而非当前请求的uri
        int permission = checkCallingUriPermission(
            Uri.parse("content://*"), // 通配符:允许访问所有URI
            Intent.FLAG_GRANT_READ_URI_PERMISSION
        );

        // 风险2:未判断permission返回值,直接执行查询
        int match = URI_MATCHER.match(uri);
        if (match == 1) {
            return queryUserProfile(); // 合法:查询用户资料
        } else if (match == 2) {
            return queryUserMessage(); // 敏感:查询用户私信
        }
        return null;
    }
}

攻击者通过访问敏感 URI 窃取私信:

  1. 恶意 APP 获取 "访问用户资料" 的 URI 权限(社交 APP 通过grantUriPermission授予);
  2. 恶意 APP 构造敏感 URI:content://com.example.social/user/message,调用 UserProvider 的 query 方法;
  3. 因 ContentProvider 使用通配符 URI 校验,checkCallingUriPermission返回PERMISSION_GRANTED;
  4. 恶意 APP 成功查询到用户私信内容,导致隐私泄露。

二、权限校验安全防御方案

针对上述风险,需围绕 "配置合法、校验可靠、权限最小" 三大原则,结合 Android 系统权限机制的底层逻辑,制定防御方案:

1. uid=1000 的安全管控:禁止普通 APP 配置 + 系统 APP 权限收敛

核心措施
  • 普通 APP:严禁在 AndroidManifest 中声明android:sharedUserId="android.uid.system",若需访问系统资源,通过系统提供的公开 API(如Settings.Secure)而非提权;

  • 系统 APP(需系统签名):配置 uid=1000 后,仅申请必要的系统权限,避免过度授权;

  • 运行时检测:系统 APP 启动时,通过Process.myUid()确认当前 UID 为 1000,避免被篡改;

  • 签名校验:系统 APP 在跨进程调用时,额外校验调用者的签名是否为系统签名,双重保障。

安全实现代码(检测系统 UID 与权限校验)
java 复制代码
// 系统APP的安全检测逻辑
public class SystemAppSecurityUtils {
    // 系统签名的SHA-256哈希值(预存,从系统证书提取)
    private static final String SYSTEM_SIGN_HASH = "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2";

    /**
     * 系统APP启动时检测UID是否合法(防止被篡改)
     */
    public static boolean checkSystemUidValid(Context context) {
        int currentUid = Process.myUid();
        // 校验当前UID是否为系统UID(1000)
        if (currentUid != 1000) {
            Log.e("SystemSecurity", "非法UID:" + currentUid + ",系统APP需为1000");
            return false;
        }

        // 额外校验APP签名是否为系统签名(防止伪造系统APP)
        return checkAppSignature(context, SYSTEM_SIGN_HASH);
    }

    /**
     * 校验APP签名是否匹配目标哈希值
     */
    private static boolean checkAppSignature(Context context, String targetHash) {
        try {
            PackageInfo packageInfo = context.getPackageManager()
                    .getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
            Signature[] signatures = packageInfo.signatures;
            if (signatures == null || signatures.length == 0) {
                return false;
            }

            // 计算签名的SHA-256哈希值
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] signatureBytes = signatures[0].toByteArray();
            digest.update(signatureBytes);
            String appSignHash = bytesToHex(digest.digest());

            // 比对哈希值(忽略大小写)
            return targetHash.equalsIgnoreCase(appSignHash);
        } catch (Exception e) {
            Log.e("SystemSecurity", "签名校验异常", e);
            return false;
        }
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}

// 系统APP启动页调用检测
public class SystemAppSplashActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 启动时检测UID与签名合法性
        if (!SystemAppSecurityUtils.checkSystemUidValid(this)) {
            finish(); // 非法则退出APP
            return;
        }
        // 合法则进入主页面
        startActivity(new Intent(this, SystemAppMainActivity.class));
        finish();
    }
}

2. 规范使用 checkCallingPermission:跨进程权限校验的唯一可靠方案

核心措施
  • 跨进程场景必用:Service、ContentProvider、BroadcastReceiver 的跨进程调用,必须使用checkCallingPermission校验调用者是否拥有指定权限;

  • 校验时机前置:在执行核心逻辑(如支付、数据查询)前先校验,避免执行部分逻辑后因权限不足中断;

  • 处理返回值:严格判断返回值是否为PackageManager.PERMISSION_GRANTED,非授权则抛出SecurityException;

  • 动态权限适配:Android 6.0(API 23)后,需确保调用者已获取 "危险权限" 的运行时授权,checkCallingPermission会自动判断动态权限状态。

合规代码示例(跨进程服务权限校验)
java 复制代码
// 安全的支付服务:使用checkCallingPermission校验权限
public class SecurePaymentService extends Service {
    // 自定义高风险权限(需在AndroidManifest中声明)
    private static final String PERMISSION_SUBMIT_PAYMENT = "com.example.permission.SUBMIT_PAYMENT";

    @Override
    public IBinder onBind(Intent intent) {
        return new SecurePaymentBinder();
    }

    public class SecurePaymentBinder extends IPaymentService.Stub {
        @Override
        public void submitPayment(String orderId, String password) throws RemoteException {
            // 前置权限校验:使用checkCallingPermission
            int permission = checkCallingPermission(PERMISSION_SUBMIT_PAYMENT);
            if (permission != PackageManager.PERMISSION_GRANTED) {
                throw new SecurityException("调用者无支付权限,需申请" + PERMISSION_SUBMIT_PAYMENT);
            }

            // (可选)双重校验:结合签名判断(针对高敏感操作)
            String callingPackage = getCallingPackage();
            if (!checkCallingPackageSignature(callingPackage)) {
                throw new SecurityException("调用者签名非法");
            }

            // 执行支付逻辑
            executePayment(orderId, password);
        }
    }

    // 校验调用者包名的签名(额外保障,避免权限被非法授予)
    private boolean checkCallingPackageSignature(String packageName) {
        // 逻辑同前文SystemAppSecurityUtils.checkAppSignature,校验包名对应的签名是否为可信签名
        // (此处省略具体实现,需预存可信APP的签名哈希值)
        return true;
    }
}
xml 复制代码
// AndroidManifest中声明自定义权限(高风险,签名权限)
<permission
    android:name="com.example.permission.SUBMIT_PAYMENT"
    android:protectionLevel="signature" /> <!-- 仅同签名APP可获取该权限 -->
<uses-permission android:name="com.example.permission.SUBMIT_PAYMENT" />

3. checkCallingUriPermission 正确用法:明确 Uri 与权限类型

核心措施
  • 使用请求的具体 Uri:校验时传入当前调用的uri参数,而非通配符或固定 Uri;

  • 匹配 modeFlags 与权限需求:需要读权限则使用Intent.FLAG_GRANT_READ_URI_PERMISSION,写权限使用Intent.FLAG_GRANT_WRITE_URI_PERMISSION;

  • 强制判断返回值:仅当返回PackageManager.PERMISSION_GRANTED时允许访问,否则拒绝;

  • 结合 URI 匹配器:使用UriMatcher限制合法 URI,避免非预期 URI 的访问。

代码示例(ContentProvider URI 权限校验)
java 复制代码
// 安全的用户ContentProvider:正确使用checkCallingUriPermission
public class SecureUserProvider extends ContentProvider {
    private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
    // 仅注册合法URI,拒绝敏感URI的外部访问
    static {
        URI_MATCHER.addURI("com.example.social", "user/profile", 1); // 合法:用户资料(允许外部访问)
        // 敏感URI(用户私信)不注册外部访问,仅内部使用
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        // 先校验URI是否在合法列表中
        int match = URI_MATCHER.match(uri);
        if (match != 1) {
            throw new SecurityException("非法URI:" + uri);
        }

        // 正确使用checkCallingUriPermission:传入当前uri+读权限flag
        int permission = checkCallingUriPermission(
            uri, // 传入当前请求的具体URI,非通配符
            Intent.FLAG_GRANT_READ_URI_PERMISSION // 匹配读权限需求
        );

        // 严格判断返回值,非授权则拒绝
        if (permission != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("无访问" + uri + "的权限");
        }

        // 权限合法,执行查询(仅返回用户资料,无敏感数据)
        return queryUserProfile(projection, selection, selectionArgs, sortOrder);
    }

    // 仅查询用户公开资料(如昵称、头像,无私信、手机号)
    private Cursor queryUserProfile(String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        // 具体查询逻辑...
        return null;
    }
}

4. 禁用不安全的校验方法:替代方案与风险规避

核心措施(不安全方法清单与替代方案)
不安全校验方法 风险点 替代方案(安全方法)
getCallingPackage()判断包名 包名可通过 Hook、动态代理伪造 1. checkCallingPermission校验权限;2. 结合checkAppSignature校验签名(双重保障)
getCallingUid()判断 UID 范围 UID 可通过 root 设备篡改,无法区分可信性 1. checkCallingPermission校验权限;2. 系统 APP 可结合Process.myUid() == 1000判断
忽略校验直接执行 任何 APP 均可调用,无权限限制 强制使用checkCallingPermission/checkCallingUriPermission校验
checkSelfPermission()跨进程校验 仅校验自身权限,不校验调用者权限 跨进程场景必须使用checkCallingPermission(而非checkSelfPermission)
代码示例(替代不安全的包名判断)
java 复制代码
// 替代getCallingPackage()的安全逻辑
private void secureCheckCallingSource() {
    // 优先校验权限(核心保障)
    int permission = checkCallingPermission("com.example.permission.TRUSTED_ACCESS");
    if (permission != PackageManager.PERMISSION_GRANTED) {
        throw new SecurityException("无可信访问权限");
    }

    // (可选)额外校验签名(针对高敏感场景)
    String callingPackage = getCallingPackage();
    if (callingPackage == null) {
        throw new SecurityException("无法获取调用者包名");
    }

    // 预存可信APP的包名与签名哈希映射
    Map<String, String> trustedApps = new HashMap<>();
    trustedApps.put("com.example.official", "trusted_sign_hash_123");

    if (!trustedApps.containsKey(callingPackage)) {
        throw new SecurityException("调用者包名不在可信列表");
    }

    // 校验调用者签名是否匹配预存哈希
    if (!checkAppSignature(getContext(), callingPackage, trustedApps.get(callingPackage))) {
        throw new SecurityException("调用者签名不匹配");
    }
}

// 校验指定包名的APP签名
private boolean checkAppSignature(Context context, String packageName, String targetHash) {
    // 逻辑同前文,计算packageName对应的签名哈希并比对
    // (此处省略具体实现)
    return true;
}

三、权限校验安全测试方法

权限校验的测试需覆盖 "配置合法性" 与 "校验可靠性",结合静态审核与动态绕过模拟,确保无漏洞:

1. 静态测试(配置与代码审核)

  • uid=1000 配置检测
  1. 检查 AndroidManifest 是否存在android:sharedUserId="android.uid.system",普通 APP 若有则标记为高风险;
  2. 系统 APP 需确认是否有checkSystemUidValid等 UID 与签名检测逻辑;
  • 权限校验方法检测
  1. 搜索跨进程场景(Service、ContentProvider)的代码,确认是否使用checkCallingPermission/checkCallingUriPermission
  2. 若存在getCallingPackage()/getCallingUid()单独判断,标记为不安全,需替换为系统推荐方法;
  3. 检查checkCallingUriPermission是否使用具体 Uri,而非通配符;
  • 权限声明检测
  1. 确认自定义权限的protectionLevel是否合理(高风险权限设为signature,普通权限设为normal)。

2. 动态测试(权限绕过模拟)

  • uid=1000 提权测试
  1. 对普通 APP,尝试添加sharedUserId="android.uid.system"并编译,验证是否安装失败;
  2. 在 root 设备上,使用pm install -t -r --uid 1000 malicious.apk强制安装恶意 APP,验证系统是否拦截。
  • 权限绕过测试
  1. 开发测试 APP,通过 Hook getCallingPackage()伪造可信包名,调用目标 APP 的跨进程接口,验证是否被checkCallingPermission拦截;
  2. 对 ContentProvider,构造未授权的 URI(如敏感数据 URI),调用 query 方法,验证是否被checkCallingUriPermission拒绝;

四、总结:权限校验的核心原则

Android 权限校验的安全防御,需紧扣 "依赖系统、最小权限、双重保障" 三大核心原则,避免因配置失误或方法误用导致权限机制失效:

  1. 依赖系统底层校验 :跨进程权限校验必须使用checkCallingPermission/checkCallingUriPermission,禁用包名、UID 等上层可伪造的标识判断 ------ 系统方法基于底层权限机制,可抵御大部分伪造攻击;
  2. uid=1000 严格管控:普通 APP 严禁配置系统 UID,系统 APP 需通过 UID + 签名双重检测,避免提权漏洞;
  3. 权限最小化:仅申请业务必需的权限,自定义权限按风险等级设置protectionLevel(高风险用signature),减少权限泄露面;
  4. 校验前置且严格:核心逻辑执行前必须完成权限校验,严格判断返回值,不遗漏任何非授权场景。
相关推荐
国科安芯6 分钟前
火箭传感器控制单元的抗辐照MCU选型与环境适应性验证
单片机·嵌入式硬件·架构·risc-v·安全性测试
介一安全14 小时前
【Web安全】XML注入全手法拆解
xml·web安全·安全性测试
大方子16 小时前
【PolarCTF】rce1
网络安全·polarctf
枷锁—sha17 小时前
Burp Suite 抓包全流程与 Xray 联动自动挖洞指南
网络·安全·网络安全
聚铭网络18 小时前
聚铭网络再度入选2026年度扬州市网络和数据安全服务资源池单位
网络安全
darkb1rd20 小时前
八、PHP SAPI与运行环境差异
开发语言·网络安全·php·webshell
世界尽头与你1 天前
(修复方案)基础目录枚举漏洞
安全·网络安全·渗透测试
国科安芯1 天前
抗辐照MCU在精密时频系统中的单粒子效应评估与可靠性验证
单片机·嵌入式硬件·架构·制造·安全性测试
枷锁—sha2 天前
【SRC】SQL注入快速判定与应对策略(一)
网络·数据库·sql·安全·网络安全·系统安全
liann1192 天前
3.1_网络——基础
网络·安全·web安全·http·网络安全