这些是计算机安全的黄金法则:“不可能对具有系统管理员权限的合格用户隐藏任何内容”和“任何可以物理访问设备的合格用户始终可以将自己提升为系统管理员”。
您不能对拥有机器物理控制权的人隐藏任何信息。如果您试图隐藏的秘密非常重要,那么您永远不应该将数据传输到机器并在您控制的其他地方进行处理。
您的程序正在用户的机器上运行。您无法保护您的数据免受用户的侵害。考虑到这一点,这是否意味着我们注定要失败?不必要。操作系统为程序提供了丰富的机制与另一个程序私下通信,不允许另一个无特权的应用程序拦截它。因此,虽然您无法保护用户自己的任何数据,但您可以保护您的数据免受其他非特权程序的侵害。在非特权程序之间提供安全边界是操作系统的主要工作之一。
其中最简单的是匿名管道。管道允许在程序之间传输单向数据流。匿名管道可用于 Windows、Linux、OSX 和所有类 Unix 系统。匿名管道通常被认为是一对称为 stdin 和 stdout 的管道,它允许父进程向其子进程发送和接收数据流。匿名管道只能在具有父子关系的进程之间使用。还有一个命名管道,但它们在 Windows 和 Linux/类 Unix 系统中的行为不同,我们稍后再讨论。
另一种常用的 IPC 是套接字。套接字就像一个双向管道。有许多不同的套接字,但它们的工作方式相似。最广为人知的是 TCP 套接字。TCP 套接字主要用于机器之间的网络,但您也可以创建只能在同一台机器内使用的环回 TCP 套接字。环回套接字提供隐私(只有连接的程序和侦听的程序才能读取通过套接字的数据),但是它并没有真正提供机制来限制谁可以成为套接字的另一端。
Unix 中用于同一台机器中进程之间通信的另一种套接字类型是 Unix 域套接字。Unix 域套接字作为文件系统中的“特殊文件”向程序公开,Unix 文件系统权限用于控制对套接字的访问。没有权限访问套接字文件的程序无法连接域套接字。在类 Unix 系统中,这意味着您的服务和 GUI 应该作为仅为您的程序保留的相同用户和/或组运行,并且您适当地设置了套接字文件权限。
让我们回到命名管道。在 Linux/类 Unix 系统中,命名管道与标准输入/标准输出非常相似,因为它们是单向的。然而,在 Windows 中,命名管道实际上是双向的,几乎等同于 Windows 中的 Unix 域套接字。像 Windows 中的许多东西一样,命名管道使用 ACL 保护。
有了 iOS,事情变得有点棘手。未越狱的 iOS 只允许非常有限的一组进程间通信,而且都不会给你一个套接字。但是如果我们放宽定义,在 iOS 应用程序中,服务程序和 GUI 程序可能实际上是同一个应用程序,因此您可以简单地在应用程序的不同组件之间直接创建一个流。这也是安全的,因为流只能在应用程序内访问。
Android 为 IPC 提供了更多选项,包括创建域套接字的能力。API 有所不同,但它们在概念上与常规 Linux 相似。或者,您可以采用与 iOS 中相同的方法,将您的服务和 GUI 打包在同一个应用程序中,并且只使用进程内流。