Bug 1155075 (CVE-2019-3691) - VUL-0: CVE-2019-3691: munge: LPE from munge to root
Summary: VUL-0: CVE-2019-3691: munge: LPE from munge to root
Status: RESOLVED FIXED
Alias: CVE-2019-3691
Product: SUSE Security Incidents
Classification: Novell Products
Component: Audits (show other bugs)
Version: unspecified
Hardware: Other Other
: P3 - Medium : Normal
Target Milestone: ---
Assignee: Egbert Eich
QA Contact: Security Team bot
URL: https://smash.suse.de/issue/245790/
Whiteboard: CVSSv2:NVD:CVE-2019-3691:7.2:(AV:L/AC...
Keywords:
Depends on:
Blocks: 1154062
  Show dependency treegraph
 
Reported: 2019-10-25 09:09 UTC by Johannes Segitz
Modified: 2020-05-12 18:42 UTC (History)
2 users (show)

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Johannes Segitz 2019-10-25 09:09:56 UTC
167 %post
168 if [ $1 -eq 1 ]
169 then
170     %{fixperm %{_localstatedir}/log/munge}
171     %{fixperm %{_localstatedir}/log/munge/munged.log}
172     %{fixperm %{_localstatedir}/run/munge}
173 fi
174 if [ ! -e %{_sysconfdir}/munge/munge.key -a -c /dev/urandom ]; then
175   /bin/dd if=/dev/urandom bs=1 count=1024 \
176     >%{_sysconfdir}/munge/munge.key 2>/dev/null
177 fi
178 /bin/chown %munge_u:%munge_g %{_sysconfdir}/munge/munge.key
179 /bin/chmod 0400 %{_sysconfdir}/munge/munge.key

allows LPE from munge to root. POC:
sh-5.0$ id
uid=464(munge) gid=463(munge) groups=463(munge)
sh-5.0$ pwd
/etc/munge
sh-5.0$ rm munge.key
sh-5.0$ ln -s /test/shadow munge.key

reinstall/update munge as root

sh-5.0$ ls -lah /test/
total 12K
drwxr-xr-x  2 root  root  4.0K Oct 25 11:01 .
drwxr-xr-x 23 root  root  4.0K Oct 25 11:01 ..
-r--------  1 munge munge 1.2K Oct 25 11:01 shadow


The fixperm calls in post/postun have similar issues
Comment 1 Egbert Eich 2019-10-25 10:25:04 UTC
So what's your suggestion to fix this?
Would a test for the file not being a symbolic link be sufficient?
Comment 2 Johannes Segitz 2019-10-25 10:53:23 UTC
(In reply to Egbert Eich from comment #1)
For the chown -R there's no easy way to fix it. I've been looking for supporting tools that could be used here, but without success so far. But since that requires fs.protected_hardlinks=0 (and we have it enabled by default) this is low priority ATM. 

For the munge.key issue: You could use runuser to create the file as the munge user. If you set the umask correctly you can remove the chown and chmod. It also prevents the attacker from racing with the if/dd construct and use it to overwrite arbitrary files
Comment 3 Johannes Segitz 2019-10-25 10:55:33 UTC
We'll track this via CVE-2019-3691. Can be made public as soon as we release an update
Comment 4 Egbert Eich 2019-10-25 11:56:41 UTC
(In reply to Johannes Segitz from comment #2)
> (In reply to Egbert Eich from comment #1)
> For the chown -R there's no easy way to fix it. I've been looking for
> supporting tools that could be used here, but without success so far. But
> since that requires fs.protected_hardlinks=0 (and we have it enabled by
> default) this is low priority ATM. 
> 
> For the munge.key issue: You could use runuser to create the file as the
> munge user. If you set the umask correctly you can remove the chown and
> chmod. It also prevents the attacker from racing with the if/dd construct
> and use it to overwrite arbitrary files

I'm using chown (and the fixperm macro) as well as chmod to fix the ownership in case it was set differently in an earlier installation. This cannot be handled by a mask.
Looking at chown, if the only concern is the fact that it is a link, we can use
chown -h to avoid that we follow the link. The only consequence would be that if the file existed and belonged to the attacker it no longer does - even if the file was set suid before, and the attacker would manage to execute it before the chown happens, the damage would be contained: the munge user/group cannot really do much.
Comment 5 Egbert Eich 2019-10-25 11:57:59 UTC
Actually, set NEEDINFO again - see previous comment.
Comment 6 Egbert Eich 2019-10-25 18:19:15 UTC
Is this better?

%define fixperm() [ -e %1 ] && /bin/chown -h %munge_u:%munge_g %1
[...]
unset tmpfile
if [ ! -e %{_sysconfdir}/munge/munge.key ]; then
  if [ -a -c /dev/urandom ]; then
      tmpfile=$(mktemp /tmp/tmpfile-XXXXXXX)
      /bin/dd if=/dev/urandom bs=1 count=1024 > $tmpfile 2>/dev/null
  fi
elif [ $(/usr/bin/stat -c %U:%G:%a %{_sysconfdir}/munge/munge.key) != \
    %munge_u:%munge_g:400 ]; then
    tmpfile=$(/usr/bin/mktemp /tmp/tmpfile-XXXXXXX)
    /usr/bin/cat %{_sysconfdir}/munge/munge.key > $tmpfile
fi
if [ -n "$tmpfile" ]; then
    /bin/chmod 0400 $tmpfile
    /bin/chown -h %munge_u:%munge_g $tmpfile
    /bin/mv $tmpfile %{_sysconfdir}/munge/munge.key
fi
Comment 7 Egbert Eich 2019-11-04 11:33:06 UTC
Further notes:
Here chown/chmod are not used recursively.
- To prevent chown from following links, one can use the -h option.
  This will mitigate your exploit example.
- umask is not really feasible as we also may have to fix up old
  ownerships
- the munge user is separate and has no root rights.

Create files in these locations requires much more rights than
one would be able to gain from becoming the munge user.
In your exploit example, one was the munge user already.
'Games' creating a suid file and having the installation chown
it to another user will not allow an exploit either: chown will
reset the suid bit.

So I believe, the proposed change addresses possible security concerns.
Comment 8 Johannes Segitz 2019-11-05 09:59:01 UTC
(In reply to Egbert Eich from comment #7)
Thank you for your work here and the detailed explanations. That's better, but with the usage of cat
elif [ $(/usr/bin/stat -c %U:%G:%a %{_sysconfdir}/munge/munge.key) != \
    %munge_u:%munge_g:400 ]; then
    tmpfile=$(/usr/bin/mktemp /tmp/tmpfile-XXXXXXX)
    /usr/bin/cat %{_sysconfdir}/munge/munge.key > $tmpfile
fi
if [ -n "$tmpfile" ]; then
    /bin/chmod 0400 $tmpfile
    /bin/chown -h %munge_u:%munge_g $tmpfile
    /bin/mv $tmpfile %{_sysconfdir}/munge/munge.key
fi

an attacker can read arbitrary files by symlinking to them. The symlink will yield
munge:munge:777
and therefor trigger the elif. cat reads the linked file and copies the content into $tmpfile, which is then transfered back

You could create a temp directory and then copy the file there without dereferencing symlinks
tmpdir=$(/usr/bin/mktemp -d /tmp/tmpfile-XXXXXXX)
cp -P /etc/munge/munge.key $tmpdir
now you have the file in a directory that root controls. Here you can test if it's a regular file and then act on it, since the attacker can't interfere anymore
Comment 9 Egbert Eich 2019-11-06 09:17:17 UTC
New proposal using a temporary directory instead of just a temporary file.

unset tmpfile
tmpdir=$(mktemp -d /tmp/tmpdir-XXXXXXXXX)
if [ -e %{_sysconfdir}/munge/munge.key ]; then
    # Preserve symlink so we can check for it                                                                     
    cp -pP %{_sysconfdir}/munge/munge.key ${tmpdir}
fi
# Make sure this is no symlinks - this may have been created by an attacker!                                      
if [ -e ${tmpdir}/munge.key -a ! -h ${tmpdir}/munge.key ]; then
    if [ $(/usr/bin/stat -c %U:%G:%a ${tmpdir}/munge.key) != \
    %munge_u:%munge_g:400 ]; then
        tmpfile=${tmpdir}/munge.key
    fi
else
    /usr/bin/rm -f ${tmpdir}/munge.key
    if [ -c /dev/urandom ]; then
        tmpfile=${tmpdir}/munge.key
        /bin/dd if=/dev/urandom bs=1 count=1024 > $tmpfile 2>/dev/null
    fi
fi
if [ -n "$tmpfile" ]; then
    /bin/chmod 0400 $tmpfile
    /bin/chown -h %munge_u:%munge_g $tmpfile
    /bin/mv $tmpfile %{_sysconfdir}/munge/munge.key
fi
/usr/bin/rm -rf ${tmpdir}
Comment 10 Johannes Segitz 2019-11-06 16:51:14 UTC
That looks good, but you need to add -f to the mv to handle the case where the file already exists. Can you please submit with this last change? 

Thank you!
Comment 11 Egbert Eich 2019-11-06 20:48:10 UTC
(In reply to Johannes Segitz from comment #10)
> That looks good, but you need to add -f to the mv to handle the case where

Indeed!

> the file already exists. Can you please submit with this last change? 
> 
> Thank you!

Done. SR#204600 and SR#204601.
Comment 14 Egbert Eich 2019-12-05 18:09:51 UTC
Submitted to Factory: SR ID #754486
Comment 15 Swamp Workflow Management 2019-12-05 18:40:05 UTC
This is an autogenerated message for OBS integration:
This bug (1155075) was mentioned in
https://build.opensuse.org/request/show/754491 Factory / munge
Comment 16 Swamp Workflow Management 2019-12-05 20:16:22 UTC
SUSE-SU-2019:3190-1: An update that fixes one vulnerability is now available.

Category: security (moderate)
Bug References: 1155075
CVE References: CVE-2019-3691
Sources used:
SUSE Linux Enterprise Module for Open Buildservice Development Tools 15-SP1 (src):    munge-0.5.13-4.3.1
SUSE Linux Enterprise Module for HPC 15-SP1 (src):    munge-0.5.13-4.3.1
SUSE Linux Enterprise Module for HPC 15 (src):    munge-0.5.13-4.3.1

NOTE: This line indicates an update has been released for the listed product(s). At times this might be only a partial fix. If you have questions please reach out to maintenance coordination.
Comment 17 Swamp Workflow Management 2019-12-11 14:22:52 UTC
openSUSE-SU-2019:2670-1: An update that fixes one vulnerability is now available.

Category: security (moderate)
Bug References: 1155075
CVE References: CVE-2019-3691
Sources used:
openSUSE Leap 15.1 (src):    munge-0.5.13-lp151.4.3.1
Comment 19 Swamp Workflow Management 2020-04-29 17:06:50 UTC
SUSE-SU-2020:1144-1: An update that solves one vulnerability and has one errata is now available.

Category: security (moderate)
Bug References: 1155075,1160075
CVE References: CVE-2019-3691
Sources used:
SUSE Linux Enterprise Module for HPC 12 (src):    munge-0.5.14-3.6.1

NOTE: This line indicates an update has been released for the listed product(s). At times this might be only a partial fix. If you have questions please reach out to maintenance coordination.