Gentoo Archives: gentoo-hardened

From: Gavin <gavin@××××.com>
To: gentoo-hardened@l.g.o, "\\\"Martin Schlemmer\\\"" <azarah@g.o>, "\\\"Nicholas Jones\\\"" <carpaski@g.o>
Cc: golden_moon_rising@×××××.com
Subject: [gentoo-hardened] Hardening the Gentoo Portage Sandbox [rev 2 - edits re: glibc's use of weak aliases]
Date: Mon, 12 Apr 2004 17:46:52
Message-Id: 007901c420b6$153b48c0$0500a8c0@EPOX2
1 Greetings,
2
3 I found some weaknesses in the Gentoo Portage sandbox with consequences similar to the recent posting about the critical issue with Portage and /tmp. FYI, Chris posted an selinux one-liner solution =)
4
5 > create_dir_notdevfile(portage_t,{ file_type -user_tmp_t })
6 > Therefore, portage_t can modify all files, except those created by users, in /tmp.
7
8 Given this group's focus on hardening Gentoo, I am curious about your opinions regarding hardening of Portage. For example, given the options available with selinux and grsecurity patches, perhaps a more efficient alternative exists to using the sandbox as implemented by libsandbox.so and the sandbox binary in Portage? Also, if 1) Gentoo developers use the sandbox when testing, 2) the sandbox works flawlessly for all tested/installed packages, and 3) there were no sandbox violations, then how much practical value does an end user forfeit if they don't use the sandbox FEATURE, but continue using the userpriv FEATURE? Since a user's unique configuration might result in different code executed during installation, a user might benefit from using the sandbox, even if the developers/ebuild maintainers did not witness any sandbox violations, but, does this occur in practice?
9
10 I hope the discussion below about Portage is constructive, informative, and encouraging, without diminishing either the value and accomplishments of the Portage team or the relevance/importance of weaknesses (discussed below) to security-conscious Gentoo users and administrators. I have invested a great deal of effort in switching our software from Red Hat to Gentoo, and have a vested interest in improving the security of Gentoo.
11
12 I welcome all feedback.
13
14 Thanks,
15 Gavin
16
17
18 Abstract
19 =========
20 I reviewed some of Gentoo's sandbox code in preparation for integrating an enhanced compiler-caching technology derived from ccache. Although I personally believe the Portage sandbox is extremely helpful and useful, I found that the sandbox is not completely self-enforcing and relies on the cooperation of the installation code in source packages to maintain the integrity of the sandbox during an emerge.
21
22 Using the 'sandbox' FEATURE in /etc/make.conf without the FEATURES userpriv, and usersandbox (i.e. emerging a package as the root user) is not sufficient to prevent an ebuild from modifying sensitive files (e.g. /etc/passwd) outside the sandbox while performing an ebuild. Similarly, the use of all three FEATURES does not prevent an ebuild from writing to any file writable by the portage user (subject to security context limitations, etc. established by selinux/grsecurity/etc.).
23
24 Conclusion
25 ==========
26 1) The attached patch helps detect and prevent "accidental" breakage of the sandbox by "whitehat" package/ebuild authors.
27
28 2) Hardened Gentoo (either grsecurity or selinux) provides a kernel-based capability to enforcing the sandbox. After this article has been edited appropriately, perhaps the hardened team might want to contribute some advice?
29
30 3) I suggest either updating Portage to eliminate the documented weaknesses, or changing Portage documentation to reflect the weaknesses, documented below, contradicting documentation claims like, ".. as long as the package isn't installed on your system, the package cannot touch any file outside the sandbox." [http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=2&chap=3]
31
32 Personal Opinions
33 ================
34 I've found the sandbox an invaluable part of Gentoo and whole-heartedly recommend its continued use via FEATURES="sandbox userpriv usersandbox", but with an understanding for security-conscious administrators that emerge'ing packages poses more risks than implied by the documentation (e.g. "cannot touch any file outside the sandbox"). However, a virtual sandbox enforced by the kernel might provide an appealing alternative to reliance on the current pre-loaded library method.
35
36 I believe the Portage team has already created a "best in class" solution.
37
38
39 Weaknesses in Portage's Sandbox
40 ================================================
41 The following weaknesses allow for the possibility of a similar type of exploit as: http://bugs.gentoo.org/show_bug.cgi?id=21923
42
43 Essentially, a blackhat might be able to trick portage into installing some form of a rootkit that the root user eventually executes unknowingly. More specifically, a blackhat who is aware of the following weakness might be able to find an existing ebuild that scribbles outside the sandbox to some pre-determined location (e.g. /tmp), and then hardlink/symlink that location to somewhere else under their control, thus allowing them to insert code (i.e. a rootkit) during the emerge'ing of a package. Regardless, such writable, vulnerable locations are not supposed to exist at all on a secured/hardened system.
44
45 First, since the correct operation of the sandbox depends on the presence and definition of the LD_PRELOAD(7) and SANDBOX_* environment variables to enable the sandbox and control its functioning, package code executed during emerge can easily escape the sandbox by unsetting these variables (e.g. SANDBOX_ON), as libsandbox.so lacks enforcement (except for LD_PRELOAD with execve, which is practically useless if the SANDBOX_* variables have been unset).
46
47 Second, when the execve wrapper finds that libsandbox.so is not present in LD_PRELOAD, it appends this library, instead of pre-pending it, potentially allowing interception of further system calls by a library other than libsandbox.so(6). Example(8):
48
49 - - - b e g i n e x a m p l e m a k e f i l e - - -
50 export LD_PRELOAD=whitehat_lib.so
51
52 breaksandbox:
53 env /bin/echo 'misc. conf. stuff' > /etc/whitehat.conf
54 - - - e n d e x a m p l e m a k e f i l e - - -
55
56 Third, when using a version of libc (e.g. recent versions of glibc) that implements execv, execl, execlp, or execvp without calling execve, the execve wrapper code in libsandbox.c is bypassed(2) by some executables (e.g. GNU's make). Note that glibc's implementation of __execve defines a weak alias, "weak_alias (__execve, execve)". When we provide our own execve in libsandbox.so, glibc's execve is no longer "available for reference from other files" [http://gcc.gnu.org/onlinedocs/gccint/]. However, execl, execle, execv, and execvp (but not execlp which calls execvp) all call __execve (glibc's "true" execve). When libsandbox.c replaces execve, these other functions know nothing about the libsandbox.so execve, and continue using __execve. From a practical perspective, GNU's make uses execvp, while gcc's frontend uses both execv and execvp. In contrast, the exec family in uClibc is written using execvp and execve. Modifying libsandbox.c to wrap __execve might work with glibc, but not with uClibc, unless additional changes are made.
57
58 Consider that glibc's implementation of __execve defines a weak alias, "weak_alias (__execve, execve)", and implements execv as follows:
59
60 int execv (const char *path, char *const argv[])
61 { return __execve (path, argv, __environ); }
62
63 Thus, when libsandbox.so provides its own execve, execv continues to use glibc's __execve(). The attached patch adds support for wrapping execvp [the others are left as an "exercise" for the reader ;) ], factors functionality common to the execve and execvp wrappers, and ensures that libsandbox.so is listed first in LD_PRELOAD. As an example demonstrating the consequences of a missing wrapper for execvp in libsandbox.c, please consider a hypothetical Makefile in a package with a corresponding ebuild:
64
65 - - - b e g i n e x a m p l e m a k e f i l e - - -
66 export LD_PRELOAD=whitehat_lib.so
67
68 breaksandbox:
69 /bin/echo 'blackhat was here' > /etc/passwd
70 /bin/echo 'misc. conf. stuff' > /etc/whitehat.conf
71 env - ./scribble_anywhere_portage_user_can_scribble.sh
72 - - - e n d e x a m p l e m a k e f i l e - - -
73
74 The script "scribble_anywhere_portage_user_can_scribble.sh" runs as the portage user ('root', unless FEATURES="sandbox usersandbox userpriv ..." in /etc/make.conf).
75
76 The first and second rules for the breaksandbox(1) target above exploit the missing execvp wrapper weakness, while the third rule exploits the lack of enforcement of the sandbox due to missing "SANDBOX_*" environment variables. The second rule also highlights how easily a package author might accidentally break the sandbox.
77
78 Proposed Changes
79 =====================
80 The attached example patch(5) addresses the execvp weakness (the first of the two example rules above), and ensures that libsandbox.so is listed first in LD_PRELOAD.
81
82 The "env - script" weakness might be avoided by storing the data in the SANDBOX_* environment variables somewhere that the portage user lacks write access to. However, that would necessitate other changes totaling a non-trivial effort.
83
84 Although one might endeavor to enforce application of sandbox protections requested via the SANDBOX_* environment variables, other weaknesses in relying on the LD_PRELOAD tactic might ameliorate the value of such endeavors. Since the hardened Gentoo project team provides hardened solutions that specifically include the capability of isolating a user using ACLs enforced by the kernel, leveraging their work might prove more efficient in seeking a self-enforcing sandbox capable of preventing one emerge from affecting unrelated files owned by the portage user.
85
86 Notes
87 =======
88 1) The "breaksandbox" Makefile rule also breaks anything depending on other preloaded shared objects (via LD_PRELOAD), but the code in libsandbox.c was already broken anyway for IA32/gcc 3.3/glibc 2.3 combo with multiple shared objects in LD_PRELOAD [50-r3 just fixed that bug].
89
90 2) The execvp problem can be hidden in a "generation skip", where a process uses execvp (e.g. GNU make), but its child uses one of the exec's implemented by execve. In the latter case, the sandbox resumes functioning normally, even though the sandbox execve wrapper code was skipped by the parent using execvp. The use of the terms 'child' and 'parent' are inappropriate to examples where there was a pure exec without a fork, but this is already too wordy.
91
92 3) Unlike glibc, uClibc implements execvp using execve. I have not tried to determine whether versions of glibc older than glibc-2.3.3 implement execvp using execve.
93
94 4) Why hasn't this problem been noticed before? Perhaps it has, and I haven't heard. Also, see #2 above. Perhaps most programs that use execvp during an ebuild don't alter the environment (i.e. clean up the environment / alter LD_PRELOAD environment variable) before executing execvp? Perhaps the practical consequences are minimal. I'm not aware of any practical, already-existing examples exploiting these sandbox weaknesses.
95
96 5) The patch contains some code inappropriate for most any purpose other than testing/evaluating the sandbox system. However, it shouldn't require much effort to integrate and adapt the patch to one's own preferences and style. Also, some debugging statements left in the patch require /tmp/jlog to exist before emerg'ing and belong to the portage user and group. These debugging statements are left intentionally in the patch to highlight how much GNU's make uses execvp (see the log file /tmp/jlog after performing an emerge using a patched version of libsandbox using the supplied patch).
97
98 The list of SANDBOX_* environment variables checked by the patch for non-empty definitions should be tuned, and possibly extended to check for unreasonable combinations. Also what is reported and how needs "adjusting" to suit the typical Gentoo user. The patch also includes an experimental performance tweak for x86 architectures that is automatically selected if ARCH == 'x86'. The patch uses a different (experimental) method of wrapping execve and execvp using assembly. I've only tested the patch on a single system (x86, the latest version of almost everything). #include <std_disclaimer.txt>
99
100 6) Prior to 50-r3, this weakness was limited to special cases where an ebuild explicitly set 'LD_PRELOAD=/mylib.so /lib/libsandbox.so', since libsandbox.so was partly broken when using multiple libraries in LD_PRELOAD, at least for the current version of GNU's ld that requires spaces between libs(prior versions of libsandbox.c used a ':' instead of ' ' when appending). Thus, prior to 50-r3, 'export LD_PRELOAD=/mylib.so' resulted in something like 'LD_PRELOAD=/mylib.so:/lib/libsandbox.so', causing ld to report an error.
101
102 7) Actually, an LD_SO_PRELOAD option exists in sandbox.c that tries to enforce the preloading of libsandbox.so via /etc/ld.so.preload. However, if the sandbox executable is interrupted at an inopportune time, the contents of ld.so.preload could be corrupted. Also, negative consequences might arise for unrelated system processes that happen to start while the sandbox exists. Perhaps if ld.so were tweaked to provide for enforced, per-user versions of ld.so.preload ... Regardless, the portage ebuild states this approach has been deprecated, and it still doesn't prevent installation code from unsetting SANDBOX_ON.
103
104 8) If we append ' /lib/libsandbox.so' to the 'export LD_PRELOAD=whitehat_lib.so' in the first makefile example, the supplied patch does not check to make sure that libsandbox.so is listed first. I consider that a "todo" item.

Attachments

File name MIME type
portage-2.0.50-r3.GB.patch application/octet-stream