这是 libappimage 和 appimaged 的一个 PoC 漏洞利用。
通过组合利用这两个 CVE,可以创建一个看起来并非 AppImage 的文件,该文件既会被 appimaged 隐式拾取并安装,从而覆盖系统中已安装的同一应用程序版本。
在本例中,使用 MP3 文件作为载荷,被覆盖的应用程序是 Nautilus。
这会影响所有版本的 appimaged,以及所有早于 1.0.3 的 libappimage 版本。
MP3 编解码器没有文件头,因此媒体软件必须扫描整个文件以查找帧头。这意味着我们可以将 ELF 和 AppImage type 2 头放在文件开头,而 MP3 仍然可以播放。这使 MP3 成为此 PoC 的理想目标。
对一个 MP3 文件进行修改,使其在可播放的媒体数据之后包含一个载荷二进制文件,并使用 Dart 脚本将 MP3 数据放置在 载荷可执行文件与 ELF 头之间。(注意,我没有调整符号表中符号的位置,因为那需要更多工作量,而且这个 PoC 并不需要 这样做。)载荷二进制文件小于 1MB,因此不会导致文件大小明显增加。在文件的最末尾,追加了一个 squashfs 文件系统, 其中包含伪造的 Nautilus 桌面文件和图标。
请注意,虽然将 MP3 添加到 squashfs 的末尾在技术上也能行得通,但由于它出现在文件中如此靠后的位置,更容易让媒体 播放器产生混淆;而紧随 ELF 头之后的位置,距离文件开头只有几十个字节。
appimaged 会扫描所有受跟踪目录中的所有文件,无论文件扩展名如何。当它拾取到这个 MP3 时,会检测到 ELF 和 AppImage 头,并继续提取其中的桌面文件。
这个恶意桌面文件现在已被写入,并指向恶意的 MP3。当用户下次运行 Files 时,它启动的将是 MP3 内嵌的 ELF 可执行文件,而不是系统安装的版本。
通常情况下,桌面文件会被命名为 "appimagekit_...desktop",因此无法完全覆盖任何系统应用程序。然而,libappimage 中的 Integrator.cpp 会不加验证或转义地获取 Name 字段,因此我们可以在恶意桌面文件中加入:
Name=/../org.gnome.Nautilus
Name[en]=Files
该文件将被写入 ~/.local/share/applications/org.gnome.Nautilus.desktop,从而掩盖系统安装的 Nautilus。
请确保你安装的 libappimage 版本至少为 1.0.3,该版本修复了 Name 字段的验证问题。
值得注意的是,目前 Debian 的 libappimage 并不符合这一要求,其版本已经相当过时。
所有版本的 appimaged 都易受攻击,且该项目已被弃用。
go-appimage 通过只拾取名为
*.AppImage 的 AppImage 来避免文件名问题。AppImageLauncher 则通过在安装进行前询问用户是否允许安装来避免文件名问题。
将一个任意音频文件放入 audio.mp3,然后运行 dart bin/write_mp3.dart 来构建载荷并写入修改后的 MP3 文件。你需要安装 Dart SDK 和 FreePascal 才能使其正常工作。
该二进制文件之所以使用 Pascal 编写,是因为在使用子进程功能时,它在所测试的其他语言(使用 musl 静态链接的 C、Go)中生成的静态链接文件最小。
在测试中,使用了 world.execute(me) 作为音频文件,因为它看起来比较合适。