-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
resolved DNSSEC validation can be bypassed by MITM #25676
Description
systemd version the issue has been seen with
251.8-1-manjaro
Used distribution
Manjaro
Linux kernel version used
5.15.81-1-MANJARO
CPU architectures issue was seen on
x86_64
Component
systemd-resolved
Expected behaviour you didn't see
When DNSSEC=yes is set and querying a DNSSEC-enabled domain, systemd-resolved should only accept records that are signed correctly.
Unexpected behaviour you saw
systemd-resolved accepts records of DNSSEC-signed domains even when they have no signature, allowing man-in-the-middles (or the upstream DNS resolver) to manipulate records.
Please note that I have repeatedly tried to report this issue to the systemd-security mailing list. I sent a mail with the details and reproduction steps to the systemd-security address on Oct 6th, Oct 14th and Oct 22nd. I first received a reply on Oct 24th from Lennart Poettering, asking for some basic system information, which I provided on the same day. Then I received no further reply, so I sent the report one more time to systemd-security on Nov 7th. The next day Poettering replied to my previous mail, asking for a debug log, but not directly acknowledging the issue. I sent debug logs on Nov 10th and haven't heard back from anyone since then.
Steps to reproduce the problem
The issue can be reproduced with an unbound server and a typetransparent local-zone to simulate an attacker modifying select records. cloudflare.net is used as an example domain since it is signed and valid. In this example, the DNS server is run on 192.168.1.1 and the systemd client has any address in the same /24 network.
unbound.conf:
server:
# Allow running unbound unprivileged
username: ""
use-syslog: no
chroot: ""
pidfile: ""
interface: 0.0.0.0
port: 10053
access-control: 192.168.1.1/24 allow
local-zone: www.cloudflare.net typetransparent
local-data: "www.cloudflare.net. 3600 IN A 1.2.3.4"
forward-zone:
name: .
forward-addr: 1.1.1.1
forward-addr: 1.0.0.1
forward-first: no
- On the "attacker" machine, install unbound and run
unbound -d -v -c unbound.conf. - On the machine running systemd-resolved, run
sudo systemd-resolve --set-dns 192.168.1.1:10053 --set-dnssec yes --interface enp0s3. (Replace IP and interface name accordingly). - Run
resolvectl statusto confirm our DNS server is used and output containsDNSSEC=yes/supported. - Run
resolvectl query cloudflare.netwhich should produce the correct reply andData is authenticated: yes, confirming that the domain is DNSSEC-signed. - Run
resolvectl query www.cloudflare.net:
$ resolvectl query www.cloudflare.net
www.cloudflare.net: 1.2.3.4 -- link: enp0s3
-- Information acquired via protocol DNS in 25.6ms.
-- Data is authenticated: no; Data was acquired via local or encrypted transport: no
-- Data from: network
systemd-resolved accepts the bogus response. Running dig @127.0.0.53 www.cloudflare.net also shows the status is NOERROR. When resolved is configured as system resolver (e.g. through /etc/resolv.conf), curl -v http://www.cloudflare.net tries to connect to 1.2.3.4, showing that applications are successfully tricked with the manipulated record.
Note that resolved does state the data is unauthenticated and also does not set the AD bit when queried on 127.0.0.53.
Repeat the test but replace typetransparent with static in the unbound configuration. In this case, resolved rejects the response as expected:
$ resolvectl query www.cloudflare.net
www.cloudflare.net: resolve call failed: DNSSEC validation failed: no-signature
(Note that due to another bug #24827, resolved will still reply with the records on 127.0.0.53, but it has status: SERVFAIL, so applications generally won't use this answer)
The difference is that static replaces all data for the www.cloudflare.net domain, whereas typetransparent only replaces the A record(s). Both strip the RRSIG records from affected queries.
My knowledge on DNS isn't great, but as far as I know no unsigned record should be allowed anywhere under the zone cloudflare.net, unless there was an insecure delegation (NS record without corresponding DS record).
However, it appears only signatures of some types of records actually matter to resolved, for example the SOA record. The RRSIG signatures on A/AAAA (and probably more) records can simply be stripped and resolved will accept the data without ensuring its validity.
Additional program output to the terminal or log subsystem illustrating the issue
systemd-resolved debug logs, including all output after running `resolvectl query www.cloudflare.net` are posted in this gist, separate for the typetransparent and the static test case: https://gist.github.com/AgentOak/11c64ff8701c4cd853d6b99382a40704