【问题标题】:Android: secure IPC alternative to AIDL?Android:AIDL 的安全 IPC 替代方案?
【发布时间】:2016-03-15 02:20:59
【问题描述】:

我正在尝试做的事情: 在设备上安装的两个应用程序之间实现轻量级、安全 IPC 协议。客户端应用应该能够向在服务应用中运行的Service 发送命令和查询,并接收返回的计算结果。

应用关系:两个应用的源代码都在我的控制之下,但应用会有不同的签名(不可协商)。

安全要求:服务应用应向单个客户端提供其服务。客户端的应用程序 ID(包名称)是已知的且不变的。

我尝试了什么:我尝试使用双向Messenger 通信方案(类似于this blog post)实现IPC。这种方法效果很好,但是我遇到了一个大问题——找不到客户端的UID,因此无法满足安全要求。

考虑在服务应用程序的Service 中找到的这段代码:

// This messenger will be used by the clients of this service in order to send commands
private Messenger inboxMessenger = new Messenger(new Handler() {

    @Override
    public void handleMessage(Message msg)

        // TODO: verify the identity of the client

        switch (msg.what) {
            case MSG_GET_DATA:
                returnDataToClient(msg.replyTo);
                break;
        }
    }
});

这里的想法是,当客户端应用程序向此Service 发送消息时,它会将其本地“回调”Messenger 放入发送的Message 的replyTo 成员中。 Messenger 的文档指出:

注意:下面的实现只是一个简单的包装器 用于执行通信的 Binder。

所以我想我可以以某种方式将Messenger#getBinder() 返回的Binder 映射到客户的UID,但我现在遇到了麻烦:

  1. Messenger#getBinder() 返回 IBinder 不能转换为 Binder
  2. 即使我设法获得了对客户Binder 的引用,Binder#getCallingUid() 方法也是static 并且不接受参数...

所以,为了使这个特定的实现安全地工作,我需要找到一种方法来根据Message 的内容或基于客户端创建的特定Messenger 获取调用者的UID。由于 Android 的安全架构是围绕 Binders 构建的,因此没有直接的方法将 Binders 映射到 UIDs(或包名称)似乎很奇怪......那么,我该怎么做呢?

额外问题:除了 AIDL,Android 上是否还有其他 IPC 技术可以满足上述要求?

【问题讨论】:

  • 当你从handleMessage()内部调用静态getCallingUid()时,返回什么值?引用the documentation,getCallingUid()“返回分配给向您发送正在处理的当前事务的进程的Linux uid......如果当前线程当前没有执行传入事务,则返回它自己的uid”。在这种情况下,我怀疑你会得到自己的 UID,因为 Handler,但至少值得一试。
  • "Android 上是否还有其他 IPC 技术可以满足上述要求?" -- 查看getCallingUid() 从服务的onStartCommand() 返回什么,由客户端上的startService() 触发。查看getCallingUid() 从onReceive() 或BroadcastReceiver 返回的内容,用于客户端发送的广播。对于客户端通过ContentResolver 发送的请求,查看getCallingUid() 在ContentProvider(例如call())的方法中返回的内容。就个人而言,我只使用了基于 AIDL 的 .Stub 中的 getCallingUid(),但我认为上述 1+ 应该可以工作。
  • @CommonsWare,确实,从handleMessage() 内部调用getCallingUid() 返回服务的“自己的”UID。明天我会测试你建议的其他方法并提供反馈。
  • @CommonsWare,我尝试在所有Service 生命周期回调(onCreate()、onStartCommand()、onBind())中测试getCallingUid()——它们都返回了“自己的”UID。也许您建议的其他方法之一会起作用,但是,即使是这种情况,它们也会使事情变得不直观,并可能造成潜在的性能瓶颈(只是我的猜测)。所以,我想,我最好开始编写 AIDL 合约......
  • 您是否考虑过使用 Binder 作为服务器向客户端发出的令牌,然后将其作为每个后续客户端请求的一部分? Binder 在所有进程中都是唯一的,因此可以(并且正在)用作与包名称/签名相结合的安全身份。

标签: android ipc android-security android-binder


【解决方案1】:

您可以在服务器端检查客户端的签名,以确保它是合格的。

【讨论】:

【解决方案2】:

经过一些研究和实验,我得出的结论是,在安全、签名保护的通信方面,Android 没有提供 AIDL 的替代方案。

好消息是 AIDL 实施起来并不难,关于这个特定主题的官方教程一点也不差。

【讨论】:

    猜你喜欢
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 2017-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多