
Proof of Concept for CVE-2025-40778: BIND 9 DNS Cache Poisoning via unsolicited Additional Section records.
This vulnerability allows an attacker to corrupt the DNS cache of a BIND Resolver, forcing legitimate users to be redirected to malicious IP addresses without their knowledge.
The attack relies on exploiting trust. The Victim trusts the Resolver, and the Resolver (BIND) trusts the answers it receives from Authoritative Servers. The flaw exists because BIND processes and caches unsolicited data provided in the ADDITIONAL section of a DNS response, even if that data belongs to a completely different, unrequested domain.
The setup: The Attacker controls a malicious Authoritative DNS server for a specific domain (e.g. poc.lab). The Attacker waits for the target Resolver (BIND) to query this domain.
The injection: When the Resolver queries the Attacker's server for poc.lab, the Attacker responds with a legitimate answer for poc.lab but includes an unsolicited answer in the ADDITIONAL section for a different domain (in our example is www.hacker.com, but could be any legitimate domain, like facebook.com) pointing to a malicious IP address.
The poisoning: Due to the vulnerability, the Resolver accepts the unsolicited "Additional" record and stores it in its cache. It does not verify that the Attacker has no authority over the unsolicited domain.
: When the Victim later queries the Resolver for the unsolicited domain (), the Resolver returns the poisoned record from its cache, redirecting the Victim to the malicious IP address controlled by the Attacker.
[!IMPORTANT]
Key Takeaways for this PoC
Indirect Attack: The Victim never communicates with the Attacker directly.
Trust Anchor Compromise: The Victim’s machine is functioning correctly; it is the infrastructure (DNS) that is lying.
The Mechanism: The exploit leverages the processing of the Additional Section to inject records that were never requested.
[!CAUTION]
This PoC is for educational purposes only. Unauthorized use of this information to compromise systems is illegal and unethical. Always obtain permission before testing or exploiting vulnerabilities on any network or system.
The following virtual machines (VMs) are used in this demonstration:
The following commands are for the setup of BIND 9.21.12 on a Debian-based system to demonstrate the CVE-2025-40778 vulnerability.
[!NOTE] This demonstration uses BIND 9.21.12, which is one of the versions affected by this vulnerability.
Other known ranges of affected versions include:
- 9.11.0 – 9.16.50
- 9.18.0 – 9.18.39
- 9.20.0 – 9.20.13
- 9.21.0 – 9.21.12
The following commands will install the necessary dependencies, download the BIND 9.21.12 source code, compile it, and install it on wer system.
sudo apt install -y build-essential pkg-config perl meson ninja-build libssl-dev libuv1-dev liburcu-dev libcap-dev liblmdb-dev libnghttp2-dev
cd /usr/local/src
sudo wget -O bind-9.21.12.tar.xz https://isc.mirrorservice.org/bind/9.21.12/bind-9.21.12.tar.xz
sudo tar -xf bind-9.21.12.tar.xz
cd bind-9.21.12
sudo meson setup build --prefix=/usr/local --sysconfdir=/etc --localstatedir=/var
sudo ninja -C build
sudo ninja -C build install
echo /usr/local/lib/x86_64-linux-gnu | sudo tee /etc/ld.so.conf.d/bind9-local.conf
sudo ldconfig
ldconfig -p | grep 'libdns-9.21.12' || true
/usr/local/sbin/named -v
Here is the expected output of the final command:
> student@student:/usr/local/src/bind-9.21.12$ /usr/local/sbin/named -v
BIND 9.21.12 (Development Release) <id:9bafc35>
Before starting the BIND server, we need to create a dedicated user and group for running the named service:
sudo groupadd --system named 2>/dev/null || true
sudo useradd --system --no-create-home --home /nonexistent --shell /usr/sbin/nologin --gid named named 2>/dev/null || true
Since this BIND installation does not come with default configuration files, we need to create the necessary directories manually:
sudo mkdir -p /etc/bind
sudo mkdir -p /var/cache/bind
sudo mkdir -p /var/log/named
sudo mkdir -p /var/run/named
sudo chown -R named:named /var/cache/bind /var/log/named /var/run/named
sudo chmod 750 /var/cache/bind /var/log/named /var/run/named
Next step is to create the main configuration file /etc/bind/named.conf with the content below:
include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.logging";
include "/etc/rndc.key";
For the options configuration, create the file /etc/bind/named.conf.options with the following content:
options {
directory "/var/cache/bind";
recursion yes;
allow-recursion { 192.168.174.0/24; };
allow-query { 192.168.174.0/24; };
listen-on { 192.168.174.131; 127.0.0.1; };
listen-on-v6 { none; };
dnssec-validation no;
forwarders {
1.1.1.1;
8.8.8.8;
};
minimal-responses no;
// for manual start
pid-file "/var/run/named/named.pid";
};
In order to set up a forward zone for the domain poc.lab to forward queries to the attacker's DNS server at 192.168.174.130 on the standard port 53, we need to edit the /etc/bind/named.conf.local file as such:
zone "poc.lab" {
type forward;
forward only;
forwarders { 192.168.174.130; };
};
For logging configuration, create the file /etc/bind/named.conf.logging containing:
logging {
channel queries_file {
file "/var/log/named/queries.log" versions 3 size 20m;
severity info;
print-time yes;
print-category yes;
};
channel default_stderr {
stderr;
severity info;
print-time yes;
print-category yes;
};
category queries { queries_file; };
category default { default_stderr; };
};
Finally, we need to configure RNDC:
sudo /usr/local/sbin/rndc-confgen -a -c /etc/bind/rndc.key
sudo chown root:named /etc/bind/rndc.key
sudo chmod 640 /etc/bind/rndc.key
Firstly, we need to ensure that the port 53 is not being used by any other service (in our case we had to disable systemd-resolved):
sudo systemctl disable --now systemd-resolved || true
sudo ss -lunp | grep ':53' || true # To verify that port 53 is free
Finally, we can start the BIND server using the following command:
sudo /usr/local/sbin/named -g -u named -c /etc/bind/named.conf
[!TIP]
In order to verify that BIND is running correctly, we can use the following command:
ss -lunpt | grep :53
For the victim machine, we need to set it to use the BIND server as its DNS resolver. Also, we have to deactivate systemd-resolved to avoid conflicts:
sudo systemctl disable --now systemd-resolved
Then we can set a static DNS server using the commands:
sudo rm -f /etc/resolv.conf
sudo nano /etc/resolv.conf
> nameserver 192.168.174.129
> options timeout:1 attempts:1
sudo chattr +i /etc/resolv.conf #block overwrites
On the attacker machine, we need to run the script provided in the repository (attacker.py).
In our scenario, the attacker controls the poc.lab domain. When asked for it or any subdomain, he adds an unsolicited answer record (www.hacker.com) pointing to his IP address.
When the victim queries for the domain poc.lab, the BIND server forwards the request to the attacker's DNS server. The attacker responds with an unsolicited answer record that poisons the cache of the BIND server. When the victim will access www.hacker.com, it will be redirected to the attacker's IP address instead of the legitimate one.
Here is a demonstration of the victim querying both domains:
student@student:~/Desktop$ dig www.poc.lab +noall +answer
www.poc.lab. 60 IN A 192.168.174.99
student@student:~/Desktop$ dig www.hacker.com +noall +answer
www.hacker.com. 60 IN A 192.168.174.130
As shown above, the victim's DNS query for www.hacker.com returns the attacker's IP address (192.168.174.130).
[!NOTE]
This video is a demonstration of the explained vulnerability: https://drive.google.com/file/d/1PATD0tUqw8-BipfSf6TkQQfnJBvV110Z/view?usp=sharing