Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DoS Vulnerabilities of SmartDNS (TuDoor Attack) #1829

Open
idealeer opened this issue Sep 29, 2024 · 3 comments
Open

DoS Vulnerabilities of SmartDNS (TuDoor Attack) #1829

idealeer opened this issue Sep 29, 2024 · 3 comments

Comments

@idealeer
Copy link

Overview

We found a new vulnerability in DNS resolving software, which triggers a resolver to ignore valid responses thus causing DoS (denial of service) for normal resolution. The effects of an exploit would be widespread and highly impactful, as the attacker could just forge a response targeting the source port of vulnerable resolver without the need to guess the correct TXID.

Vulnerability Details

After analyzing the source code of all DNS software, we locate a response preprocessing part that receives incoming packets and parses them before processing valid DNS data.

We find that there is a huge implementation difference between different DNS software on the preprocessing operation. Specially, some software just accept the first-incoming packet and ignore all the other responses for each outgoing query. Unfortunately, they don't check the packet format and TXID. If the source port is matched, these software will accept these packets.

Regarding this sort of processing, we propose a DoS attack to cause vulnerable resolvers to ignore any valid response and terminate current resolution process. We name it TuDoor attack.

General attack steps:

  1. The target resolver sends a query for current resolution.
  2. The attacker forges malformed packets and returns them to the target resolver earlier to legal response.
  3. To hitting the correct source port, the attacker could just brute-force the 65,535 port numbers. By doing so, all queries using any port of these 65,535 ports would fail.
  4. After receiving malformed packets, the target resolver just decides that there is something wrong with the remote server and ignores any follow-up responses.
  5. Thus, current resolution fails and a DoS attack is achieved.

Malformed packets :

There are two type of malformed packets: ICMP packet and bad-format UDP packet. For example:

ICMP packet (the attacker even needn't to impersonate the remote server's IP).

spf_resp = IP(src="8.8.8.8", dst=pkt[IP].src) / ICMP(type=3, code=3) / \
           IP(src=pkt[IP].src, dst=pkt[IP].dst) / UDP(sport=pkt[UDP].sport, dport=int(PORT_OF_SERVER))

Bad-format UDP packet with null or malformed DNS layer payload (the attacker needs to forge the remote server's IP).

spf_resp = IP(src=pkt[IP].dst, dst=pkt[IP].src) / UDP(sport=int(PORT_OF_SERVER), dport=pkt[UDP].sport)
# or other packets, please check the poc for details

Note:

To enlarge the impact, the attacker could DoS the response for queries targeting TLD so that all follow-up resolution under the TLD will fail.

Furthermore, to handle the retry and multiple queries on different nameserver IPs, the attacker could send these malformed packets from multiple machines round by round.

Threat Surface

Software Version ICMP packet Bad-format UDP packet
SmartDNS latest Vulnerable Vulnerable

Mitigation

Resolvers should wait for a timeout until receiving a legal DNS response and ignore any malformed packets.

We recommend that all implementations should take a similar way to guarantee receiving a valid response rather than just receiving one, processing one, and ignoring others.

Reference

https://www.computer.org/csdl/proceedings-article/sp/2024/313000a181/1V28Z5fBEVG

@pymumu
Copy link
Owner

pymumu commented Sep 30, 2024

Maybe I don't fully understand how this attack works.
The smartdns code checks the TXID and UDP packet format before returning the results to the client.
The corresponding code is as follows:

smartdns/src/dns_client.c

Lines 1828 to 1870 in 84f217d

len = dns_decode(packet, DNS_PACKSIZE, inpacket, inpacket_len);
if (len != 0) {
char host_name[DNS_MAX_CNAME_LEN];
tlog(TLOG_INFO, "decode failed, packet len = %d, tc = %d, id = %d, from = %s\n", inpacket_len, packet->head.tc,
packet->head.id, get_host_by_addr(host_name, sizeof(host_name), from));
if (dns_save_fail_packet) {
dns_packet_save(dns_save_fail_packet_dir, "client", host_name, inpacket, inpacket_len);
}
return -1;
}
/* not answer, return error */
if (packet->head.qr != DNS_OP_IQUERY) {
tlog(TLOG_DEBUG, "message type error.\n");
return -1;
}
tlog(TLOG_DEBUG,
"qdcount = %d, ancount = %d, nscount = %d, nrcount = %d, len = %d, id = %d, tc = %d, rd = %d, ra = %d, rcode "
"= %d, payloadsize = %d\n",
packet->head.qdcount, packet->head.ancount, packet->head.nscount, packet->head.nrcount, inpacket_len,
packet->head.id, packet->head.tc, packet->head.rd, packet->head.ra, packet->head.rcode,
dns_get_OPT_payload_size(packet));
/* get question */
for (j = 0; j < DNS_RRS_END && domain[0] == '\0'; j++) {
rrs = dns_get_rrs_start(packet, (dns_rr_type)j, &rr_count);
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) {
dns_get_domain(rrs, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass);
tlog(TLOG_DEBUG, "domain: %s qtype: %d qclass: %d\n", domain, qtype, qclass);
break;
}
}
if (dns_get_OPT_payload_size(packet) > 0) {
has_opt = 1;
}
/* get query reference */
query = _dns_client_get_request(domain, qtype, packet->head.id);
if (query == NULL) {
return 0;
}

line 1828 checks udp packet format.
line 1867 checks TXID.

What's missing is a check of the server address.
I wonder if adding server address checking can avoid this problem?

In addition, if there is a cache poisoning attack similar to GFW, I think it is a problem with the UDP DNS protocol. There may be no solution except DNSSEC, DOT, and DOH.

@idealeer
Copy link
Author

idealeer commented Oct 1, 2024

Yeah. SmartDNS does check the txid and src port. Also, it will ignore malformed response packets. But if it receives an icmp error message (only validating the inner 4 tuples while not checking the txid), it will terminate and stop receiving any promising legal response.

@pymumu
Copy link
Owner

pymumu commented Oct 1, 2024

Is there a way to reproduce the problem? Or any suggestions for a fix?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants