(CVE-2024-6655) Library injection from CWD
Original reporter: Dimitrios Glynos
Area: Platform component (libraries, tools)
Message
GTK 3 blacklisted module loading from untrusted search path
The Issues
The GTK 3 library is vulnerable to two security issues that when combined, may enable a remote adversary to trick victim users into executing malicious code on their systems.
Please note that any references made to lines of code in this analysis, refer to the gtk+-3.24.42 and the glib-2.80.3 codebases.
GTK 3 applications typically invoke libgio's g_application_run() (see [1]) to handle command line arguments, start their event loop and deliver the "activate" signal to the program.
g_application_run() eventually calls libgtk's do_pre_parse_initialization() that populates the "gtk_modules_string" variable with GTK modules coming from the combination of environment variables GTK3_MODULES and GTK_MODULES.
Then, libgtk's do_post_parse_initialization() uses "gtk_modules_string" with _gtk_modules_init() to load the referenced GTK modules (which are shared libraries). This will eventually have load_module() load each module.
In load_module()'s implementation there is a blacklist for the GTK-2
"gail" and "atk-bridge" modules (see module_is_blacklisted()).
The blacklist is implemented by not invoking the "gtk_module_init"
function of the blacklisted modules. However, just before checking the
blacklist, each module (shared library) is loaded into memory by
find_module() in gtk/gtkmodule.c:292
. Clearly, this is not a true
blacklist as any library constructor in a blacklisted module will
execute just fine (Issue 1).
Let's imagine that for whatever reason the GTK_MODULES variable mentions
any of these two modules. GTK-3 will look in its standard modules
directory but will not be able to find these modules (because they are
GTK-2 modules). When it fails to do so, find_module() in gtk/gtkmodule.c:222
tries to find them in the current working directory. If the current working
directory is one that may contain potentially untrusted content
(like "~/Downloads" in drive-by-download attacks), this opens up
the possibility for a Shared Library Preloading attack (Issue 2).
Please note that in glibc's dlopen(3) implementation, simply providing the
filename of a library (without any path elements) does not by default load
the library from the current working directory (as other things
need also be tweaked like LD_LIBRARY_PATH etc.). glibc would have been
happy to do that if we had provided "./libfoo.so" (i.e. a relative path
with a slash character). This means that glib's find_module() call
to _g_module_open() in glib/module/gmodule.c:624
on such a glibc-based system
will always fail for a "libfoo.so" library. However, if find_module() can't
find the library itself on disk, it also searches for a similarly named
".la" file. Therefore, it is possible to craft this file (say "libfoo.la")
to point to a completely different library (say "libx.so") at so-called
libdir ".". The parsing mechanism for ".la" files will be happy to
synthesize the "./libx.so" path for us and this will eventually
be fed to dlopen(3) to load the "libx.so" module from the current working
directory.
Impact and Exploitation
The result of Issues 1 and 2 is that for example on Debian and Debian-derived distributions (such as Ubuntu) where package libatk-adaptor (a GNOME dependency) injects a GTK_MODULES="gail:atk-bridge" variable to the environment of GTK applications, it may be possible for a remote attacker to perform the shared library preloading attack to a victim's GTK-3 applications.
A simple exploitation scenario would have a Debian 12 user visit a malicious website and the website would auto-download malicious library artifacts to a local directory (say "Downloads"). Then, at a later time, when the user downloads an AppImage bundled software based on gtk-3 (e.g. https://inkscape.org/it/release/inkscape-1.2/gnulinux/appimage/) and makes the file executable, running the file through the file manager from the directory where it was downloaded would load the malicious gail (or atk-bridge) module and would thus execute malicious code.
Another simple exploitation scenario could have an Ubuntu 24.04 victim user execute a GTK-3 application through the terminal, in the directory where the malicious files were downloaded (e.g. "eog ." in "Downloads"). In Debian oldstable (11) it is even possible to trigger the malicious code by running "nautilus ." in the "Downloads" directory, as "nautilus" in oldstable is linked to GTK-3.
Notes on the attack surface
From a quick investigation, it seems this is exploitable on Debian and Debian-derived distributions where the GTK_MODULES environment variable references non-GTK-3 modules.
Debian oldstable (11) is more exposed to this than other distributions because it carries a GTK-3 based GNOME desktop (much like Ubuntu's focal 20.04LTS and jammy 22.04LTS). Debian stable (12) seems to be based on a GTK-4 built GNOME but also carries some GTK-3 applications, while Ubuntu nobble 24.04LTS and mantic 23.10 depend on even less GTK-3 applications.
Here is a list of applications that may fall victims to the attack on a default Debian stable (12) installation with a GNOME desktop:
- cheese, eog, evolution, file-roller, gcm-import, gcm-inspect, gcm-picker, gcm-viewer, gdm-screenshot, gkbd-keyboard-display, gnome-disk-image-mounter, gnome-disks, gnome-help, gnome-shell, gnome-system-monitor, gnome-terminal, gtk-builder-tool, gtk-launch, gtk-query-settings, nm-applet, nm-connection-editor, rhythmbox, seahorse, shotwell, simple-scan, totem, transmission-gtk, xdg-user-dirs-gtk-update, yelp, zenity, synaptic
Many other packages, that are not on the default installation, like "keepassxc" are also based on GTK-3.
Also, the official upstream releases of many popular software projects (like Firefox [2], Chrome [3] and VMWare Workstation [4]) are GTK-3 applications.
The effects are eliminated if a GTK-3 application runs through the "snap" sandbox (like the Firefox shipped on Ubuntu 24.04) or when the application has "apparmor" rules that deny the loading of libraries (as is the case with "evince" in all of the aforementioned distributions).
I haven't looked into how GTK-3 is used in other operating systems, as I believe the above mentioned use warrants a security hotfix.
Reproduction Steps
Let's create two files to direct execution to a malicious libfoo.so library.
The contents of the first file "libatk-bridge.so.la" follow (I've copied this from libtiff):
-----------------------------------------------------------------------------
# libtiff.la - a libtool library file
# Generated by libtool (GNU libtool) 2.4.2
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname='libfoo.so'
# Names of this library.
library_names='libtiff.so.4.3.6 libtiff.so.4 libtiff.so'
# The name of the static archive.
old_library='libtiff.a'
# Linker flags that can not go in dependency_libs.
inherited_linker_flags=''
# Libraries that this one depends upon.
dependency_libs=''
# Names of additional weak libraries provided by this library
weak_library_names=''
# Version information for libtiff.
current=7
age=3
revision=6
# Is this an already installed library?
installed=yes
# Should we warn about portability when linking against -modules?
shouldnotlink=no
# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''
# Directory that this library needs to be installed in:
libdir='.'
The second file will be the basis of our malicious library (foo.c):
/* Compile this with gcc -shared -fPIC -o libfoo.so foo.c */
#include
static void woot(void) __attribute__((constructor));
static void woot(void) {
fprintf(stderr, "HELLO!n");
}
Place both libfoo.so and libatk-bridge.so.la in a directory.
Within that directory, try to start firefox on a Debian stable (12) system and you should see a HELLO! message printed to standard error.
$ cd directory
$ ls
libatk-bridge.so.la libfoo.so
$ firefox
HELLO!
Gtk-Message: 16:13:05.585: Not loading module "atk-bridge": The functionality
is provided by GTK natively. Please try to not load it.
Mitigation Steps
It is strongly advised, to not use find_module() to load GTK modules if their name has been found to be blacklisted. More importantly, it is advised to not include the current working directory in the GTK module search path (i.e. remove the mechanism of calling g_module_build_path() with a NULL first argument in gtk/gtkmodules.c:217), as this opens the door for shared library preloading attacks (similar to the "DLL preloading" attacks in the Windows world [5]).
Contact & Next Steps
I remain available for any further information you might require on the matter. The last section of this report has a PGP key you can use with my email address (dglynos.pub@gmail.com).
I am happy to obtain CVE(s) for this, evaluate any fix proposed and conform to an embargo period for downstream vendors to push fixes. I typically work with a 90-days notice period before (advisory) disclosure but if the stakeholders require more time we can discuss this.
Thank you for your amazing work on gtk.
References
[1] https://www.gtk.org/docs/getting-started/hello-world [2] https://download.mozilla.org/?product=firefox-latest-ssl&os=linux64&lang=en-US [3] https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb [4] https://www.vmware.com/products/desktop-hypervisor.html.html.html [5] https://support.microsoft.com/en-us/topic/secure-loading-of-libraries-to-prevent-dll-preloading-attacks-d41303ec-0748-9211-f317-2edc819682e1
PGP Key
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
=ultC
-----END PGP PUBLIC KEY BLOCK-----