MASTG-TEST-0223: 未启用栈保护
概述¶
此测试用例检查应用程序的 native 库在编译时是否未启用堆栈金丝雀,因此缺乏 堆栈粉碎保护,这是一种常见的缓冲区溢出攻击缓解技术。
- NDK 库应启用堆栈金丝雀,因为 编译器默认会这样做。
- 其他自定义 C/C++ 库可能未启用堆栈金丝雀,因为它们缺少必要的编译器标志 (
-fstack-protector-strong
或-fstack-protector-all
),或者金丝雀已被编译器优化掉。 有关更多详细信息,请参阅评估部分。
步骤¶
- 提取应用内容( 探索应用程序包)。
- 在每个共享库上运行 获取编译器提供的安全特性,并 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.so
或libreact_render_debug.so
)在发布版本中实际上是空的,因此不包含任何符号。 即使您尝试使用-fstack-protector-all
进行构建,您仍然无法看到stack_chk_fail
字符串,因为那里没有方法调用。 - 缺少堆栈缓冲区调用:其他文件(例如
libreact_utils.so
、libreact_config.so
和libreact_debug.so
)不为空并包含方法调用,但这些方法不包含堆栈缓冲区调用,因此其中没有stack_chk_fail
字符串。
在这种情况下,React Native 开发人员声明他们不会添加 -fstack-protector-all
,因为在他们看来,他们认为这样做会增加性能损失,而不会获得有效的安全收益。