Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 630972 - net-vpn/peervpn: root privilege escalation via "chown -R" in pkg_preinst
Summary: net-vpn/peervpn: root privilege escalation via "chown -R" in pkg_preinst
Status: RESOLVED FIXED
Alias: None
Product: Gentoo Security
Classification: Unclassified
Component: Auditing (show other bugs)
Hardware: All Linux
: Normal normal (vote)
Assignee: Gentoo Security
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-09-14 12:33 UTC by Michael Orlitzky
Modified: 2020-10-12 14:06 UTC (History)
3 users (show)

See Also:
Package list:
Runtime testing required: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Orlitzky gentoo-dev 2017-09-14 12:33:26 UTC
Sorry Zac =)

As part of the fix for another problem I reported, the ebuild for peervpn is now running "chown -R" on the live root filesystem in pkg_preinst:

      pkg_preinst() {
      ...
          chown -R root:${PN} "${EROOT}etc/${PN}" || die
          chmod -R g+rX-w,o-rwx "${EROOT}etc/${PN}" || die

The /etc/peervpn directory is expected to be owned by the "peervpn" user when this happens, and in that case, the "peervpn" user can exploit the "chown -R" to gain root. The call to chown will affect the target of a hard link, so the "peervpn" user can place a hard link in /etc/peervpn pointing to e.g. /etc/passwd, and the "chown -R" will give ownership of /etc/passwd to the "peervpn" user. In that manner he can gain control of any of root's files.

I believe you can make the "chown" call safe in this case by passing

  --from=peervpn:peervpn

That will prevent "chown" from operating on any new hard links that the peervpn user might throw in /etc/peervpn, since if he tried to point the link at a root-owned file, that hard link would be root:root instead of peervpn:peervpn.

The call to chmod has the same problem, but no "--from" flag. Instead, you should probably collect only those files under /etc/peervpn that are owned by root:peervpn at that point, and call chmod on those. For the call to chmod, you should ensure that the target is not a symlink.
Comment 1 Zac Medico gentoo-dev 2017-09-14 20:08:24 UTC
How about his:

pkg_preinst() {
    if ! has_version '>=net-vpn/peervpn-0.044-r5' && \
        [[ -d ${EROOT}etc/${PN} &&
        $(find "${EROOT}etc/peervpn" -user "${PN}" ! -type l -print) ]]; then
        ewarn "Tightening '${EROOT}etc/${PN}' permissions for bug 629418"
        while read -r -d ''; do
            chown root:${PN} "${REPLY}" || die
            chmod g+rX-w,o-rwx "${REPLY}" || die
        done < <(find "${EROOT}etc/peervpn" -user "${PN}" ! -type l -print0)
    fi
}
Comment 2 Michael Orlitzky gentoo-dev 2017-09-14 22:06:36 UTC
(In reply to Zac Medico from comment #1)
> How about his:

That's the idea, but there's a race condition you have to worry about. The first time around, "chown --from=..." is necessary because "find" might return a path that the "peervpn" user can overwrite before you have time to call chown on it.

I think chmod has the same issue, but once you've chown'ed everything (if you don't find any "peervpn"-owned paths), the chmods should be immune because he can't replace anything.
Comment 3 Zac Medico gentoo-dev 2017-09-14 23:15:11 UTC
How about this:

pkg_preinst() {
    if ! has_version '>=net-vpn/peervpn-0.044-r4' && \
        [[ -d ${EROOT}etc/${PN} && ! -L ${EROOT}etc/${PN} &&
        $(find "${EROOT}etc/${PN}" -maxdepth 1 \
        -user "${PN}" ! -type l -print) ]]; then
        ewarn "Tightening '${EROOT}etc/${PN}' permissions for bug 629418"
        # Tighten the parent directory permissions first, in
        # order to protect against race conditions involving a
        # less-privileged user.
        chown root:${PN} "${EROOT}etc/${PN}"
        chmod g+rX-w,o-rwx "${EROOT}etc/${PN}"
        # Don't chown/chmod the referent of a symlink
        # owned by a less-privileged user.
        while read -r -d ''; do
            chown root:${PN} "${REPLY}" || die
            chmod g+rX-w,o-rwx "${REPLY}" || die
        done < <(find "${EROOT}etc/${PN}" -mindepth 1 -maxdepth 1 \
            -user "${PN}" ! -type l -print0)
    fi
}
Comment 4 Michael Orlitzky gentoo-dev 2017-09-14 23:24:46 UTC
(In reply to Zac Medico from comment #3)
> How about this:

I think this one just might be safe; I can't figure out a way to trick it. The mindepth/maxdepth should ensure that you're only operating in /etc/${PN}, which you fix first...
Comment 5 Robin Johnson archtester Gentoo Infrastructure gentoo-dev Security 2020-04-03 23:16:36 UTC
Unrestricting and reassigning to security@ per bug #705894
Comment 6 Robin Johnson archtester Gentoo Infrastructure gentoo-dev Security 2020-04-03 23:18:33 UTC
unrestricting per bug 705894
Comment 7 Aaron Bauman Gentoo Infrastructure gentoo-dev Security 2020-05-04 00:38:59 UTC
(In reply to Zac Medico from comment #3)
> How about this:
> 
> pkg_preinst() {
>     if ! has_version '>=net-vpn/peervpn-0.044-r4' && \
>         [[ -d ${EROOT}etc/${PN} && ! -L ${EROOT}etc/${PN} &&
>         $(find "${EROOT}etc/${PN}" -maxdepth 1 \
>         -user "${PN}" ! -type l -print) ]]; then
>         ewarn "Tightening '${EROOT}etc/${PN}' permissions for bug 629418"
>         # Tighten the parent directory permissions first, in
>         # order to protect against race conditions involving a
>         # less-privileged user.
>         chown root:${PN} "${EROOT}etc/${PN}"
>         chmod g+rX-w,o-rwx "${EROOT}etc/${PN}"
>         # Don't chown/chmod the referent of a symlink
>         # owned by a less-privileged user.
>         while read -r -d ''; do
>             chown root:${PN} "${REPLY}" || die
>             chmod g+rX-w,o-rwx "${REPLY}" || die
>         done < <(find "${EROOT}etc/${PN}" -mindepth 1 -maxdepth 1 \
>             -user "${PN}" ! -type l -print0)
>     fi
> }

Zac, is this good now? I don't see the mindepth parts in the ebuild...
Comment 8 Larry the Git Cow gentoo-dev 2020-05-04 04:05:22 UTC
The bug has been referenced in the following commit(s):

https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=41725d13927f9012e1758ef662f3e5ba351423ac

commit 41725d13927f9012e1758ef662f3e5ba351423ac
Author:     Zac Medico <zmedico@gentoo.org>
AuthorDate: 2020-05-04 04:00:28 +0000
Commit:     Zac Medico <zmedico@gentoo.org>
CommitDate: 2020-05-04 04:02:01 +0000

    net-vpn/peervpn: 0.044-r5 revbump for bug 630972
    
    Tighten up permission adjustments related to bug 629418.
    
    Bug: https://bugs.gentoo.org/630972
    Package-Manager: Portage-2.3.99, Repoman-2.3.22
    Signed-off-by: Zac Medico <zmedico@gentoo.org>

 ...eervpn-0.044-r4.ebuild => peervpn-0.044-r5.ebuild} | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)
Comment 9 Zac Medico gentoo-dev 2020-05-04 04:08:03 UTC
0.044-r5 has the pkg_preinst shown in comment #3.
Comment 10 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2020-10-12 08:54:53 UTC
Removing it now.