Android中Binder提供的进程间通信是否可以防止中间人攻击?是否有任何文档提供此信息?
2 回答
Binder 使用基于能力的安全模型。每个 binder 对象代表一个能力;将该对象交给另一个进程会授予该进程对该功能的访问权限。从这个角度来看,您可以通过不将重要的活页夹对象交给中间人来防止中间人攻击。如果一个进程没有得到一个活页夹对象,它就不能以任何方式访问它。
关于论文中讨论的“跨绑定器参考伪造”问题,如果我理解他们正在谈论的具体场景,我认为他们关于用户空间的附录比我同意的要弱一些。他们犯了我认为查看为 ServiceManager 编写的特殊 C 代码的错误。形式上,我认为 C++ 用户空间代码(特别是 Parcel)是 Binder 架构的一部分。当您调用其 readBinder() 和相关方法时,此代码特别确保处理此类欺骗尝试。
我不同意内核没有完全确保数据完整性是一个缺陷的说法。我能想象到的唯一方法是为绑定事务定义标准类型的数据结构,以便它可以读取和验证包裹的内容。在我看来,这将太多的知识放在内核中,并没有真正的好处。不管你放了多少,用户空间都需要对传入的交易进行某种验证,以确保它符合预期。今天,这是在验证 Parcel 上的原始数据读取操作(readBinder()、readString16()、readInt() 等)是为了避免攻击而编写的。向内核推送更多验证仍然需要在用户空间验证数据类型是否正确,
关于 binder 安全性的最后一件事是,重要的是要意识到在平台级别还有另一个重要的安全模型在 binder 基础设施之上实现。这是基于权限/uid 的系统,服务可以检查传入呼叫的 uid 以验证它们是否符合其允许的权限。
这种安全模型有另一个必须处理的欺骗漏洞。一个典型的场景是应用程序接收活动管理器服务的 IBinder(因为每个人都可以得到它)。Activity Manager Service 的 API 深度基于检查传入调用的 uid 以确定允许的内容——例如,如果调用了 bindService(),它将检查该 uid 是否有权绑定到给定的服务。恶意应用程序可以通过将活动管理器 IBinder 交给另一个系统服务来尝试在这里玩游戏,例如作为窗口管理器的 IWindow。如果它知道第二个系统服务将进行的事务,
存在此漏洞是因为没有以任何方式键入活页夹系统,“方法”调用只是使用整数事务代码和数据缓冲区发送的事务。
为了防止这种情况发生,aidl 生成的用户空间类型接口总是将它们打算调用的接口的名称放在其事务缓冲区的开头,并且事务的接收代码会检查缓冲区前面的接口名称以确保它与自己的交互相匹配。这样,当活动管理器看到它有一个接口是窗口的来电时,上面场景中的欺骗者就会被捕获。
无论如何,对于 Android 开发人员的大多数实际使用,基于 uid 的安全性与核心绑定器功能模型一样重要。在某些情况下,您将通过限制哪些进程可以访问活页夹来加强安全性。一个例子是如何有一个 IBinder 代表每个活动,只有系统进程和运行活动的进程共享。
在其他情况下,IBinder 对象将与任何感兴趣的进程共享,但在基于 uid 的调用点强制执行安全性。如果您使用aidl 来提供此类接口的标准实现,那么您可以根据要应用于uid 的含义来完成您自己的此类安全性实现。例如,您可以使用标准工具将权限与 uid 关联,并询问包管理器传入的 uid 是否具有权限。
Binder 有一个已确定的安全漏洞,可能使其容易受到 MITM 攻击:http ://crypto.hyperlink.cz/files/xbinder.pdf 。引用 TFA:
攻击者可以管理目标以进一步传递或调用其“受保护的”绑定器(攻击者不被邀请直接调用)。我们称之为跨绑定器参考伪造(XBRF)
作者接着说,Android 中有针对这种攻击的防御措施,但是
在某些情况下,对攻击进程准备的交易数据进行仔细操作仍可能导致成功的 XBRF 攻击
给人的印象是,对于精心编写的代码,Binder 似乎相对安全,但存在一些风险。