安全误报
简介
#我们偶尔会收到关于 Dart 和 Flutter 应用程序安全漏洞的错误报告,这些报告是由为其他类型的应用程序(例如,用 Java 或 C++ 编写的应用程序)构建的工具生成的。本文件提供有关我们认为不正确的报告的信息,并解释为什么这些担忧是错位的。
常见问题
#共享对象应使用强化函数
#共享对象没有任何强化函数。 强化函数提供针对 glibc 的常用不安全函数(如
strcpy
、gets
等)的缓冲区溢出检查。 使用编译器选项-D_FORTIFY_SOURCE=2
来强化函数。
当这指的是编译后的 Dart 代码(例如 Flutter 应用程序中的 libapp.so
文件)时,此建议是错误的,因为 Dart 代码不会直接调用 libc 函数;所有 Dart 代码都通过 Dart 标准库进行。
(一般来说,MobSF 在这里会产生误报,因为它会检查任何使用带有 _chk
后缀的函数的情况,但由于 Dart 完全不使用这些函数,因此它没有任何带有或不带有后缀的调用,因此 MobSF 将代码视为包含非强化调用。)
共享对象应使用 RELRO
#未在
libapp.so
二进制文件中找到 RELRO
Dart 完全不使用正常的过程链接表 (PLT) 或全局偏移表 (GOT) 机制,因此重定位只读 (RELRO) 技术对于 Dart 并没有多大意义。
Dart 的 GOT 等效项是池指针,它与 GOT 不同,位于随机位置,因此更难以利用。
原则上,在使用 Dart FFI 时,您可以创建易受攻击的代码,但是,假设它与本身正确使用 RELRO 的 C 代码一起使用,则正常使用 Dart FFI 也不会容易出现这些问题。
共享对象应使用堆栈金丝雀值
#未在
libapp.so
二进制文件中找到金丝雀
此共享对象没有向堆栈添加堆栈金丝雀值。 堆栈金丝雀用于检测和防止利用覆盖返回地址的漏洞。 使用选项 -fstack-protector-all 来启用堆栈金丝雀。
Dart 不生成堆栈金丝雀,因为与 C++ 不同,Dart 没有堆栈分配的数组(C/C++ 中堆栈粉碎的主要来源)。
在编写纯 Dart 代码(不使用 dart:ffi
)时,您已经拥有比任何 C++ 缓解措施都能提供的更强大的隔离保证,这仅仅是因为纯 Dart 代码是一种托管语言,其中不存在缓冲区溢出等问题。
原则上,在使用 Dart FFI 时,您可以创建易受攻击的代码,但是,假设它与本身正确使用堆栈金丝雀值的 C 代码一起使用,则正常使用 Dart FFI 也不会容易出现这些问题。
代码应避免使用 _sscanf
、_strlen
和 _fopen
API
#二进制文件可能包含以下不安全的 API:
_sscanf
、_strlen
、_fopen
。
报告这些问题的工具在其扫描中往往过于简单;例如,查找具有这些名称的自定义函数,并假设它们指的是标准库函数。Flutter 的许多第三方依赖项都具有触发这些检查的同名函数。某些情况可能是有效的担忧,但是由于误报数量众多,无法从这些工具的输出中判断。
代码应使用 calloc
(而不是 _malloc
)进行内存分配
#二进制文件可能使用
_malloc
函数而不是calloc
。
内存分配是一个细致的问题,必须在性能和对漏洞的弹性之间进行权衡。仅仅使用 malloc
并不能自动表明存在安全漏洞。虽然我们欢迎针对使用 calloc
更可取的情况的具体报告(见下文),但在实践中,统一将所有 malloc
调用替换为 calloc
将是不合适的。
iOS 二进制文件设置了 Runpath 搜索路径(@rpath
)
#二进制文件设置了 Runpath 搜索路径(
@rpath
)。 在某些情况下,攻击者可以滥用此功能来运行任意可执行文件以进行代码执行和权限提升。 删除编译器选项-rpath
以删除@rpath
。
构建应用程序时,Runpath 搜索路径指的是链接器搜索以查找应用程序使用的动态库 (dylib) 的路径。默认情况下,iOS 应用程序将其设置为 @executable_path/Frameworks
,这意味着链接器应在应用程序包内应用程序二进制文件相对于 Frameworks
目录中搜索 dylib。Flutter.framework
引擎(与大多数嵌入式框架或 dylib 一样)被正确复制到此目录中。应用程序运行时,它会加载库二进制文件。
Flutter 应用程序使用默认的 iOS 构建设置(LD_RUNPATH_SEARCH_PATHS=@executable_path/Frameworks
)。
涉及 @rpath
的漏洞不适用于移动设置,因为攻击者无权访问文件系统,无法随意替换这些框架。即使攻击者以某种方式 能够 用恶意框架替换框架,由于代码签名冲突,应用程序也会在启动时崩溃。
使用 PKCS5/PKCS7 填充的 CBC 漏洞
#我们收到一些模糊的报告,称某些 Flutter 包中存在“使用 PKCS5/PKCS7 填充的 CBC 漏洞”。
据我们所知,这是由 ExoPlayer 中的 HLS 实现(com.google.android.exoplayer2.source.hls.Aes128DataSource
类)触发的。HLS 是 Apple 的流媒体格式,它定义了必须用于 DRM 的加密类型;这并非漏洞,因为 DRM 不保护用户的机器或数据,而只是提供模糊处理以限制用户充分使用其软件和硬件的能力。
应用程序可以读取和写入外部存储
#应用程序可以读取/写入外部存储。任何应用程序都可以读取写入外部存储的数据。
与来自任何不受信任来源的数据一样,处理来自外部存储的数据时,应执行输入验证。 我们强烈建议您不要在动态加载之前将可执行文件或类文件存储在外部存储中。 如果您的应用程序确实从外部存储检索可执行文件,则应在动态加载之前对文件进行签名和加密验证。
我们收到报告称,某些漏洞扫描工具将图像选择器插件读取和写入外部存储的能力解释为威胁。
从本地存储读取图像是这些插件的目的;这并非漏洞。
应用程序使用 file.delete() 删除数据
#使用 file.delete 删除文件时,只会从文件系统表中删除对文件的引用。 文件仍然存在于磁盘上,直到其他数据覆盖它,使其容易被恢复。
某些漏洞扫描工具将相机插件在从设备相机录制数据后删除临时文件解释为安全漏洞。因为视频是由用户录制的,并存储在用户的硬件上,所以没有实际风险。
过时的担忧
#本节包含可能在较旧版本的 Dart 和 Flutter 中看到的有效消息,但在较新版本中不再应看到这些消息。如果您在旧版本的 Dart 或 Flutter 中看到这些消息,请升级到最新的稳定版本。如果您在当前稳定版本中看到这些消息,请报告它们(请参阅本文档末尾的部分)。
堆栈应设置其 NX 位
#共享对象未设置 NX 位。 NX 位通过将内存页面标记为不可执行来提供针对内存损坏漏洞利用的保护。 使用选项
--noexecstack
或-z noexecstack
将堆栈标记为不可执行。
(来自 MobSF 的消息具有误导性;它正在查找堆栈是否被标记为不可执行,而不是共享对象。)
在较旧版本的 Dart 和 Flutter 中,存在一个错误,即 ELF 生成器没有使用 ~X
权限发出 gnustack
段,但这现在已修复。
报告真实问题
#虽然自动化漏洞扫描工具会报告诸如上述示例之类的误报,但我们不能排除存在需要仔细关注的真实问题。如果您发现您认为是合法安全漏洞的问题,我们将非常感谢您报告它:
除非另有说明,否则本网站上的文档反映的是 Flutter 的最新稳定版本。页面最后更新于 2025-01-30。 查看源代码 或 报告问题。