Ebuilds do a lot of unsafe things in the src_* phases. In particular, they call chown/chmod via fowners/fperms on paths that may be user-controlled, and they install files (as root) from user-controlled paths. The ebuild author may not even be aware that these paths are user-controlled; many build systems set weird permissions on paths like /usr or /var (in $D) that are then ignored by src_install(), which ultimately has no visible effect on the live filesystem. For an example of the latter situation, consider the still-unfixed CVE-2017-14312. A natural solution to that problem is to call "fowners" on the executables, to make them root:root again. But doing so leaves a substantial about of time where those executables are writable by the unprivileged user. Which brings me to the point of this bug report: the temporary location that portage uses for its installation image is predictable, and it's fairly easy for a long-running unprivileged daemon to gain root by messing with /var/tmp/portage/<predictable-path>. For a proof of concept, I can use my own nagios-core package. First we modify the ebuild to make it easy to exploit interactively, emake DESTDIR="${D}" install-basic + echo "${D}/usr/$(get_libdir)/nagios/plugins vulnerable, sleeping..." + sleep 15 + echo "Fixing ownership on ${D}/usr/$(get_libdir)/nagios/plugins." fowners root:root /usr/$(get_libdir)/nagios/plugins and then during that sleep interval, $ sudo su -s /bin/sh nagios -c 'touch /var/tmp/portage/net-analyzer/nagios-core-4.4.4/image/usr/lib64/nagios/plugins/exploit.txt' This leads to the exploit.txt being installed to a root-owned location: ... >>> /usr/lib64/nagios/cgi-bin/tac.cgi >>> /usr/lib64/nagios/cgi-bin/extinfo.cgi >>> /usr/lib64/nagios/cgi-bin/config.cgi --- /usr/lib64/nagios/plugins/ >>> /usr/lib64/nagios/plugins/exploit.txt This is a mild example, but is still pretty bad because that plugin directory is akin to /usr/bin for nagios users. If I made exploit.txt look legitimate and executable, root could conceivably run it. With some imagination, you can trick many ebuilds (especially with fowners) into giving you root directly. Ultimately this is the fault of the ebuild: developers should know that when they're manipulating the installation image, they're doing it as root, and that all of the usual precautions apply. But, it's naive to rely on hundreds of developers to be so meticulous. It's also impractical: to fix the proof-of-concept above, I have to reimplement the "make install" command that installs the plugins, and I don't want to do that. Portage is in a position to mitigate this entire class of vulnerabilities by e.g. making the temporary location unpredictable.
Using an entirely unpredictable location would be problematic for current behavior of the ebuild(1) command since it can be invoked multiple times with the intention of operating on a predictable location. How about if we set secure permissions on the parent directory? We've already got a secure default PORTAGE_WORKDIR_MODE="0700" setting that applies to ${WORKDIR}, and we could apply it to the parent directory.
(In reply to Zac Medico from comment #1) > > How about if we set secure permissions on the parent directory? We've > already got a secure default PORTAGE_WORKDIR_MODE="0700" setting that > applies to ${WORKDIR}, and we could apply it to the parent directory. I think that should work too.
Couldn't the permissions of /var/tmp/portage simply be changed to deny all access to 'other' (chmod o-rwx)? This would deny access of arbitrary accounts to anything inside /var/tmp/portage. The would limit access to the portage user and the portage group, which is generally much more tightly controlled and 'trusted'.
(In reply to Daniel Robbins from comment #3) > Couldn't the permissions of /var/tmp/portage simply be changed to deny all > access to 'other' (chmod o-rwx)? This would deny access of arbitrary > accounts to anything inside /var/tmp/portage. > > The would limit access to the portage user and the portage group, which is > generally much more tightly controlled and 'trusted'. Sure, that will give similar protection to the PORTAGE_WORKDIR_MODE approach from comment #1. I can't think of a reason not to apply PORTAGE_WORKDIR_MODE to PORTAGE_TMPDIR.
(In reply to Zac Medico from comment #4) > (In reply to Daniel Robbins from comment #3) > > Couldn't the permissions of /var/tmp/portage simply be changed to deny all > > access to 'other' (chmod o-rwx)? This would deny access of arbitrary > > accounts to anything inside /var/tmp/portage. > > > > The would limit access to the portage user and the portage group, which is > > generally much more tightly controlled and 'trusted'. > > Sure, that will give similar protection to the PORTAGE_WORKDIR_MODE approach > from comment #1. I can't think of a reason not to apply PORTAGE_WORKDIR_MODE > to PORTAGE_TMPDIR. Actually, the default PORTAGE_WORKDIR_MODE="0700" setting is a little too restrictive for PORTAGE_TMPDIR, since normally this directory is writable by trusted users in the portage group. This patch will apply PORTAGE_WORKDIR_MODE to the PORTAGE_BUILDDIR parent directory, as suggested in comment #1: https://archives.gentoo.org/gentoo-portage-dev/message/4aed84c475a00594be4d53ef94643220 https://github.com/gentoo/portage/pull/533
The bug has been referenced in the following commit(s): https://gitweb.gentoo.org/proj/portage.git/commit/?id=ef8c21e59953aa5fdd153f19b7bf04356e2164fe commit ef8c21e59953aa5fdd153f19b7bf04356e2164fe Author: Zac Medico <zmedico@gentoo.org> AuthorDate: 2020-03-15 00:01:25 +0000 Commit: Zac Medico <zmedico@gentoo.org> CommitDate: 2020-03-15 00:42:43 +0000 _prepare_workdir: apply PORTAGE_WORKDIR_MODE to PORTAGE_BUILDDIR (bug 692492) Apply secure PORTAGE_WORKDIR_MODE permissions to PORTAGE_BUILDDIR, since the child directory ${D} and its children may have vulnerable permissions as reported in bug 692492. Bug: https://bugs.gentoo.org/692492 Signed-off-by: Zac Medico <zmedico@gentoo.org> lib/portage/package/ebuild/prepare_build_dirs.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-)
The bug has been referenced in the following commit(s): https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=729dc030f6b318f84ca6336c7bd7dddaa7e48040 commit 729dc030f6b318f84ca6336c7bd7dddaa7e48040 Author: Zac Medico <zmedico@gentoo.org> AuthorDate: 2020-03-15 01:23:23 +0000 Commit: Zac Medico <zmedico@gentoo.org> CommitDate: 2020-03-15 01:29:25 +0000 sys-apps/portage: Bump to version 2.3.94 #692492 secure ebuild ${D} permissions #710444 omit zstd --long=31 for decompress on 32-bit arch #712298 respect emerge --deep=<depth> with --update Bug: https://bugs.gentoo.org/711148 Bug: https://bugs.gentoo.org/692492 Bug: https://bugs.gentoo.org/710444 Bug: https://bugs.gentoo.org/712298 Package-Manager: Portage-2.3.94, Repoman-2.3.20 Signed-off-by: Zac Medico <zmedico@gentoo.org> sys-apps/portage/Manifest | 1 + sys-apps/portage/portage-2.3.94.ebuild | 271 +++++++++++++++++++++++++++++++++ 2 files changed, 272 insertions(+)
The bug has been referenced in the following commit(s): https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=7f03ec4a46055a75eb13bf5fad85cf451822f589 commit 7f03ec4a46055a75eb13bf5fad85cf451822f589 Author: Zac Medico <zmedico@gentoo.org> AuthorDate: 2020-05-25 00:43:07 +0000 Commit: Zac Medico <zmedico@gentoo.org> CommitDate: 2020-05-25 00:43:23 +0000 sys-apps/portage: Remove vulnerable 2.3.89-r3 for bug 692492 Bug: https://bugs.gentoo.org/692492 Package-Manager: Portage-2.3.100, Repoman-2.3.22 Signed-off-by: Zac Medico <zmedico@gentoo.org> sys-apps/portage/Manifest | 1 - sys-apps/portage/portage-2.3.89-r3.ebuild | 271 ------------------------------ 2 files changed, 272 deletions(-)