saddns.net/4

参考: https://knqyf263.hatenablog.com/entry/2020/11/19/200900

/4.3

4 INFERRING DNS QUERY’S SOURCE PORT

In this section, we will describe the idea and procedure of inferring DNS source ports. We will also measure the vulnerable software and in-the-wild population when feasible.

4.1 Analysis of UDP Source Port Scannability

UDP is a stateless protocol and hence fundamentally different from TCP. More specifically, it is stated in the UDP programming guideline (RFC 8085 [24]) that “UDP datagrams may be directly sent andreceived, without any connection setup. Using the sockets API, applications can receive packets from more than one IP source address on a single UDP socket.”

Furthermore, to ensure that an application will receive data from only one particular source address, “these applications MUST implement corresponding checks at the application layer or explicitly request that the operating system filter the received packets.”

These are surprisingly under-scrutinized statements.

On a first glance, they may be interpreted as applicable to UDP servers only, which can bind to a local port, and subsequently receive packets from “any remote IPs”.

Surprisingly, from our experiments, it applies to UDP clients as well —

a client calling sendto() on a specific remote IP and subsequently 
recvfrom() on the same socket can
technically receive packets from “any other IPs” as well. 

We have verified this behavior on all modern operating systems, including Windows, Linux, and MacOS.

This nuanced behavior has a profound impact on what an attacker can learn 
through a trivial UDP port scan — 
when a DNS server issues a query, its source port effectively becomes open to the public. 

This allows an attacker to simply scan the ephemeral port range with any UDP packet, which will trigger nothing upon hitting the correct port (as the probe will be accepted by the OS but discarded at the application layer), or an ICMP port unreachable message upon missing it (by design).

Stub ResolverForwarderRecursiveResolverAuthoritativename servers1.vctm.com A ? ②Muting (§5)1.vctm.com A ? sp=x, dp=53, id=y1.vctm.com A v.c.t.m1.vctm.com A a.t.k.r, sp=53, dp=x1.vctm.com A a.t.k.rdp=0, 1, 2, ……, x①Port Scan (§4)Cachedvctm.com NSDNS ServerAttackerid=0, 1, 2, ……, ysp=source portdp=destporta.t.k.r=maliciousIPSession 4E: Network Security CCS '20, November 9–13, 2020, Virtual Event, USA1339^L

Next, the UDP programming guideline (RFC 8085) further states that “Many operating systems also allow a UDP socket to be connected, i.e., to bind a UDP socket to a specific pair of addresses and ports.”

Indeed, modern socket APIs allow connect() on a UDP socket but “this is only a local operation that serves to simplify the local send/receive functions and to filter the traffic”.

As a result, when a DNS query is issued from a source port to a particular 
destination IP address and port, the OS will accept incoming packets
from only the same remote IP and port. 

Specifically, when testing the behavior on real network stacks, we find that they will reject a packet with either a wrong IP or port, and respond with an ICMP port unreachable message (as if the packet was a port scan attempt).

This effectively prevents the source port of a DNS query from being scanned directly.

In summary, the scannability of source port is dependent on the implementation of DNS software, i.e., whether a connect() API call is issued on the UDP socket.

Interestingly, we find that out of the three most popular DNS forwarder and resolver software BIND, Unbound, and dnsmasq, only BIND uses connect().

Nevertheless, we develop different scan methods that can work for each (described in §4.3 and §4.4, overcoming the challenge outlined in the next section.

4.2 ICMP Rate Limit Challenge

A major hurdle to scan UDP source ports efficiently is the commonly deployed rate limit of outgoing ICMP error messages on endhosts.

Even in the simple case where a source port is public-facing and can be scanned directly by any IP address, an attacker’s scanning speed is limited by the number of allowable ICMP packets per second (a signal indicating a source port is not in use).

Historically, ICMP rate limit was first recommended to limit the resource consumption on a router (described in RFC 1812 [7]) where an attacker can force it to generate a high volume of ICMP error messages.

Today, the rate limit mechanism is universally implemented by all major OSes. Here we focus on the Linux’s ICMP rate limiting behavior as it is the most popular server OS, but will briefly describe the behaviors of other OSes afterwards.

For Linux, there are both a per-IP and global rate limit on how many ICMP error packets can be sent out per second.

The per-IP rate limit was historically introduced in the very early versions of Linux, i.e., present in kernel 2.4.10. The global rate limit was introduced in kernel 3.18 as a way to alleviate the expensive per-IP rate limit check (e.g., red-black tree operations) [22].

By default, the per-IP rate limit is one per second (with an accrued max burst of 6) which will severely restrict the scanning speed; the global rate limit is effectively 1,000 (with periodic max allowable bursts of 50).

Both are implemented in token bucket style, with the per-IP tokens recovering at a rate one per second and the global token recovering at a “nominal” rate of one per millisecond (but the actual token increment happens only after at least 20ms has elapsed since the last increment). The number of available tokens is capped at 50 at all times.

We also tested Windows Server 2019 (version 1809), MacOS 10.15 and FreeBSD 12.1.0, all of which have global ICMP rate limits. Specifically, their limits are 200, 250 and 200 respectively.

Besides, none of them has a per-IP rate limit.

MoinQ: DNS/毒盛/2020/saddns.net/4 (last edited 2020-11-23 09:28:20 by ToshinoriMaeno)