Out of bounds write in resolved with crafted TCP responses
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
| systemd (Ubuntu) |
High
|
Dimitri John Ledkov | ||
| Xenial |
Undecided
|
Unassigned | ||
| Yakkety |
Undecided
|
Unassigned | ||
| Zesty |
Undecided
|
Unassigned | ||
| Artful |
High
|
Dimitri John Ledkov |
Bug Description
[Impact]
Certain sizes passed to dns_packet_new can cause it to allocate a buffer that's too small. A page-aligned number - sizeof(DnsPacket) + sizeof(iphdr) + sizeof(udphdr) will do this - so, on x86 this will be a page-aligned number - 80. Eg, calling dns_packet_new with a size of 4016 will result in an allocation of 4096 bytes, but 108 bytes of this are for the DnsPacket struct.
A malicious DNS server can exploit this by responding with a specially crafted TCP payload to trick systemd-resolved in to allocating a buffer that's too small, and subsequently write arbitrary data beyond the end of it.
To demonstrate this you can run the attached python script. This is a mock DNS server that sends a response where the first two bytes of the TCP payload specify a size of 4016 (note, this size is picked to trigger an out of bounds write on x86 - you'll probably need to pick a different number for x86-64). You'll need to temporarily set your DNS server to 127.0.0.1.
[Testcase]
Launch the attached script on i386, point resolved at the started dns server, execute a dns query via resolved observe that it crashes.
Upgrade systemd package and observe that resolved no longer crashes.
[Regression Potential]
Low, resolved is not used by default in xenial. This is a bug fix to resolved, in case somebody does use resolved in xenial.
CVE References
Chris Coulson (chrisccoulson) wrote : | #1 |
description: | updated |
Chris Coulson (chrisccoulson) wrote : | #3 |
This appears to have been introduced by https:/
Changed in systemd (Ubuntu): | |
assignee: | nobody → Dimitri John Ledkov (xnox) |
importance: | Undecided → High |
milestone: | none → ubuntu-17.06 |
Dimitri John Ledkov (xnox) wrote : | #4 |
I can reproduce the bug, using the python script, and setting DNS to 127.0.0.1 in /etc/systemd/
The proposed patch seems to work around the problem. But i'm not sure if that is correct solution, that will work for all alignments on all architectures.
I guess we should be approaching upstream about this next?
Chris Coulson (chrisccoulson) wrote : | #5 |
I've sent the details of this to Lennart now.
description: | updated |
Launchpad Janitor (janitor) wrote : | #6 |
This bug was fixed in the package systemd - 232-21ubuntu5
---------------
systemd (232-21ubuntu5) zesty-security; urgency=medium
* SECURITY UPDATE: Out-of-bounds write in systemd-resolved (LP: #1695546)
- debian/
Add a simple allocation test
- debian/
allocation size calculation
- CVE-2017-9445
-- Chris Coulson <email address hidden> Wed, 21 Jun 2017 16:33:22 +0100
Changed in systemd (Ubuntu): | |
status: | New → Fix Released |
Launchpad Janitor (janitor) wrote : | #7 |
This bug was fixed in the package systemd - 231-9ubuntu5
---------------
systemd (231-9ubuntu5) yakkety-security; urgency=medium
* SECURITY UPDATE: Out-of-bounds write in systemd-resolved (LP: #1695546)
- debian/
Add a simple allocation test
- debian/
allocation size calculation
- CVE-2017-9445
-- Chris Coulson <email address hidden> Wed, 21 Jun 2017 16:35:26 +0100
Changed in systemd (Ubuntu): | |
status: | New → Fix Released |
information type: | Private Security → Public Security |
Changed in systemd (Ubuntu Xenial): | |
status: | New → Confirmed |
Changed in systemd (Ubuntu Yakkety): | |
status: | New → Fix Released |
Changed in systemd (Ubuntu Zesty): | |
status: | New → Fix Released |
description: | updated |
Hello Chris, or anyone else affected,
Accepted systemd into xenial-proposed. The package will build now and be available at https:/
Please help us by testing this new package. See https:/
If this package fixes the bug for you, please add a comment to this bug, mentioning the version of the package you tested and change the tag from verification-
Further information regarding the verification process can be found at https:/
Changed in systemd (Ubuntu Xenial): | |
status: | Confirmed → Fix Committed |
tags: | added: verification-needed verification-needed-xenial |
Dimitri John Ledkov (xnox) wrote : | #9 |
Instead of disconnect, I now get invalid reply response and the systemd-resolved service is not crashing.
Dimitri John Ledkov (xnox) wrote : | #10 |
Crashes with 229-4ubuntu17, crash resiliant with 229-4ubuntu18.
tags: |
added: verification-done verification-done-xenial removed: verification-needed verification-needed-xenial |
Adam Conrad (adconrad) wrote : | #11 |
Hello Chris, or anyone else affected,
Accepted systemd into xenial-proposed. The package will build now and be available at https:/
Please help us by testing this new package. See https:/
If this package fixes the bug for you, please add a comment to this bug, mentioning the version of the package you tested and change the tag from verification-
Further information regarding the verification process can be found at https:/
tags: |
added: verification-needed verification-needed-xenial removed: verification-done verification-done-xenial |
Dimitri John Ledkov (xnox) wrote : | #12 |
Starting with systemd 229-4ubuntu17, pointed systemd-resolve to the break-tcp DNS server and observed crash in the journal after calling systemd-resolve start.ubuntu.com.
Upgraded to 229-4ubuntu19, and now systemd-resolve start.ubuntu.com instead of disconnecting and crashing systemd-resolved daemon, keeps the systemd-resolved daemon running and an error is bubbled up back to the clinet received invalid reply.
tags: |
added: verification-done verification-done-xenial removed: verification-needed verification-needed-xenial |
Launchpad Janitor (janitor) wrote : | #14 |
This bug was fixed in the package systemd - 229-4ubuntu19
---------------
systemd (229-4ubuntu19) xenial; urgency=medium
* debian/
revert, by removing ExecStart|StopPost lines, as these are not needed on
xenial and generate warnings in the journal. (LP: #1704677)
systemd (229-4ubuntu18) xenial; urgency=medium
* debian/
is going to be started, make sure this blocks network-
(LP: #1673860)
* networkd: cherry-pick support for setting bridge port's priority
(LP: #1668347)
* Cherrypick upstream commit to enable system use kernel maximum limit for
RLIMIT_NOFILE isntead of hard-coded (low) limit of 65536. (LP: #1686361)
* Cherrypick upstream patch for platform predictable interface names.
(LP: #1686784)
* resolved: fix null pointer dereference crash (LP: #1621396)
* Cherrypick core/timer downgrade message about random time addition
(LP: #1692136)
* SECURITY UPDATE: Out-of-bounds write in systemd-resolved (LP: #1695546)
- CVE-2017-9445
* Cherry-pick subset of patches to introduce infinity value in logind.conf
for UserTasksMax (LP: #1651518)
-- Dimitri John Ledkov <email address hidden> Mon, 17 Jul 2017 17:00:42 +0100
Changed in systemd (Ubuntu Xenial): | |
status: | Fix Committed → Fix Released |
Adam Conrad (adconrad) wrote : Update Released | #13 |
The verification of the Stable Release Update for systemd has completed successfully and the package has now been released to -updates. Subsequently, the Ubuntu Stable Release Updates Team is being unsubscribed and will not receive messages about this bug report. In the event that you encounter a regression using the package from -updates please report a new bug using ubuntu-bug and tag the bug report regression-update so we can easily find any regressions.
The test case results in traces like this.
#0 0xb7758cf9 in __kernel_vsyscall () signal_ restore_ set (set=0xbf8395e0) at ../sysdeps/ unix/sysv/ linux/nptl- signals. h:79 unix/sysv/ linux/raise. c:55 handler = {sa_handler = 0x30320a5d, sa_sigaction = 0x30320a5d}, sa_mask = {__val = {908996910, 892822026, 808465971, 929180976, 808923957, 1914712112, 544222509, 1664102448, 808464481, 979592736, 840970544, 859255606, 538976310, 1815027744, 1764713065, 758528051, 1970170220, 1852255608, 1768697717, 1919117154, 779382905, 841903987, 774975024, 929172022, 808923957, 1647128624, 1630745911, 540028976, 1882027890, 808464416, 0, 4096}}, sa_flags = -1222154106, sa_restorer = 0xbf839840} <optimised out>, fmt=<optimised out>) at ../sysdeps/ posix/libc_ fatal.c: 175 free.lto_ priv.128 (s=<optimised out>) at ../src/ libsystemd/ sd-event/ sd-event. c:887 source_ unref (s=<optimised out>) at ../src/ libsystemd/ sd-event/ sd-event. c:1402 stop.lto_ priv.71 (s=<optimised out>) at ../src/ resolve/ resolved- dns-stream. c:35 resolve/ resolved- dns-stream. c:55 io.lto_ priv.64 (es=0x809d6640, fd=18, revents=1, userdata= 0x809d6738) at ../src/ resolve/ resolved- dns-stream. c:321
No symbol table info available.
#1 0xb728b050 in __libc_
No locals.
#2 __GI_raise (sig=6) at ../sysdeps/
set = {__val = {18946, 0, 808464438, 926376493, 808466485, 762454064, 807432237, 808464432, 540028976, 809119792, 540024880, 538976288, 538976288, 1987468064, 173896289, 892811106, 808464440, 926376493, 808476981, 762454064, 807432312, 808464432, 540028976, 809119792, 540024880, 538976288, 538976288, 1685478176, 173895539, 892811106, 808464481, 926376493}}
pid = <optimised out>
tid = <optimised out>
ret = 0
#3 0xb728c577 in __GI_abort () at abort.c:89
save_stage = 2
act = {__sigaction_
sigs = {__val = {32, 0 <repeats 31 times>}}
#4 0xb72c6f4f in __libc_message (do_abort=
ap = <optimised out>
fd = 2
on_2 = <optimised out>
list = <optimised out>
nlist = <optimised out>
cp = <optimised out>
written = <optimised out>
#5 0xb72cdb47 in malloc_printerr (action=<optimised out>, str=0xb73c2d5c "double free or corruption (out)", ptr=<optimised out>, ar_ptr=0xb7415780 <main_arena>) at malloc.c:5046
buf = "809d68b0"
cp = <optimised out>
ar_ptr = 0xb7415780 <main_arena>
ptr = <optimised out>
str = 0xb73c2d5c "double free or corruption (out)"
action = <optimised out>
#6 0xb72ce406 in _int_free (av=0xb7415780 <main_arena>, p=0x809d68a8, have_lock=0) at malloc.c:3902
size = <optimised out>
fb = <optimised out>
nextchunk = <optimised out>
nextsize = <optimised out>
nextinuse = <optimised out>
prevsize = <optimised out>
bck = <optimised out>
fwd = <optimised out>
errstr = <optimised out>
locked = <optimised out>
__func__ = "_int_free"
#7 0xb75a76fe in source_
No locals.
#8 0xb7602507 in sd_event_
No locals.
#9 0x800523b6 in dns_stream_
No locals.
#10 0x8005240b in dns_stream_complete (s=<optimised out>, error=<optimised out>) at ../src/
No locals.
#11 0x80052689 in on_stream_
s = 0x80...