Allele Security Alert
ASA-2019-00465
Identifier(s)
ASA-2019-00465, CVE-2019-13272
Title
Broken permission and object lifetime handling for PTRACE_TRACEME
Vendor(s)
Linux foundation
Product(s)
Linux kernel
Affected version(s)
Linux kernel versions before 5.2
Linux kernel versions before 4.4.185
Linux kernel versions before 4.9.185
Linux kernel versions before 4.14.133
Linux kernel versions before 4.19.58
Linux kernel versions before 5.1.17
Linux kernel versions with the following commit applied:
ptrace: Capture the ptracer’s creds not PT_PTRACE_CAP
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=64b875f7ac8a5d60a4e191479299e931ee949b67
Fixed version(s)
Linux kernel version 5.2
Linux kernel version 4.4.185
Linux kernel version 4.9.185
Linux kernel version 4.14.133
Linux kernel version 4.19.58
Linux kernel version 5.1.17
Proof of concept
Yes
Description
A flaw was found in the way PTRACE_TRACEME functionality was handled in the Linux kernel. The kernel’s implementation of ptrace can inadvertently grant elevated permissions to an attacker who can then abuse the relationship between the tracer and the process being traced. This flaw could allow a local, unprivileged user to increase their privileges on the system or cause a denial of service.
Technical details
ptrace relationships can be set up in two ways:
Either the tracer attaches to another process (PTRACE_ATTACH/PTRACE_SEIZE), or the tracee forces its parent to attach to it (PTRACE_TRACEME). When a tracee goes through a privilege-gaining execve(), the kernel checks whether the ptrace relationship is privileged. If it is not, the privilege-gaining effect of execve is suppressed. The idea here is that a privileged tracer (e.g. if root runs “strace” on some process) is allowed to trace through setuid/setcap execution, but an unprivileged tracer must not be allowed to do that, since it could otherwise inject arbitrary code into privileged processes.
In the PTRACE_ATTACH/PTRACE_SEIZE case, the tracer’s credentials are recorded at the time it calls PTRACE_ATTACH/PTRACE_SEIZE; later, when the tracee goes through execve(), it is checked whether the recorded credentials are capable over the tracee’s user namespace. But in the PTRACE_TRACEME case, the kernel also records _the tracer’s_ credentials, even though the tracer is not requesting the operation. There are two problems with that.
First, there is an object lifetime issue:
ptrace_traceme() -> ptrace_link() grabs __task_cred(new_parent) in an RCU read-side critical section, then passes the creds to __ptrace_link(), which calls get_cred() on them. If the parent concurrently switches its creds (e.g. via setresuid()), the creds’ refcount may already be zero, in which case put_cred_rcu() will already have been scheduled. The kernel usually manages to panic() before memory corruption occurs here using the following code in put_cred_rcu(). However, memory corruption would also be possible if this code races exactly the right way.
if (atomic_read(&cred->usage) != 0) panic("CRED: put_cred_rcu() sees %p with usage %d\n", cred, atomic_read(&cred->usage));
The second problem is that, because the PTRACE_TRACEME case grabs the credentials of a potentially unaware tracer, it can be possible for a normal user to create and use a ptrace relationship that is marked as privileged even though no privileged code ever requested or used that ptrace relationship. This requires the presence of a setuid binary with certain behavior: It has to drop privileges and then become dumpable again (via prctl() or execve()).
– task A: fork()s a child, task B
– task B: fork()s a child, task C
– task B: execve(/some/special/suid/binary)
– task C: PTRACE_TRACEME (creates privileged ptrace relationship)
– task C: execve(/usr/bin/passwd)
– task B: drop privileges (setresuid(getuid(), getuid(), getuid()))
– task B: become dumpable again (e.g. execve(/some/other/binary))
– task A: PTRACE_ATTACH to task B
– task A: use ptrace to take control of task B
– task B: use ptrace to take control of task C
Polkit’s pkexec helper fits this pattern. On a typical desktop system, any process running under an active local session can invoke some helpers through pkexec (see configuration in /usr/share/polkit-1/actions, search for <action>s that specify <allow_active> yes </allow_active> and <annotate key=”org.freedesktop.policykit.exec.path”> …</annotate>).
While pkexec is normally used to run programs as root, pkexec actually allows its caller to specify the user to run a command as with –user, which permits using pkexec to run a command as the user who executed pkexec.
Credits
Jann Horn (Google Project Zero)
Reference(s)
Issue 1903: Linux: broken permission and object lifetime handling for PTRACE_TRACEME
https://bugs.chromium.org/p/project-zero/issues/detail?id=1903
ptrace: Fix ->ptracer_cred handling for PTRACE_TRACEME
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6994eefb0053799d2e07cd140df6c2ea106c41ee
ptrace: Capture the ptracer’s creds not PT_PTRACE_CAP
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=64b875f7ac8a5d60a4e191479299e931ee949b67
Linux 5.2
https://lore.kernel.org/lkml/CAHk-=whtW3FdruS-q2zehJPSan1SKtHoFHKX28A3J_1gfTFUMw@mail.gmail.com/
Linux kernel 4.4.185
https://cdn.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.4.185
Linux kernel 4.9.185
https://cdn.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.9.185
Linux kernel 4.14.133
https://cdn.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.14.133
Linux kernel 4.19.58
https://cdn.kernel.org/pub/linux/kernel/v4.x/ChangeLog-4.19.58
Linux kernel 5.1.17
https://cdn.kernel.org/pub/linux/kernel/v5.x/ChangeLog-5.1.17
CVE-2019-13272 Linux local root exploit
https://github.com/jas502n/CVE-2019-13272
CVE-2019-13272 - Red Hat Customer Portal
https://access.redhat.com/security/cve/CVE-2019-13272
https://people.canonical.com/~ubuntu-security/cve/CVE-2019-13272.html
CVE-2019-13272 | SUSE
https://www.suse.com/security/cve/CVE-2019-13272
CVE-2019-13272
https://security-tracker.debian.org/tracker/CVE-2019-13272
CVE-2019-13272
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-13272
CVE-2019-13272
https://nvd.nist.gov/vuln/detail/CVE-2019-13272
If there is any error in this alert or you wish a comprehensive analysis, let us know.
Last modified: October 10, 2019