Qualys Security Advisory
System Down: A systemd-journald exploit
Contents
Summary
CVE-2018-16864
- Analysis
- Exploitation
CVE-2018-16865
- Analysis
- Exploitation
CVE-2018-16866
- Analysis
- Exploitation
Combined Exploitation of CVE-2018-16865 and CVE-2018-16866
- amd64 Exploitation
- i386 Exploitation
Acknowledgments
Timeline
Conversion, software version 7.0
-- System of a Down, "Toxicity"
Summary
We discovered three vulnerabilities in systemd-journald
(https://en.wikipedia.org/wiki/Systemd):
- CVE-2018-16864 and CVE-2018-16865, two memory corruptions
(attacker-controlled alloca()s);
- CVE-2018-16866, an information leak (an out-of-bounds read).
CVE-2018-16864 was introduced in April 2013 (systemd v203) and became
exploitable in February 2016 (systemd v230). We developed a proof of
concept for CVE-2018-16864 that gains eip control on i386.
CVE-2018-16865 was introduced in December 2011 (systemd v38) and became
exploitable in April 2013 (systemd v201). CVE-2018-16866 was introduced
in June 2015 (systemd v221) and was inadvertently fixed in August 2018.
We developed an exploit for CVE-2018-16865 and CVE-2018-16866 that
obtains a local root shell in 10 minutes on i386 and 70 minutes on
amd64, on average. We will publish our exploit in the near future.
To the best of our knowledge, all systemd-based Linux distributions are
vulnerable, but SUSE Linux Enterprise 15, openSUSE Leap 15.0, and Fedora
28 and 29 are not exploitable because their user space is compiled with
GCC's -fstack-clash-protection.
This confirms https://grsecurity.net/an_ancient_kernel_hole_is_not_closed.php:
"It should be clear that kernel-only attempts to solve [the Stack Clash]
will necessarily always be incomplete, as the real issue lies in the
lack of stack probing."
CVE-2018-16864
Analysis
The waves all keep on crashing by
-- System of a Down, "Suggestions"
We accidentally discovered CVE-2018-16864 while working on the exploit
for Mutagen Astronomy (CVE-2018-14634); if we pass several megabytes of
command-line arguments to a program that calls syslog(), then journald
crashes:
systemd-journal[472]: segfault at 7ffe9a077420 ip 7f45f6174877 sp
7ffe9a0773f0 error 6 in systemd-journald[7f45f6169000+3f000]
(gdb) disassemble 0x7f45f6174877 - 0x7f45f6169000
Dump of assembler code for function dispatch_message_real.4064:
...
0xb82c <+988>: callq 0x2bd10
0xb831 <+993>: test %eax,%eax
0xb833 <+995>: js 0xb8ea
0xb839 <+1001>: mov-0x218(%rbp),%rbx
0xb840 <+1008>: test %rbx,%rbx
0xb843 <+1011>: je 0xd31b
0xb849 <+1017>: mov%rbx,%rdi
0xb84c <+1020>: callq 0x5360
0xb851 <+1025>: add$0xa,%eax
0xb854 <+1028>: cltq
0xb856 <+1030>: add$0x1e,%rax
0xb85a <+1034>: and$0xfff0,%rax
0xb85e <+1038>: sub%rax,%rsp
0xb861 <+1041>: movabs $0x454e494c444d435f,%rax
0xb86b <+1051>: lea0x37(%rsp),%r15
0xb870 <+1056>: and$0xfff0,%r15
0xb874 <+1060>: test %rbx,%rbx
0xb877 <+1063>: mov%rax,(%r15)
0xb87a <+1066>: mov$0x3d,%eax
0xb87f <+1071>: mov%ax,0x8(%r15)
0xb884 <+1076>: lea0x9(%r15),%rax
0xb888 <+1080>: je 0xb895
0xb88a <+1082>: mov%rbx,%rsi
0xb88d <+1085>: mov%rax,%rdi
0xb890 <+1088>: callq 0x5370
538 static void dispatch_message_real(
...
604 r = get_process_cmdline(ucred->pid, 0, false, );
605 if (r >= 0) {
606 x = strjoina("_CMDLINE=", t);
919 #define strjoina(a, ...)\
920 ({ \
921 const char *_appendees_[] = { a, __VA_ARGS__ }; \
922 char *_d_, *_p_;\
923 int _len_ = 0; \
924 unsigned _i_; \
925 for (_i_ = 0; _i_ < ELEMENTSOF(_appendees_) &&