跳过内容

MASTG-TEST-0223: 未启用栈保护

概述

此测试用例检查应用程序的 native 库在编译时是否未启用堆栈金丝雀,因此缺乏 堆栈粉碎保护,这是一种常见的缓冲区溢出攻击缓解技术。

  • NDK 库应启用堆栈金丝雀,因为 编译器默认会这样做
  • 其他自定义 C/C++ 库可能未启用堆栈金丝雀,因为它们缺少必要的编译器标志 (-fstack-protector-strong-fstack-protector-all),或者金丝雀已被编译器优化掉。 有关更多详细信息,请参阅评估部分。

步骤

  1. 提取应用内容( 探索应用程序包)。
  2. 在每个共享库上运行 获取编译器提供的安全特性,并 grep 搜索 “canary” 或所选工具使用的相应关键字。

观察

输出应显示是否启用或禁用堆栈金丝雀。

评估

如果禁用堆栈金丝雀,则测试用例失败。

开发人员需要确保所有 native 库的编译器标志中都设置了标志 -fstack-protector-strong-fstack-protector-all。 对于不属于 NDK 的自定义 C/C++ 库,这一点尤其重要。

在评估此项时,请注意可能存在预期内的误报,对于这些误报,测试用例应被视为通过。 为了确定这些情况,需要手动审查原始源代码和所使用的编译标志。

以下示例涵盖了一些可能遇到的误报情况

使用内存安全语言

Flutter 框架不使用堆栈金丝雀,因为 Dart 可以缓解缓冲区溢出

编译器优化

有时,由于库的大小和编译器应用的优化,库最初可能使用堆栈金丝雀编译,但它们已被优化掉。 例如,某些 react native 应用程序就是这种情况。 它们使用 -fstack-protector-strong 构建,但尝试在 .so 文件中搜索 stack_chk_fail 时,找不到它。

  • 空的 .so 文件:某些 .so 文件(例如 libruntimeexecutor.solibreact_render_debug.so)在发布版本中实际上是空的,因此不包含任何符号。 即使您尝试使用 -fstack-protector-all 进行构建,您仍然无法看到 stack_chk_fail 字符串,因为那里没有方法调用。
  • 缺少堆栈缓冲区调用:其他文件(例如 libreact_utils.solibreact_config.solibreact_debug.so)不为空并包含方法调用,但这些方法不包含堆栈缓冲区调用,因此其中没有 stack_chk_fail 字符串。

在这种情况下,React Native 开发人员声明他们不会添加 -fstack-protector-all,因为在他们看来,他们认为这样做会增加性能损失,而不会获得有效的安全收益