Bug 1023041 - (CVE-2017-2616) VUL-0: CVE-2017-2616: util-linux, coreutils: su PAM local SIGKILL DoS
(CVE-2017-2616)
VUL-0: CVE-2017-2616: util-linux, coreutils: su PAM local SIGKILL DoS
Status: RESOLVED FIXED
Classification: Novell Products
Product: SUSE Security Incidents
Classification: Novell Products
Component: Incidents
unspecified
Other Other
: P3 - Medium : Major
: ---
Assigned To: Security Team bot
Security Team bot
https://smash.suse.de/issue/179681/
CVSSv2:NVD:CVE-2017-2616:4.7:(AV:L/AC...
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2017-02-01 15:15 UTC by Stanislav Brabec
Modified: 2020-06-30 07:39 UTC (History)
14 users (show)

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


Attachments
Proposed patch for coreutils-8.12 from SLE11SP2 (3.22 KB, text/plain)
2018-02-28 10:36 UTC, Raymund Will
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Stanislav Brabec 2017-02-01 15:15:20 UTC
I just got a mail from Karel Žák, upstream maintainer of util-linux:

From: Karel Zak <kzak@redhat.com>
To: Werner Fink <werner@suse.de>, Andreas Henriksson <andreas@fatal.se>,
	Stanislav Brabec <sbrabec@suse.cz>,
	Mike Frysinger <vapier@gentoo.org>,
	Bruce Dubbs <bruce.dubbs@gmail.com>, secalert@redhat.com
Subject: su(1) security issue

Hi guys,
 
 (downstream maintainers and RH security guys),

 Tobias Stöckmann <tobias@stoeckmann.org> found a nice su(1) bug, see
 his description:

        If su is compiled with PAM support, it is possible for any local user
        to send SIGKILL to other processes with root privileges. There are
        only two conditions. First, the user must be able to perform su with
        a successful login. This does NOT have to be the root user, even using
        su with the same id is enough, e.g. "su $(whoami)". Second, SIGKILL
        can only be sent to processes which were executed after the su process.
        It is not possible to send SIGKILL to processes which were already
        running. I consider this as a security vulnerability, because I was
        able to write a proof of concept which unlocked a screen saver of
        another user this way.

The complete original report is bellow.

The bugfix patch is already committed to the upstream repository:
https://github.com/karelzak/util-linux/commit/dffab154d29a288aa171ff50263ecc8f2e14a891

(the commit message is without any details...)


Please, downstream maintainers don't share the information about this
issue publicly. It would be better to do it by security community, but
I still think that downstream should be informed now.

IMHO affected are also old distros with su(1) from corecutils.

    Karel

********* *BEGIN OF SIGNED MESSAGE* *********

Hello Karel,
hello Serge,

I have discovered a security issue in su. Independently, the same bug
exists in shadow as well as util-linux. Therefore, I have written this
mail to both maintainers (which explains why you got it  ). I would
prefer a coordinated release of this, including the involvement of
distro-watch etc. This mail went to:

Karel Zak <kzak@redhat.com>
PGP: B0C64D14301CC6EFAEDF60E4E4B71D5EEC39C284

and

Serge Hallyn <serge.hallyn@ubuntu.com>
PGP: F1D08DB778185BF784002DFFE9FEEA06A85E3F9D

As both of you are involved with Linux distributions and the whole
procedure of security release, I hope you can help me with doing this.

SUMMARY
=======

If su is compiled with PAM support, it is possible for any local user
to send SIGKILL to other processes with root privileges. There are
only two conditions. First, the user must be able to perform su with
a successful login. This does NOT have to be the root user, even using
su with the same id is enough, e.g. "su $(whoami)". Second, SIGKILL
can only be sent to processes which were executed after the su process.
It is not possible to send SIGKILL to processes which were already
running. I consider this as a security vulnerability, because I was
able to write a proof of concept which unlocked a screen saver of
another user this way.

DETAILS
=======

When su started a shell or another program with the permissions of the
target user, it performs waitpid() on the child's process id. While it
waits, it also accepts signals, e.g. SIGTERM, which would merely set a
flag called caught/caught_signal (this depends on the project).

The problem arises when the child successfully finishes. On Unix
systems, child processes turn into zombies until the parent process
called wait() or waitpid(). As long as the zombie exists, the process
id cannot be given to a new process.

But su contains some logic to kill a child process when it received a
signal on its own, e.g. SIGTERM. As such a signal can be received at
any given time, it is possible to send such a signal _after_ waitpid()
finished successfully. This in turn means that su will send SIGKILL to
any kind of process that happens to have the same id as the child had
before.

It sounds like a very racy thing to do, but the attacker has multiple
advantages. First, he can decide when to stop the child, as it is under
his own control. Second, su can be suspended by SIGSTOP, which the
attacker can send to the su process due the ownership (it's setuid).
Third, the attacker knows exactly which pid will be killed, because the
information can be easily retrieved while the child process is running.

A successfully suspended su is therefore a loaded gun which is about to
be triggered the moment su receives the SIGCONT signal...

If the system does not offer process id randomisation, it is rather
easy to fast-forward by constantly calling fork() and kill() until
the very next fork call will yield the desired pid. Also, it is possible
to keep multiple su processes ready in the background, so an attacker
could have a small repertoire of killers around, when it's time to
fire...

SOLUTION
========

I have inlined patches which fix the issue at the end. Which one depends
on the project you maintain (otherwise the mail is identical for you
two).

The fix is rather "simple", but I really really hope that you both
take a very close look at them. What we have to do is to make sure
that if waitpid() finished successfully, the child mustn't receive any
more signals, because it's already gone.

In the case of shadow, it takes a critical section to prevent SIGALRM
from sending a signal to the child while we reset the child_pid.

PROOF OF CONCEPT
================

I used this code to loop around the process id list:

-------------------------getpid.c---------------------------------------
#include <sys/types.h>
#include <sys/wait.h>

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int argc, char *argv[])
{
	pid_t cpid, pid;
	int wstatus;

	if (argc < 2) {
		fprintf(stderr, "usage: getpid pid\n");
		return 1;
	}

	pid = atoi(argv[1]);
	if (pid < 1) {
		fprintf(stderr, "pid is invalid: %s\n", pid);
		return 1;
	}

try_again:
	cpid = fork();
	switch (cpid) {
	case -1:
		fprintf(stderr, "unable to fork\n");
		return 1;
	case 0:
		execl("/bin/sleep", "sleep", "500000", NULL);
		_exit(1);
	default:
		if (cpid == pid) {
			printf("got pid %ld\n", (long) pid);
			while (waitpid(pid, &wstatus, 0) < 0) {
				if (errno == EINTR)
					continue;
				fprintf(stderr, "waitpid failed\n");
				return 1;
			}
			printf("child exited\n");
		} else {
			kill(cpid, SIGTERM);
			waitpid(cpid, &wstatus, 0);
			goto try_again;
		}
		break;
	}

	return 0;
}
-------------------------getpid.c---------------------------------------

Otherwise I was too lazy to automate the password handling in su, so
instead I've inserted a delay after waitpid, which gave me enough time
to prepare a process of another user which I wanted to kill. In my
example, I did:

userA                           | userB
--------------------------------+-------------------
$ su -c 'echo $$' userA         |
Password:                       |
21540                           |
pretend suspend, press enter... |
                                | $ ./getpid 21540
                                | got pid 21540
### enter pressed ###           |
                                | child exited
$ _                             | $ _

NEED HELP?
==========

In case you have further questions, don't hesitate to ask me. If it's
about coordinating all this, I would prefer a CC so everyone stays
updated.


With kind regards,

Tobias

PS: My PGP fingerprint is CDB24BD3BDDCBCBBAE5CB6207DB470F35B0B8B18


diff --git a/login-utils/su-common.c b/login-utils/su-common.c
index 5aefd3fff..f9a749fc3 100644
--- a/login-utils/su-common.c
+++ b/login-utils/su-common.c
@@ -368,6 +368,7 @@ create_watching_parent (void)
             }
           else
             status = WEXITSTATUS (status);
+          child = -1;
         }
       else if (caught_signal)
         status = caught_signal + 128;
@@ -377,7 +378,7 @@ create_watching_parent (void)
   else
     status = 1;

-  if (caught_signal)
+  if (caught_signal && child != -1)
     {
       fprintf (stderr, _("\nSession terminated, killing shell..."));
       kill (child, SIGTERM);
@@ -387,9 +388,12 @@ create_watching_parent (void)

   if (caught_signal)
     {
-      sleep (2);
-      kill (child, SIGKILL);
-      fprintf (stderr, _(" ...killed.\n"));
+      if (child != -1)
+        {
+          sleep (2);
+          kill (child, SIGKILL);
+          fprintf (stderr, _(" ...killed.\n"));
+        }

       /* Let's terminate itself with the received signal.
        *


********* *END OF SIGNED MESSAGE* *********

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com
Comment 4 Stanislav Brabec 2017-02-02 15:31:35 UTC
Attaching further discussion. Please let me know, whether one week is sufficient for CRD.

From my side (backport of fixes in util-linux to SLE12 *), I can submit fixes just now.

The rest depends on QA and coreutils backport.


Date: Thu, 2 Feb 2017 04:52:12 -0500
From: Red Hat Product Security <secalert@redhat.com>
Subject: [engineering.redhat.com #436002] su(1) security issue
To: kzak@redhat.com
CC: andreas@fatal.se, bruce.dubbs@gmail.com, sbrabec@suse.cz,
        vapier@gentoo.org, werner@suse.de

... skipping citation ...

Hello Karel,

Thank you for reporting this issue. Any idea on public disclosure date? Also do
you need CVE or have you already requested one?

Best Regards,

--
Adam Mariš / Red Hat Product Security


Date: Thu, 2 Feb 2017 12:01:42 +0100
From: Karel Zak <kzak@redhat.com>
To: Red Hat Product Security <secalert@redhat.com>
Cc: andreas@fatal.se, bruce.dubbs@gmail.com, sbrabec@suse.cz,
        vapier@gentoo.org, werner@suse.de
Subject: Re: [engineering.redhat.com #436002] su(1) security issue

On Thu, Feb 02, 2017 at 04:52:12AM -0500, Red Hat Product Security wrote:
> Thank you for reporting this issue. Any idea on public disclosure date? 

I have bugfix, so it's all about time we all need to prepare
erratas/updates packages. IMHO one week should be enough (if we really
need embargo...)

> Also do you need CVE or have you already requested one?

I do not need CVE for anything, it's your playground guys 

There is Suse bug report about it:
    http://bugzilla.suse.com/show_bug.cgi?id=1023041

I have no feedback from another distros yet (but they are in CC:)

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com


Date: Thu, 2 Feb 2017 10:09:44 -0500
From: Red Hat Product Security <secalert@redhat.com>
To: kzak@redhat.com
CC: andreas@fatal.se, bruce.dubbs@gmail.com, sbrabec@suse.cz,
        vapier@gentoo.org, werner@suse.de

On Thu Feb 02 12:01:48 2017, kzak@redhat.com wrote:
> On Thu, Feb 02, 2017 at 04:52:12AM -0500, Red Hat Product Security wrote:
>> Thank you for reporting this issue. Any idea on public disclosure date?
>
> I have bugfix, so it's all about time we all need to prepare
> erratas/updates packages. IMHO one week should be enough (if we really
> need embargo...)
>
>> Also do you need CVE or have you already requested one?
>
> I do not need CVE for anything, it's your playground guys 

Well then please use CVE-2017-2616 for this issue.

Best Regards,

--
Adam Mariš / Red Hat Product Security
Comment 11 Swamp Workflow Management 2017-02-23 11:10:19 UTC
SUSE-SU-2017:0553-1: An update that solves two vulnerabilities and has 11 fixes is now available.

Category: security (important)
Bug References: 1008965,1012504,1012632,1019332,1020077,1023041,947494,966891,978993,982331,983164,987176,988361
CVE References: CVE-2016-5011,CVE-2017-2616
Sources used:
SUSE Linux Enterprise Server for SAP 12 (src):    python-libmount-2.25-24.10.3, util-linux-2.25-24.10.1, util-linux-systemd-2.25-24.10.1
SUSE Linux Enterprise Server 12-LTSS (src):    python-libmount-2.25-24.10.3, util-linux-2.25-24.10.1, util-linux-systemd-2.25-24.10.1
Comment 12 Swamp Workflow Management 2017-02-23 11:13:24 UTC
SUSE-SU-2017:0554-1: An update that solves one vulnerability and has 6 fixes is now available.

Category: security (important)
Bug References: 1008965,1012504,1012632,1019332,1020077,1020985,1023041
CVE References: CVE-2017-2616
Sources used:
SUSE Linux Enterprise Workstation Extension 12-SP2 (src):    util-linux-2.28-44.3.1
SUSE Linux Enterprise Software Development Kit 12-SP2 (src):    util-linux-2.28-44.3.1
SUSE Linux Enterprise Server for Raspberry Pi 12-SP2 (src):    python-libmount-2.28-44.3.3, util-linux-2.28-44.3.1, util-linux-systemd-2.28-44.3.3
SUSE Linux Enterprise Server 12-SP2 (src):    python-libmount-2.28-44.3.3, util-linux-2.28-44.3.1, util-linux-systemd-2.28-44.3.3
SUSE Linux Enterprise Desktop 12-SP2 (src):    python-libmount-2.28-44.3.3, util-linux-2.28-44.3.1, util-linux-systemd-2.28-44.3.3
Comment 13 Swamp Workflow Management 2017-02-23 11:14:42 UTC
SUSE-SU-2017:0555-1: An update that solves one vulnerability and has 5 fixes is now available.

Category: security (important)
Bug References: 1008965,1012504,1012632,1019332,1020077,1023041
CVE References: CVE-2017-2616
Sources used:
SUSE Linux Enterprise Workstation Extension 12-SP1 (src):    util-linux-2.25-40.1
SUSE Linux Enterprise Software Development Kit 12-SP1 (src):    util-linux-2.25-40.1
SUSE Linux Enterprise Server 12-SP1 (src):    python-libmount-2.25-40.2, util-linux-2.25-40.1, util-linux-systemd-2.25-40.1
SUSE Linux Enterprise Desktop 12-SP1 (src):    python-libmount-2.25-40.2, util-linux-2.25-40.1, util-linux-systemd-2.25-40.1
Comment 14 Swamp Workflow Management 2017-03-02 14:15:39 UTC
openSUSE-SU-2017:0589-1: An update that solves one vulnerability and has 6 fixes is now available.

Category: security (important)
Bug References: 1008965,1012504,1012632,1019332,1020077,1020985,1023041
CVE References: CVE-2017-2616
Sources used:
openSUSE Leap 42.2 (src):    python-libmount-2.28-10.2, util-linux-2.28-10.1, util-linux-systemd-2.28-10.1
Comment 15 Swamp Workflow Management 2017-03-02 14:16:56 UTC
openSUSE-SU-2017:0590-1: An update that solves one vulnerability and has 5 fixes is now available.

Category: security (important)
Bug References: 1008965,1012504,1012632,1019332,1020077,1023041
CVE References: CVE-2017-2616
Sources used:
openSUSE Leap 42.1 (src):    python-libmount-2.25-21.1, util-linux-2.25-21.1, util-linux-systemd-2.25-21.1
Comment 16 Stanislav Brabec 2017-03-02 18:07:04 UTC
util-linux should be fixed in Leap 42.1, Leap 42.2, SLE12, SLE12 SP1, SLE12 SP2 and Tumbleweed. SLE11 and older are not affected, su is not present in util-linux there.

Reassigning to coreutils maintainer to evaluate vulnerability of su in SLE11 and possibly SLE10.
Comment 17 Philipp Thomas 2017-06-06 11:49:09 UTC
Su in coreutils needs no changes as it used execve and not fork like su in util-linux and therefore doesn't need the special signal handling required when using fork.
Comment 18 Matthias Gerstner 2017-06-20 13:43:27 UTC
Hi Philipp,

(In reply to pth@suse.com from comment #17)

> Su in coreutils needs no changes as it used execve and not fork like su in
> util-linux and therefore doesn't need the special signal handling required
> when using fork.

can you please explain this to me in more detail?

I had a look at the coreutils code for SLE-11-SP2 again in

  SUSE:SLE-11-SP2:Update/coreutils/coreutils-8.12/src/su.c

and can't see how it's not affected. It's calling create_watching_parent(),
and USE_PAM seems to be defined for the build.

Thank you.
Comment 19 Philipp Thomas 2017-06-26 08:18:16 UTC
I'll have to let my co-maintainer and upstream coreutil maintainer answer that question, as it was his statement I was relaying. Berny, could you please chime in?
Comment 20 Bernhard Voelker 2017-06-27 06:22:59 UTC
Sorry, it seems that I don't have access to build.suse.com [1], so I am/was
looking into the upstream version at coreutils at that time [2], and there is no
fork -> wait/waitpid, because main() calls run_shell() which in turn calls
execv().

[1] 402: Account Unconfirmed
[2] http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/su.c?h=v8.12&id=8c6a1d1281#n331

Of course the SUSE sources of that time may have diverged from upstream
by patches for this or that, but I was assuming that it was still almost
about the same.

Have a nice day,
Berny
Comment 21 Philipp Thomas 2017-06-27 08:57:41 UTC
I checked again and
Comment 22 Matthias Gerstner 2017-06-27 14:43:19 UTC
(In reply to Philipp Thomas from comment #21)
> I checked again and

Your comment is truncated, but given that you reopened the bug I suspect there is still something to fix?
Comment 23 Philipp Thomas 2017-06-28 07:26:07 UTC
Yes, I had completely forgotten that although SLE11 SP2 got coreutils 8.12 su was still provided by it. Somehow I had connected corerutils 8.12 with su coming from util-linux. So as you wrote, the su in SLE11 SP2 needs the fix.
Comment 24 Johannes Segitz 2018-02-14 13:44:32 UTC
(In reply to Philipp Thomas from comment #23)
Please submit for this codestream. Thank you
Comment 25 Johannes Segitz 2018-02-27 16:19:16 UTC
ping. Please submit
Comment 26 Bernhard Voelker 2018-02-27 23:30:41 UTC
As openSUSE guy, I still don't have access to the SUSE bild service,
but looking back at Base:System/coreutils rev 126, I see that the
patch "coreutils-8.6-pam-support-for-su.diff" would need the tweaks
as shown in the UL commit.
Re-assigning to Raymund Will (as new SLE maintainer AFAIK).
Comment 27 Raymund Will 2018-02-28 10:36:58 UTC
Created attachment 762118 [details]
Proposed patch for coreutils-8.12 from SLE11SP2

Thank you, Bernhard.
Would you (or anyone on CC) be willing to review this patch?
(It compiles, but is otherwise untested.)
Comment 28 Bernhard Voelker 2018-02-28 14:56:20 UTC
Hi Raymund,

hmm, the patch looks quite different from the original mentioned at the top if this issue.  Where did you get the changes from (this is not mentioned in the patch)?

Have a nice day,
Berny
Comment 29 Philipp Thomas 2018-02-28 15:29:29 UTC
Raimund looked at the su code in util-linux for which the patch was done and noticed a few things that where missing from coreutils-8.6-pam-support-for-su.diff and added them (like saving and restoring signal handling). For me it looks like the patch implements exactly what is needed.
Comment 30 Bernhard Voelker 2018-03-01 08:05:23 UTC
I agree: while the patch doesn't apply against the latest openSUSE sources [0],
a visual comparison against latest upstream UL looks good to me as well. Thanks.

[0] https://build.opensuse.org/package/show/Base:System/coreutils?rev=126
Comment 31 Bernhard Voelker 2018-03-01 08:08:28 UTC
(In reply to Bernhard Voelker from comment #30)

little clarification:

> [...] doesn't apply against the latest openSUSE sources [...]

s/latest openSUSE sources/& of version 8.12/
Comment 32 Raymund Will 2018-03-01 10:30:07 UTC
The latest openSUSE sources of version 8.12 are unfortunately lacking
some SLE-patches, including 'coreutils-bnc#697897-setsid.patch'.
But as 'su' is no longer part of maintained openSUSE 'coreutils' packages,
this should be no problem, right?
Comment 35 Swamp Workflow Management 2018-04-03 22:08:16 UTC
SUSE-SU-2018:0866-1: An update that fixes one vulnerability is now available.

Category: security (important)
Bug References: 1023041
CVE References: CVE-2017-2616
Sources used:
SUSE Linux Enterprise Server 11-SP4 (src):    coreutils-8.12-6.25.33.3.1
SUSE Linux Enterprise Debuginfo 11-SP4 (src):    coreutils-8.12-6.25.33.3.1
Comment 41 Alexandros Toptsoglou 2020-06-30 07:39:09 UTC
Done