Allele Security Alert
ASA-2019-00011
Identifier(s)
ASA-2019-00011, CVE-2018-16866
Title
Out-of-bounds read when parsing a crafted syslog message
Vendor(s)
The systemd project
Product(s)
systemd
Affected version(s)
systemd v221 up to v240
Fixed version(s)
systemd released with the following commits:
journal: fix syslog_parse_identifier()
https://github.com/systemd/systemd/commit/a6aadf4ae0bae185dc4c414d492a4a781c80ffe5
journal: do not remove multiple spaces after identifier in syslog message
https://github.com/systemd/systemd/commit/8595102d3ddde6d25c282f965573a6de34ab4421
Proof of concept
Yes
Description
An out-of-bounds read was discovered in systemd-journald in the way it parses log messages that terminate with a colon ‘:’. A local attacker can use this flaw to disclose process memory data.
Technical details
It was discovered an out-of-bounds read in journald that can be transformed into an information leak:
File: v238/src/journal/journald-syslog.c --- 31 #define WHITESPACE " \t\n\r" ... 194 size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid) { 195 const char *p; ... 197 size_t l, e; ... 203 p = *buf; 204 205 p += strspn(p, WHITESPACE); 206 l = strcspn(p, WHITESPACE); 207 208 if (l <= 0 || 209 p[l-1] != ':') 210 return 0; 211 212 e = l; ... 240 if (strchr(WHITESPACE, p[e])) 241 e++; 242 *buf = p + e; 243 return e; 244 } ---
If we send a syslog message to journald (in *buf), and if the last character of this message is a ‘:’ (before the ‘\0’ terminator), then:
– at line 240, p[e] is the ‘\0’ terminator of our message;
– at line 240, strchr(WHITESPACE, p[e]) returns a pointer to the ‘\0’ terminator of the WHITESPACE string (as mentioned in man strchr: “The terminating null byte is considered part of the string, so that if c is specified as ‘\0’, these functions return a pointer to the terminator.”);
– at line 241, e is incremented;
– at line 242, *buf points out-of-bounds, to the first character after the ‘\0’ terminator of our message;
– later, the out-of-bounds string at *buf (supposedly the body of our syslog message) is written (leaked) to the journal.
Consequently, we can read this out-of-bounds string:
– either directly from the journal (if journald’s “Storage” is “persistent”, or “auto” and /var/log/journal/ exists), because journald supports extended file ACLs (Access Control Lists):
$ id uid=1000(john) gid=1000(john) groups=1000(john) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 $ ls -l /var/log/journal/*/user-$UID.journal -rw-r-----+ 1 root systemd-journal 8388608 Nov 20 09:35 /var/log/journal/2562d1eced654f44a3d3a217d66b9ff3/user-1000.journal $ getfacl /var/log/journal/*/user-$UID.journal ... user:john:r-- $ ./infoleak $ journalctl --all --user --lines=1 --identifier=infoleak | hexdump -C ... 00000050 2e 20 2d 2d 0a 4e 6f 76 20 32 30 20 31 36 3a 30 |. --.Nov 20 16:0| 00000060 30 3a 33 36 20 6c 6f 63 61 6c 68 6f 73 74 2e 6c |0:36 localhost.l| 00000070 6f 63 61 6c 64 6f 6d 61 69 6e 20 69 6e 66 6f 6c |ocaldomain infol| 00000080 65 61 6b 5b 33 35 34 38 5d 3a 20 78 fb 1e 78 54 |eak[3548]: x..xT| 00000090 7f 0a |..|
– or (if journald’s “Storage” is “volatile”, or “auto” and /var/log/journal/ does not exist) from a tty that we recorded to /var/run/utmp, because journald writes (“walls”) emergency messages (LOG_EMERG) to the tty of every logged-in user; our exploit records a tty to /var/run/utmp via an ssh connection to localhost, but other methods exist (for example, utempter and gnome-pty-helper):
$ ./infoleak ... 00003510 0a 07 0d 0d 0a 42 72 6f 61 64 63 61 73 74 20 6d |.....Broadcast m| 00003520 65 73 73 61 67 65 20 66 72 6f 6d 20 73 79 73 74 |essage from syst| 00003530 65 6d 64 2d 6a 6f 75 72 6e 61 6c 64 40 6c 6f 63 |emd-journald@loc| 00003540 61 6c 68 6f 73 74 2e 6c 6f 63 61 6c 64 6f 6d 61 |alhost.localdoma| 00003550 69 6e 20 28 54 75 65 20 32 30 31 38 2d 31 31 2d |in (Tue 2018-11-| 00003560 32 30 20 31 36 3a 32 35 3a 34 36 20 43 53 54 29 |20 16:25:46 CST)| 00003570 3a 0d 0d 0a 0d 0d 0a 69 6e 66 6f 6c 65 61 6b 5b |:......infoleak[| 00003580 33 38 37 32 5d 3a 20 78 6b a2 e1 2f 7f 0d 0d 0a |3872]: xk../....|
This vulnerability was introduced in systemd v221:
commit ec5ff4445cca6a1d786b8da36cf6fe0acc0b94c8 Date: Wed Jun 10 22:33:44 2015 -0700 ... - e += strspn(p + e, WHITESPACE); + if (strchr(WHITESPACE, p[e])) + e++;
and was inadvertently fixed in August 2018:
commit a6aadf4ae0bae185dc4c414d492a4a781c80ffe5 Date: Wed Aug 8 15:06:36 2018 +0900 ... - if (strchr(WHITESPACE, p[e])) - e++; + e += strspn(p + e, WHITESPACE);
commit 8595102d3ddde6d25c282f965573a6de34ab4421 Date: Fri Aug 10 11:07:54 2018 +0900 ... - e += strspn(p + e, WHITESPACE); + /* Single space is used as separator */ + if (p[e] != '\0' && strchr(WHITESPACE, p[e])) + e++;
Credits
Qualys Research Labs
Reference(s)
System Down: A systemd-journald exploit
https://seclists.org/oss-sec/2019/q1/54
journal: fix syslog_parse_identifier()
https://github.com/systemd/systemd/commit/a6aadf4ae0bae185dc4c414d492a4a781c80ffe5
journal: do not remove multiple spaces after identifier in syslog message
https://github.com/systemd/systemd/commit/8595102d3ddde6d25c282f965573a6de34ab4421
system-down.tar.gz
https://www.qualys.com/2019/05/09/system-down/system-down.tar.gz
CVE-2018-16866
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-16866
CVE-2018-16866
https://nvd.nist.gov/vuln/detail/CVE-2018-16866
If there is any error in this alert or you wish a comprehensive analysis, let us know.
Last modified: September 3, 2019