|
|
Message-ID: <20161012131247.GB14056@suse.de>
Date: Wed, 12 Oct 2016 15:12:47 +0200
From: Sebastian Krahmer <krahmer@...e.com>
To: oss-security@...ts.openwall.com
Subject: bubblewrap LPE
Hi
There is a beautiful, easy to exploit, logical bug within the
bubblewrap program, thats part of the flatpak container-app framework,
but also used with other container solutions.
/usr/bin/bwrap may be installed mode 04755 or with cap_sys_admin and other
file caps. I dont know if there are any dists already shipping it that way,
but the Makefile and some RedHat spec files contain file caps for it.
bubblewrap's aim is to setup a container and seccomp sandbox for programs to be run
as user.
For some reason it sets the PR_SET_DUMPABLE flag, as seen below. The comment about
it looks strange to me. If thats really true, suid programs shouldn't
be forced to play with the dumpable flag to achieve their goal.
Once the dumpable flag is set, there is a chance we could attach to the process,
once the remaining caps are dropped and the whole process runs as user.
Luckily, that happens at line 1707, right after a PrivSep socket has been opened!
Once attached to the (now running as unprived user) process, we can inject
commands into that socket. We could do arbitrary mounts, but won't achieve much, since
the bwrap process is running in its own mount namespace. However, there is
a sethostname() OP, that we can use to affect the hostname of the entire system
(not restricted to UTS namespace). Now, just wait for root or other users to
login and execute bash to use one of the PS expansion bugs to execute code.
(I wonder that has been re-discovered recently, it was already part of the
CVE-2011-0966 attack vector.)
383 acquire_caps (void)
384 {
[...]
422 /* We need the process to be dumpable, or we can't access /proc/self/uid_map */
423 if (prctl (PR_SET_DUMPABLE, 1, 0, 0, 0) < 0)
424 die_with_error ("prctl(PR_SET_DUMPABLE) failed");
425 }
[...]
1422 int
1423 main (int argc,
1424 char **argv)
1425 {
[...]
1440 /* Get the (optional) capabilities we need, drop root */
1441 acquire_caps ();
[...]
1692 if (is_privileged)
1693 {
1694 pid_t child;
1695 int privsep_sockets[2];
1696
1697 if (socketpair (AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, privsep_sockets) != 0)
1698 die_with_error ("Can't create privsep socket");
1699
1700 child = fork ();
1701 if (child == -1)
1702 die_with_error ("Can't fork unprivileged helper");
1703
1704 if (child == 0)
1705 {
1706 /* Unprivileged setup process */
1707 drop_caps (); // BOOM
1708 close (privsep_sockets[0]);
1709 setup_newroot (opt_unshare_pid, privsep_sockets[1]);
1710 exit (0);
1711 }
1712 else
1713 {
1714 uint32_t buffer[2048]; /* 8k, but is int32 to guarantee nice alignment */
1715 uint32_t op, flags;
1716 const char *arg1, *arg2;
1717 cleanup_fd int unpriv_socket = -1;
1718
1719 unpriv_socket = privsep_sockets[0];
1720 close (privsep_sockets[1]);
1721
1722 do
1723 {
1724 op = read_priv_sec_op (unpriv_socket, buffer, sizeof (buffer),
1725 &flags, &arg1, &arg2);
1726 privileged_op (-1, op, flags, arg1, arg2);
1727 if (write (unpriv_socket, buffer, 1) != 1)
1728 die ("Can't write to op_socket");
1729 }
1730 while (op != PRIV_SEP_OP_DONE);
1731
1732 /* Continue post setup */
1733 }
1734 }
-s
--
~ perl self.pl
~ $_='print"\$_=\47$_\47;eval"';eval
~ krahmer@...e.com - SuSE Security Team
Powered by blists - more mailing lists
Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.