如何防止其他应用程序定义相同的权限名称?

9
我的应用程序定义了一个使用android:protectionLevel="signature"的权限。
<permission android:name="my.app.permission.EXAMPLE" android:protectionLevel="signature" />

我的意图是创建只能由我的签名应用程序启动的应用程序模块。这些应用程序模块在其活动中具有android:permission。 这很好用。但是... 第三方应用程序可以使用相同的权限名称并将保护级别更改为普通,例如

<permission android:name="my.app.permission.EXAMPLE" android:protectionLevel="normal" />

如果我的应用程序先安装,我可以防止其他应用程序覆盖权限。但是,如果卸载我的应用程序,然后安装他的应用程序,则会重新定义权限。
是否可能防止其他应用程序使用相同的权限名称,例如为权限分配唯一的ID,如应用程序包?
尽管清单已加密,但在尝试启动需要此权限的活动时,任何人都可以在日志窗口中读取权限名称(当具有所需权限名称时,将抛出异常)。

好问题,我的猜测是你没有办法限制其他应用程序这样做。 - FoamyGuy
这是一个安全问题。我无法保证我的签名应用程序模块只会在我的签名核心应用程序中启动,因为未签名的应用程序可以替换我的权限定义低级别保护,然后使用我的签名模块。 - Dennix
您可以通过创建一个具有不同包名、签名和protectionLevel=normal的修改版本的应用程序来设置测试。看看当两个应用程序在同一设备上时会发生什么。我的猜测是,a) 签名检查将首先启动,并确保流氓应用程序无法访问需要正确签名的应用程序。b) 具有不同protectionLevel级别的相同权限字符串可以共存于同一设备上。 - tiguchi
1
@Dennix 你可以考虑增加额外的安全层,例如在启动模块活动时添加一些加密的Extra。并编写程序以此方式:如果Extra不正确或不存在,直接关闭而不执行任何操作。这样,如果模块活动是从其他来源启动的,则它们将没有这个Extra,并且模块将似乎没有任何反应。 - FoamyGuy
3个回答

5
只有惯例,没有执行。就像其他Java世界一样,它松散地依赖于域名注册基础设施。这个想法是你用你所拥有的公共互联网域名(例如com.myawesomecompany.myapp.MYPERMISSION)作为你的许可名称的前缀。
域名的唯一性自然由注册机构社区强制执行。
是的,系统容易被滥用。
编辑:如果您正在保护广播式频道,可以添加双向签名检查,如果您觉得有必要的话。将权限名称作为第二个参数调用Context.sendBroadcast()。
编辑2:我觉得你在过度思考这个问题时却对更大的Android应用程序安全画面视而不见。这并不令人印象深刻。滥用权限基础架构并不能让人进入Android应用程序。如果我打算截取你的意图,我不会组装一个假的意图接收器(活动、服务)。相反,我会将调试器连接到你应用程序中的真正接收器,包括签名等等。
使用公开可用的工具,只需几分钟即可为给定的APK组合一个Eclipse项目。将其加载到Eclipse中,连接到运行中的进程,在相关系统API中设置断点(请记住,Android是开源的),然后就可以了。稍加努力,您就可以获得已反编译的Java源代码,以YOUR方法而不是系统方法进行调试。

尽管我使用我的公共互联网域名作为前缀来授予权限,但这并不能防止另一个应用程序使用相同的前缀。我认为Android应该将权限名称与应用程序的包名称绑定。 - Dennix
就像我说的那样 - 这是一个可以被故意滥用的漏洞。 - Seva Alekseyev
我认为Android应该将权限名称与应用程序的包名称绑定在一起。因此,两个不同的应用程序将不会有相同的权限定义。 - Dennix
1
我从未尝试过,但很有可能在安装包时检查权限名称冲突。可以设置一个实验 - 创建一个故意的冲突(使用不同的签名),并尝试在设备上安装两个包。我怀疑第二个 APK 将失败。 - Seva Alekseyev
1
我做了这个测试。第二个apk安装正常,但是权限定义仍然来自第一个apk。问题在于当第一个apk被卸载并重新定义权限后,第二个apk被安装。 - Dennix
一个反向签名检查有帮助吗?请参阅Context.sendBroadcast(Intent,String)。它可以确保接收方持有发送方定义的权限。 - Seva Alekseyev

2
注意:系统不允许多个包使用相同名称声明权限,除非所有的包都使用相同的证书签名。如果一个包声明了一个权限,系统将不允许用户安装其他具有相同权限名称的包,除非这些包与第一个包使用相同的证书签名。为避免命名冲突,我们建议为自定义权限使用反向域名样式的命名方式,例如com.example.myapp.ENGAGE_HYPERSPACE。

https://developer.android.com/guide/topics/permissions/defining


-1

如果您想防止其他应用程序更改您的权限级别,可以使用系统预定义的权限,其级别为“签名”。没有其他常规应用程序可以在系统之前定义权限。

使用系统权限来保护您的资源并不意味着您的应用程序必须使用平台密钥进行签名。

例如:

<service
        android:name="xxx.xxx.xxx.exservice"
        android:permission="android.permission.BROADCAST_PACKAGE_REMOVED" >

唯一的问题是,如果以下代码显示在应用程序的manifest.xml中,AppStore将显示您使用的权限。
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED" />

在这个示例中,您可以通过相同的标志密钥访问您的资源,但是您绝对不能广播软件包删除。

1
这并不能解决安全问题,因为任何你通过uses-permission声明的android.*权限也可能被另一个应用程序声明和使用。 - BLuFeNiX
@BLuFeNiX,我能在Android 12中做到这个吗? 先安装应用程序A,然后安装应用程序B,然后从应用程序A调用应用程序B的组件;在应用程序A中:<permission android:name="com.mycoolcam.USE_CUSTOM1" android:protectionLevel="normal"/> ; 在应用程序B中:<permission android:name="com.mycoolcam.USE_CUSTOM1" android:protectionLevel="signature"/> - ani0904071
@ani0904071 不是的。这只是在非常旧版本的Android上存在的问题,但现在如果您尝试安装一个声明与现有应用程序相同权限的应用程序,则安装将失败。 - BLuFeNiX
@BLuFeNiX,是的,我昨天尝试了一下安卓12,无论是在Android Studio还是设备上都失败了 :) - ani0904071

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接