MIT 6.858 计算机系统安全讲义 2014 秋季(三)(3)https://developer.aliyun.com/article/1484160
每个通过 OR 的电路保留哪些状态?
- 电路中两个方向(从 OP 到 OR)的电路 ID 和相邻 OR。
- 与此电路和此 OR 的 OP 共享密钥。
- 每个电路的 SHA-1 状态。
我们能否避免在网络中存储所有这些状态?
- 没有每个单元中的可变长度路径描述符。
- 出口节点同样需要路径描述符才能知道如何发送回去。
- 中间节点需要执行公钥加密(昂贵)。
Tor 为什么需要出口策略?
- 防止滥用(例如,匿名发送垃圾邮件)。
- 出口策略类似于防火墙规则(例如,不能连接到端口 25)。
- 每个出口节点在打开新连接时检查出口策略。
- 为什么在目录中发布出口策略,以及其他节点信息?
- 不用于强制执行。
- OP 需要知道哪些出口节点可能有效。
如果 Tor 不进行完整性检查会怎样?
- 需要完整性以防止标记攻击。
- 攻击者入侵内部节点,损坏数据包。
- 损坏的数据包最终会被发送出去,可以观察它们的去向。
Tor 如何防止重放攻击?
- 每个校验和实际上是 OP 和 OR 之间所有先前单元的校验和。
- 再次发送相同数据的校验和将不同。
- 运行良好,因为底层传输是可靠的(SSL/TLS 在 TCP 上)。
匿名服务
- 隐藏服务由公钥命名(伪 DNS 名称“publickey.onion”)。
- 为什么要在介绍点和会面点之间分开?
- 避免在介绍点上放置流量负载。
- 避免介绍点传输已知非法数据。
- 分割可以防止这两个问题。
- Bob(服务)有一个介绍点(IP)。
- Alice 选择一个会面点(RP),告诉 Bob 的 IP 关于 RP。
- 介绍点不中继数据。
- 会面点不知道它正在中继的数据是什么
- 为什么 Bob 要连接回 Alice?
- 准入控制,将负载分散到许多会面点。
- 什么是会面点 cookie?-让 Bob 向 Alice 的 RP 证明它是 Bob。
- 什么是授权 cookie?
- 一些可能会促使 Bob 回复的东西,否则他不会回复。
- 或许是大多数人不知道的秘密词语。
- 限制对 Bob 服务器的 DoS 攻击(只需发送许多 cookie)。
- 存储在主机名中:cookie.pubkey.onion。
- 最终状态:两个电路连接到 RP,之间有一个流连接。
- RP 从一个电路的流中获取中继单元,并
- 将它们发送到另一个电路中的流中。
- 使用 Alice 和 Bob 之间共享的密钥(DH)加密桥接数据。
- 每个人都可以控制自己的匿名级别。
- 两个电路的完整路径都不知道。
使用 Tor 时可能会遇到的潜在问题?
- 应用层泄漏(Javascript,HTTP 头,DNS,…)
- 使用应用级代理(例如,Privoxy 剥离许多 HTTP 头)。
- 基于 Tor 客户端行为的指纹识别(新电路打开的频率)。
- 时间/量分析(部分防御是运行自己的 Tor OR)。
- 对网站进行指纹识别:流行网站的请求次数和文件大小。
- 固定大小单元的量化有所帮助。
- 恶意 OR:加入网络,广告大量带宽,开放出口政策。
运行 OR 的好处/风险?
好处:
- 更多的匿名性
风险:
- 资源使用
- 在线攻击(DoS,入侵,…)
- 离线攻击(例如,机器被执法部门扣押)
阻止 Tor 有多难?
- 从目录中找到 OR IP 列表,阻止所有流量到它们。
- 如何防御这种攻击?
- 向不同的客户端透露不同的 OR?
- 允许基于使用的 OR 对客户端进行指纹识别。
- 保持一些未列出的 OR?
- 只将未列出的 OR 用作第一跳,以避免指纹识别。
- Tor 有“桥接”节点的概念,这是一个未列出的 OR。
- 如何找到这些未列出的“桥接”OR?
- 希望合法用户找到它们,但不让对手枚举它们。
- Tor 采取的方法:特殊的桥接目录。
- 向每个 IP(通过 HTTP)或电子邮件地址(通过电子邮件)透露 3 个桥接。
- 仅在 24 小时后向相同客户端地址透露新的桥接。
- 可以按 IP 限制速率,找到尝试枚举桥接数据库的尝试等。
- 对于电子邮件,对手更容易创建虚假身份(电子邮件地址)。
- Tor 信任 3 个邮件提供商来限制注册(gmail,yahoo,mit)。
你会使用 Tor 吗?它适用于哪些应用程序?
- 可能对所有流量使用速度太慢(高延迟)。
- 但不幸的是,这意味着只有敏感流量会通过 Tor 传输。
- 可能存在可信攻击,因此对抗非常强大的对手不是很好。
- 或许是避免拒绝服务攻击的好方法(即,转移到 Tor 上)。
- 据说,谷歌使用 Tor 来检查服务器是否特殊处理谷歌的 IP 地址。
Tor 有多活跃?
- 现在比论文描述的使用更加活跃。
- ~3000 个公共 ORs,~1000 个出口节点,~1000 个桥接节点,~2GB/s 的 OR 带宽。
- 8-9 (?) 个目录服务器,约 1600 个目录镜像。
- 困难问题:分发入口点 IP 地址,批准 ORs,…
- 有些 BitTorrent 使用,但并不压倒性:主要是因为对于大文件来说太慢了。
另一种方法:DC-nets(“用餐密码学家网络”)。
- N 个参与者,但假设只有一个发送者(不知道是谁)。
- 每对参与者共享一个秘密比特位。
- 要传输“0”比特位,发送所有秘密的异或值。- 否则,发送相反的值。
- 所有传输都是公开的:为了恢复比特位,对所有人的传输进行异或运算。
- 可以建立发送多个比特位,使用冲突检测协议等。
- 在性能方面代价高昂,但提供比 Tor 更强大的安全性。
- 查看 Dissent OSDI 2012 论文,了解基于 DCnet 的系统的更多细节。
参考:
Android 安全
注意: 这些讲座笔记略有修改,来自 2014 年 6.858 课程网站上发布的内容。
为什么选择这篇论文?
- 真实系统,被广泛使用。
- 谨慎的安全设计(比 Web 或桌面应用程序更重要)。
- 原则=应用程序(而不是用户)
- 策略与代码(清单)分离
- 一些问题是不可避免的,并且看到问题出现的地方是有启发性的。
- 但也有趣的是看如何设计一个合理的安全计划。
威胁模型
- 目标: 任何人都可以编写任何人都可以安装的应用程序
- 威胁:
- 应用程序可能存在错误
- 应用程序可能是恶意的
CVE 数据库
www.cvedetails.com/vulnerability-list/vendor*id-1224/product*id-19997/Google-Android.html
- 一些错误但不是压倒性的—安全计划有效吗?
- 缓冲区溢出(仍然发生…)
- 当然,Android 运行在 Linux 上,这也包括 Linux 内核问题
总体计划
- 首先了解 Android 应用程序的外观和工作原理。
- 然后讨论安全机制和策略。
Android 应用程序是什么样子的?
- 四种组件类型:
- 活动: 应用程序的 UI 组件,通常每个“屏幕”一个活动。
- 服务: 后台处理,可以被其他组件调用。
- 内容提供程序: 可被其他组件访问的 SQL 数据库。
- 广播接收器: 接收来自其他组件的广播通知。
- 每个应用程序还有私有文件存储。
- 应用程序通常用 Java 编写。
- 运行在 Linux 内核+Android“平台”上(稍后会介绍)。
- 应用程序还有一个声明其权限的清单(稍后)。
- 整个应用程序由开发者签名。
活动:可以在屏幕上绘制,获取用户输入等。
- 一次只有一个活动在运行。
- 帮助用户推理输入的安全性。
- 如果用户正在运行银行应用程序(活动),则没有其他活动获取用户的输入。
意图:Android 中的基本消息原语。
- 代表应用程序意图做某事/与另一个组件交互。
意图字段:
- 组件:将请求路由到的组件名称(只是一个字符串)。
- 例如,
com.google.someapp/ComponentName
- 操作:此消息的操作码(只是一个字符串)。
- 例如,
android.intent.action.MAIN
,android.intent.action.DIAL
,…
- 数据:用于动作的数据的 URI(只是一个字符串)。
- 例如,
tel:16172536005
,content://contacts/people/1
(用于拨号)。 - 还包括数据的 MIME 类型。
- 类别:用于查找发送意图的过滤机制。
- 例如,
android.intent.category.BROWSABLE
表示可以从浏览器调用,用于动作android.intent.action.VIEW
,该动作查看数据中的 URI。
- 显式意图:指定组件名称。
- 隐式意图:没有组件名称,因此系统必须找出。
- 查看动作,数据,类别。
- 如果有多个组件匹配,也可以询问用户要使用哪个应用程序。
- 例如,用户点击地址 - 要打开哪个地图应用程序?
对服务的 RPC
- 初始与服务的通信通过发送意图进行。
- 服务还可以为客户端定义一个 RPC 协议。
- 比每次发送意图更有效。
- 客户端将连接“绑定”到服务。
网络 - 访问互联网。
- 与任何其他 Linux 系统中一样工作。
- 应用程序可以直接使用套接字,也可以通过 Java 的网络库。
为什么我们需要一个新的应用程序模型?(或者,现有模型有什么问题?)
- 桌面应用程序:
- – 应用程序之间的隔离不够。
- – 每个应用程序都拥有完整的特权,任何一个恶意应用程序都可以接管。
- ++ 应用程序可以轻松互相交互,共享文件。
- ++ 用户可以为每个任务选择应用程序(电子邮件应用程序、图像查看器等)。
- 基于 Web/浏览器的应用程序:
- ++ 无需安装应用程序或担心本地状态。
- – 在典型模型中需要服务器(离线使用困难)。
- – 应用程序之间的互动有限。
- –存在的互动通常是硬编码到特定的 URL。
- 例如,链接到联系管理器应用程序的 URL:用户无法选择新的。
- 越来越好:尝试解决此问题的“Web 意图”。
- –纯客户端应用程序的功能有些受限。
- 越来越好:相机、位置信息、本地存储、工作线程等。
Android 访问控制
Android 的应用程序模型如何处理应用程序互动、用户选择应用程序?
- 主要基于意图。
- 如果多个应用程序可以执行一个操作,发送隐式意图。
- Android 框架决定哪个应用程序获得意图;可以询问用户。
Android 的应用程序模型如何处理应用程序隔离?
- 每个应用程序的进程在 Linux 中运行在单独的 UID 下。
- 例外:一个开发者可以将多个应用程序捆绑到一个 UID 中。
- 每个应用程序都有自己的 Java 运行时(但这主要是按照惯例)。
- Java 解释器不受信任,甚至不是必需的;内核强制执行隔离。
每个应用程序 UID 有什么好处?
- 一个应用程序不能直接操作另一个应用程序的进程、文件。
- 每个应用程序都有私有目录(
/data/data/appname
)。
- 存储首选项、内容提供程序的 sqlite 数据库、缓存文件等。
UID 隔离缺少什么:对共享资源的访问控制。
- 网络访问。
- 可移动的 sd 卡。
- 设备(相机、指南针等)。
- 意图:谁可以发送,什么意图,发送给谁?
- 我们还需要以某种方式确定所有这些的策略。
首先,机制:Android 如何控制对上述所有内容的访问?
- 网络访问:GIDs。
- 特殊的组 ID 定义了应用程序可以与网络通信的内容。
- GID
AID_NET_BT_ADMIN (3001)
: 可以创建低级蓝牙套接字 - GID
AID_NET_BT (3002)
: 可以创建蓝牙套接字 - GID
AID_INET (3003)
: 可以创建 IP 套接字 - GID
AID_NET_RAW (3004)
: 可以创建原始套接字 - GID
AID_NET_ADMIN (3005)
: 可以更改网络配置(ifconfig,…)
- 需要内核更改才能实现这一点。
- 每个应用程序根据其特权获得这些组 ID 的子集。
- 没有对网络通信进行更精细的控制。
- 例如,可以想象按 IP 地址或按来源类似的策略。
- 访问可移动 SD 卡。
- 为什么不使用文件系统权限?
- 希望在 SD 卡上使用 FAT 文件系统,以允许在其他设备上访问。
- FAT 文件系统没有文件所有权、权限等概念。
- 内核将所有 SD 卡文件视为特殊组 sdcard_rw(1015)拥有。
- 应该访问 SD 卡的应用程序在其组列表中具有此 GID。
- 在整个 SD 卡内没有更精细的隔离。
- 设备。
- 设备文件(
/dev/camera
、/dev/compass
等)由特殊组拥有。 - 应用程序在其组列表中以适当的组运行。
- 意图。
- 所有意图都经过单个可信的“参考监视器”路由。
- 运行在 system_server 进程中。
- 参考监视器执行意图解析(将意图发送到哪里?),
- 用于隐式意图。
[ref: ActivityStack.startActivityMayWait]
- 参考监视器检查权限,基于意图和发送者。
[ref: ActivityStack.startActivityLocked]
- 将意图路由到适当的应用程序进程,或启动一个新的进程。
- 为什么不只使用意图来处理一切,而不是使用特殊组?
- 效率:希望直接访问相机、网络、SD 卡文件。
- 通过意图发送所有内容可能会带来重大开销。
参考监视器如何决定是否允许一个意图?
- 分配给应用程序和组件的“标签”。
- 每个标签都是一个自由格式的字符串。
- 通常以 Java 风格的包名称编写,以确保唯一性。
- 例如,
com.android.phone.DIALPERM
。
- 每个组件都有一个保护它的单个标签。
- 对该组件的任何意图必须由具有该标签的应用程序发送。
- 例如,电话拨号服务标记为
...DIALPERM
。 - 对于内容提供程序,有两个标签:一个用于读取,一个用于写入。
- 应用程序有一个授权使用的标签列表。
- 例如,如果应用程序可以拨打电话,则
...DIALPERM
在其标签集中。
- 其他权限(网络、设备、SD 卡)映射到特殊的标签字符串。
- 例如,android.permission.INTERNET 被翻译为应用程序在 GID 3003 下运行。
应用程序如何获得一组特定标签的权限?
- 每个应用程序都有一个声明其所需权限(标签)的清单。
- 还声明了应该保护每个组件的标签。
- 当应用程序安装时,Android 系统会询问用户是否允许安装应用程序。
- 提供应用程序正在请求的权限列表。
曾经,Android 允许用户设置细粒度的权限选择。
- Android 4.3 引入了“权限管理器”。
- 显然,这在 Android 4.4 中被移除了。
- 可能的原因:开发人员希望对事物有可预测的访问。
谁定义权限?
- 应用程序自己定义权限(回想:只是自由格式的字符串)。
- Android 系统为内置资源(相机、网络等)定义权限。
- 可以使用 ‘adb shell pm list permissions -g’ 列出。
- 内置应用程序为其提供的服务定义权限。
- 例如,读取/写入联系人、发送短信等。
- 定义权限意味着指定:
- 权限的用户可见名称。
- 用户的权限描述。
- 将权限分组到一些类别中(花费、私人数据等)。
- 权限类型:“正常”、“危险”和“签名”。
三种权限类型的含义是什么?
- 正常:
- 可能会让应用程序烦扰用户,但不会造成严重后果的良性权限。
- 例如,
SET_WALLPAPER
。 - 比较
和(pmlistpermissions−g−d)和(pm list permissions -g -d) 和 (pm list permissions -g)
- 系统不会询问用户有关“正常”权限。
- 为什么要有这些权限?
- 可以在真正感兴趣时进行审查。
- 最小权限原则,如果应用程序以后被破坏。
- 危险:
- 可能允许应用程序执行危险操作。
- 例如,访问互联网、访问联系信息等。
- 签名:
- 只能授予由同一开发人员签名的应用程序。
- 想要强制使用 HTTPS:希望防止用户意外泄露。
为什么在引用监视器中进行此检查,而不是在每个应用程序中?
- 便利性,以防程序员忘记。
- 可以在应用程序端的库中执行。
- 根据权限可能将意图路由到不同的组件。
- 不想发送一个意图给组件 A,而另一个组件 B 却愿意接受它。
- 强制访问控制(MAC):权限与代码分开指定。
- 附注:烦恼,MAC 是一个多义词缩写。
- 媒体访问控制 – 以太网中的 MAC 地址。
- 消息认证码 – Kerberos v4 缺少的东西。
- 希望了解系统的安全属性而不查看代码。
- 对比:Unix 中的自主访问控制(DAC)。
- 每个应用程序都可以在文件上设置自己的权限。
- 权限可以随时间由应用程序更改。
- 看当前文件权限无法准确预测会发生什么。
- 应用程序也可以执行自己的检查。
[ref: checkCallingPermission()]
- 有点破坏了 MAC 模型:不能只看清单。
- 有必要,因为一个服务可能导出不同的 RPC 函数,
- 想要为每个权限设置不同级别的保护。
- 引用监视器只检查客户端是否可以访问整个服务。
谁可以注册接收意图?
- 任何应用程序都可以指定要接收具有任意参数的意图。
- 例如,可以在意图过滤器中创建活动(在清单中):
示例:
<intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="http" android:host="web.mit.edu" /> </intent-filter>
- 这是一个问题吗?
- 为什么或为什么不?
- 每当用户点击链接到 http://web.mit.edu/ 时,系统会提示用户。
- 只有“顶层”用户点击转换为意图,而不是网页组件。
- 如果提示用户可能会没问题。
- 即使如此,如果您唯一的地图应用程序是“不好的”:窃取发送给它的地址?
- 对于广播意图来说并不是很好,因为会发送给所有可能的接收者。
控制广播意图的分发。
- 在文档的示例中,希望
FRIEND_NEAR
意图不被所有人披露。 - 解决方案:发送方在发送广播意图时可以指定额外的权限标签。
- 参考监视器只将此意图发送给具有该标签的接收方。
如何验证意图的来源?
- 通常在接收组件上使用权限标签。
- 只要发送方具有正确的权限,就不一定关心发送方是谁。
- 结果应用程序经常忘记在广播接收器上设置权限限制。
- 2011 年 Usenix 安全论文:“权限再委托攻击”。
- 例如,可以创建一个永远响铃和震动的闹钟。
- 例如,可以向设置广播接收器发送消息以切换 wifi 等。
- 安卓中的一个解决方案:“受保护的广播”(不完整,但是…)
- 参考监视器特殊处理一些意图操作(例如,系统启动)。
- 只有系统进程可以发送那些广播意图。
发送方是否可以依赖名称将意图路由到特定组件?
- 更广泛地说,安卓如何验证名称?(应用程序名称,权限名称。)
- 没有一般计划,只是先到先得。
- 系统名称(应用程序,权限等)在这个模型中获胜。
- 其他应用程序可能会被先到的恶意应用程序抢占。
- 可以通过使用应用程序的名称向恶意应用程序发送敏感数据。
- 可以通过查看发送者名称信任恶意应用程序的意图。
- 可以通过使用恶意应用程序的权限名称设置宽松权限。
如果两个应用程序定义了相同的权限名称会发生什么?
- 先到先得。
- 恶意应用程序可以将一些重要权限名称注册为"正常"。
- 任何应用程序(包括恶意应用程序)现在都可以获得此权限。
- 其他依赖此权限的应用程序将容易受到恶意应用程序的攻击。
- 即使受害应用程序定义了自己的权限并且是唯一使用它的应用程序。(例如,签名权限。)
- 可能更好的做法:如果权限已经定义,则拒绝安装应用程序。
- 允许应用程序假设其自己的权限已经正确定义。
- 仍然不允许应用程序假设其他应用程序/权限名称的任何内容。
如果应用程序名称没有经过验证,为什么应用程序需要签名?
- 代表开发者。
- 对 CA 没有真正的要求。
- 帮助安卓回答三个问题:
- 这个新版本的应用程序是否来自与旧版本相同的开发者?(如果是,可以升级。)
- 这两个应用程序是否来自同一开发者?(如果是,可以请求相同 UID。)
- 应用程序是否来自定义权限的相同开发者?(如果是,可以获得访问签名级别权限。)
如何给另一个应用程序临时权限?
- URI 委托。
- URI 读/写访问的能力式委托。
- 系统通过文字字符串 URI 跟踪委托访问。
- 例如,
content://gmail/attachment/7
- 必须记得撤销委托访问!
- 例如,URI 可能表示稍后的另一条记录…
[ref: grantUriPermission(), revokeUriPermission()]
- 参考监视器将授予的 URI 保留在内存中。
[ref: ActivityManagerService.mGrantedUriPermissions]
- 授权是短暂的,只持续到重新启动。
- 待定意图。
- 用例:从闹钟/时间服务回调到您的应用程序。
- system_server 在内存中跟踪挂起的意图;短暂的。[参考:PendingIntentRecord.java]
- 撤销问题,与 URI 委托一样。“破坏”了 MAC 模型:无法完全从清单中推理出所有安全性。
应用程序存储在哪里?
- 两个选项:内部手机存储器或 SD 卡。
- 内部存储器始终由 Android 控制,因此可以假设它是安全的。
- 在 SD 卡上安装应用程序更加复杂,但由于空间原因更可取。
- 威胁模型:
- 担心恶意应用程序修改 SD 卡数据。
- 担心恶意用户复制付费应用程序。
- SD 卡使用 FAT 文件系统,没有文件权限。
- 方法:使用每部手机的随机密钥对应用代码进行加密/认证。
- 密钥存储在手机的内部闪存中,对应手机唯一。
Android“平台”的安全性有多高?
- TCB:内核+任何以 root 身份运行的东西。
- 优于桌面应用程序:
- 大多数应用程序不属于 TCB 的一部分。
- 作为 root 运行的东西要少得多。
- 一些漏洞在实践中显现。
- Linux 内核或 setuid-root 二进制文件中的错误允许应用程序获取 root 权限。
- 如何做得更好?
- 系统调用过滤/ seccomp 使利用内核漏洞变得更加困难?
- 不清楚。
- 用户无意中安装具有危险权限的恶意软件应用程序。
- 实际常见的恶意软件:向高价号码发送短信。
- 攻击者通过部署此类恶意软件直接获得金钱。
- 用户为什么会犯这样的错误?
- 一个原因:某些权限对于平凡任务和敏感任务都是必要的。
- 例如,访问电话状态/身份需要获取唯一设备 ID。
- 导致不必要请求危险权限,使用户麻木不仁。
- 另一个原因:应用程序提前要求权限“以防万一”。
- 例如,可能以后需要它们,但更改权限需要手动更新。
- 另一个原因:无法拒绝某些权限。
- 另一个原因:包含恶意软件的现有 Android 应用程序的副本。
- 如何修复?
- 找到允许更多“非危险”权限而无需询问用户的方法。
- 允许用户有选择地禁用某些权限。(有关此方面的一些研究工作,请参见下面的参考资料。)
- 静态/运行时分析和审计–现在由 Google 实施。
- 寻找现有热门应用程序的几乎相同的克隆。
- 运行应用程序一小段时间以确定它们的功能。
- 安全研究人员在 Google 的应用程序扫描程序上获得了(非 root)shell。
- 事后合理预期:应用程序扫描程序只运行应用程序。
- Android 的应用市场(Google Play)允许 Google 远程停用应用程序。
移动电话应用程序中的安全性的另一种模型:iOS/iPhone。
- 安全机制:所有应用程序运行两个可能的 UID。
- 苹果应用程序一个 UID,其他所有应用程序另一个 UID。
- 从历史上看是有道理的:一次只有一个应用程序处于活动状态。
- 随着多任务应用程序的切换,未更改 UID 模型。
- 反而,使用苹果的沙盒隔离应用程序(“Seatbelt”?)。
- 最初苹果应用程序之间没有隔离(现在不清楚?)。
- 因此,浏览器中的漏洞利用使所有苹果应用程序“暴露”。
- 在使用时提示权限。
- 用户可以运行应用程序而不授予权限(不像安卓)。
- 在这个模型中,“普通”权限并不是很有意义。
- 苹果在其应用商店中批准应用程序,部分基于安全评估。
- “基于声誉”的系统:难以利用许多手机并避免被检测。