
-
利用内存完整性强制技术确保 App 安全
了解“内存完整性强制”(Memory Integrity Enforcement, MIE),这一新的安全技术能帮助硬件、操作系统和编译器协同工作,防止对无效内存的访问,从而在漏洞被利用之前安全地中止程序执行。了解 MIE 如何使攻击者更难利用内存损坏错误。了解如何在 App 中采用 MIE 来保护用户及其数据,同时根除代码库中难以发现的内存问题。
章节
- 0:05 - 简介
- 1:29 - 内存溢出和“释放后使用”漏洞
- 3:08 - 内存完整性强制
- 4:42 - 演示:内存损坏“释放后使用”错误
- 5:52 - 启用硬件内存标记
- 6:20 - 演示:硬件内存标记中断利用漏洞的尝试
- 6:44 - 其他配置选项
- 7:25 - 演示:修复内存损坏错误
- 9:32 - 其他注意事项
- 10:10 - 标记指针中的位
- 10:30 - 指针值的哈希处理、比较和算术运算
- 11:02 - 软模式
- 11:31 - 后续步骤
资源
- Enabling enhanced security for your app
- Memory Integrity Enforcement: A complete vision for memory safety in Apple devices
相关视频
WWDC15
-
搜索此视频…
大家好 我叫 Julian 是 Developer Security Tools 团队的一名工程师 在这个视频中 我将介绍 如何利用内存完整性强制技术 来确保你的 App 的安全 App 触及我们生活的方方面面 它们是人们信赖的工具 承载了大量个人生活的私密细节 包括地理位置和浏览历史记录、照片 信息、联系人、财务等众多信息 同时 App 会连接到互联网 因此其中的各种安全漏洞 可能致使用户受到攻击 针对个人的攻击可能造成严重后果 轻则遭遇诈骗、身份盗用 重则受到勒索甚至危及生命 人们期望自己的数据 获得隐私保护和安全保障 如果这一承诺未能兑现 便是对信任的辜负 安全性是保障隐私的技术基础 因此安全性对于通讯、社交媒体 和浏览器 App 尤为重要 这些 App 会处理大量不受信任输入 而且拥有广泛的用户基础 这为攻击者精准锁定受害者 提供了便利 常见的安全漏洞之一是内存损坏 攻击者可以利用内存缺陷 劫持 App 的控制权 并窃取用户的敏感数据 例如 缓冲区溢出损坏 会导致数据超出缓冲区边界 从而损坏其他分配区域的内存 当另一个指针读取这些损坏内存时 可能导致数据损坏 以及难以复现的崩溃 但更糟糕的是 攻击者可能会通过精心编写的内容 诱骗你的 App 执行 攻击者控制的任意代码 攻击者还可以利用 许多“释放后使用”错误 假设某个 App 释放了一块内存 却留下了一个指向这个块的悬垂指针 随后 App 又创建了新的分配区域 恰好位于内存中的同一位置 如果 App 通过悬垂指针 进行读取或写入操作 就会导致内存损坏
防止内存损坏的最佳方法 是使用 Swift 之类的内存安全语言 通过为你管理内存 安全语言可确保 编程错误不会导致内存损坏
但即使你用 Swift 编写所有新代码 App 可能仍包含现有代码库中 原有的一些 C 和 C++ 代码 或者它可能依赖于 用不具备内存安全性的语言 编写的外部库 内存完整性强制技术是一项新技术 它能极大增加 攻击者利用内存损坏漏洞的难度 这是内存安全领域的一项重大进步 使用这种技术 硬件、操作系统与编译器会协同工作 通过安全地中止程序执行 来阻止对无效内存的访问 首批支持这项技术的设备包括 iPhone 17、 iPhone Air、iPhone 17 Pro 和 iPhone Pro Max 在“资源”下方查看“为 App 启用增强安全功能”文档 了解支持这项技术的 其他 Apple 设备 这项技术的工作原理如下 在内存完整性强制技术中 系统分配器 会为每个堆分配区域分配一个标记 并将这个标记编码到返回的指针中 每次从内存中进行加载或存储操作时 硬件都会检查指针中的标记 是否与分配区域的标记匹配 例如 如果带标记 A 的指针 被用于读取或写入 同样标记为 A 的内存区域 则允许访问操作继续执行
但在“释放后使用”的场景中 悬垂的 A 指针将访问 标有不同标记的新分配区域 这属于标记不匹配 因此硬件会中止程序执行 从而阻止攻击者破坏内存 这种方法也能防范缓冲区溢出损坏 因为分配器会为相邻的分配区域 分配不同的标记 这是我的演示 App 其中包含一个内存损坏漏洞 注意 App 本身是使用 Swift 编写的 但它使用外部 C 语言库来解析图像 我怀疑这个库存在释放后使用错误 但并不清楚具体位置 我将运行 App
结果我收到了一条信息 我想看照片 于是轻点了信息
哎呀 发生了什么? 原来这张看似可爱小狗的照片 实际上是由恶意攻击者 精心制作并发送的图片 在后台 这张图片利用了 “释放后使用”错误 将我的私人消息发送到 互联网上的某个服务器上
这非常可怕 我在这里夸大了漏洞利用的视觉效果 实际上攻击者 通常会尽可能隐藏这类活动
在现实攻击中 用户可能是 在毫无察觉的情况下被窃取了数据 要在 Xcode 中使用 内存完整性强制技术保护你的 App 进入 App 目标的 Signing and Capabilities Editor 点按“Add Capability” 并选择“Enhanced Security”
这将启用多个强大的安全保护功能 包括硬件内存标记
在进行本地测试时 需检查是否禁用了内存标记的软模式 稍后我会进一步介绍软模式 我已启用硬件内存标记 并重新启动了 App 当我再次轻点这张恶意图片时
App 不再允许攻击者窃取信息 而是终止了运行 点按查看终止原因显示 App 因标签不匹配而中止执行
硬件内存标记 还有一些额外的配置选项 “Memory Tag Pure Data”选项可将 保护范围扩展到更广泛的分配区域 如果你的 App 使用了 解释器或即时编译器 请启用“Prevent Receiving Tagged Memory”选项 同时请确保已启用 Enhanced Security Type Allocator 它能有效防御 对于“释放后使用”错误的利用 并可与内存标记技术结合使用 提供最强的安全防护 最后是“Soft Mode”选项 用于验证 App 是否已准备好支持内存标记 在我的演示 App 中 攻击者已无法利用这个错误
但用户体验并不理想 为了防止 App 崩溃 我仍需修复底层内存损坏漏洞 Xcode 能帮助你在开发环境中 发现并修复这些漏洞 以避免影响 App 用户 进入 Scheme Editor 并启用 Diagnostics 面板中的 Hardware Memory Tagging 我已在 Scheme Editor 中启用了 硬件内存标记诊断并再次运行 App 当我再次轻点图片以触发漏洞时
App 会再次终止 但 Xcode 现提供了额外的诊断信息 来帮助我理解问题所在 首先 它指出标记不匹配是 由于使用了已释放的内存 即“释放后使用”错误
调试导航器显示一段有用的堆栈跟踪 明确指出内存被释放的位置
在本例中 这个位置位于 process_image_message 函数中
回到崩溃发生的位置 可以看到问题出在一个异步派发块中
好了 我现在明白问题所在了 主线程在后台线程有机会处理信息前 就释放了这条信息 为了解决这个问题 我将把信息的释放操作 从主线程
移到异步块末尾 确保它只在信息处理完后才会被释放
我将再次启动 App 以确认这次修改 已彻底修复了这个底层漏洞
再次轻点图片 是的 这次一切正常 App 收到了恶意图片 但攻击者无法用它劫持 App
接下来 我将介绍一些让 App 为内存完整性强制技术做好准备的 其他注意事项 现在应着手修复 App 正常运行期间 仍存在的任何缓冲区溢出 或“释放后使用”错误 你可在测试中启用硬件内存标记诊断 来发现并了解这些漏洞
这会将许多难以复现的内存损坏问题 变为可处理的崩溃 如果你没有 支持内存完整性强制技术的设备 可以使用 Address Sanitizer 作为替代方案 硬件内存标记通过将标记 存储在指针高位来保护分配区域 你需要确保 App 不会使用 或修改这些高位 若你的 App 使用自定标记指针方案 请调整以将这些信息存储在其他位置
在对指针进行哈希处理、比较 或算术运算时也需格外小心 启用内存标记后 指向不同 分配区域的指针会带有不同的标记 因此高位也会不同 请考虑这对指针值的哈希处理、比较 和算术运算可能造成的影响 应避免比较来自不同分配区域的指针 并在必要时屏蔽掉标记位
软模式可帮助你确认是否已发现 并修复了 App 中的内存损坏漏洞 它以模拟崩溃日志的形式 提供标记不匹配的遥测数据 而不会终止执行 在试运行版和面向客户的发布版本中 启用这个功能以确保不再存在 内存损坏漏洞 完成内存损坏漏洞的修复后 禁用软模式以保护用户 以下是后续步骤 如果你的 App 处理未经验证的输入 请采用内存完整性强制技术保护用户 它对于通讯、社交媒体 和浏览器 App 尤为重要 修复已知的内存损坏漏洞 准备好你的 App 确保你的 App 没有将指针的标记位 用于其他用途 在启用硬件内存标记诊断的条件下 测试 App 并使用软模式验证修复 然后禁用软模式以保护用户 感谢观看和采用内存完整性强制技术
-