Verder naar navigatie Doorgaan naar hoofdinhoud Ga naar de voettekst

State of DNS Rebinding in 2023

27 april 2023

door Roger Meyer

Different forms of DNS rebinding attacks have been described as far back as 1996 for Java Applets and 2002 for JavaScript (Quick-Swap). It has been four years since our State of DNS Rebinding presentation in 2019 at DEF CON 27 (slides), where we introduced our DNS rebinding attack framework Singularity of Origin. In 2020, we studied the impact of DNS over HTTPS (DoH) on DNS rebinding attacks.

This update documents the state of DNS rebinding for April 2023. We describe Local Network Access, a new draft W3C specification currently implemented in some browsers that aims to prevent DNS rebinding, and show two potential ways to bypass these restrictions.

We also discuss the effects of WebRTC IP address leak mitigation, and DNS Bit 0x20 on DNS rebinding attacks.

Local Network Access

Local Network Access (previously called Private Network Access or CORS-RFC1918) is a W3C draft specification intended to mitigate the risks of unintentional exposure of web services on a client’s internal network. It does this by segmenting address ranges into different address spaces, and will behave differently depending upon the origin of the request. If the request is to a more private address space than the origin, it will first perform a CORS Preflight request to the host, allowing the host to perform access control.

While this might be a draft standard, it has already been implemented in Chrome and some derived browsers (e.g. Edge).

Local Network Access Address Spaces

The specification defines the following three broad IP address spaces:

  • loopback: The loopback address space contains the local host only (127.0.0.0/8, ::1/128).
  • local: The local address space contains addresses that are reachable only within the current network (e.g., 10.0.0.0/8, 100.64.0.0/10, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16, fc00::/7, fe80::/10).
  • public: The public address space contains all other addresses.

Local Network Requests

The concept of a local network request is defined as follows (defined in “2.2. Local Network Request” of the specification):

A request is a local network request if request’s current URL’s host maps to an IP address whose IP address space is less public than request’s policy container’s IP address space.

This prevents the following two conditions:

  1. Network access to the loopback address space from an origin that is either in the local or public address space. This is because loopback is less public than the local or public address space.
  2. Network access to the local address space from an origin that is in the public address space. This is because local is less public than the public address space.

CORS Preflight

Access to less public networks will generate a CORS preflight request. The Local Network Access specification defines the following two additional CORS headers:

  • The Access-Control-Request-Local-Network client request header indicates that the request is a local network request
  • The Access-Control-Allow-Local-Network server response header indicates that a resource can be safely shared with external networks

Let’s walk through an example scenario. An attacker entices a home user to browse to the attacker’s web site at attacker.com. The attacker’s malicious JavaScript triggers a request to the victim’s local router (router.local) trying to modify the DNS settings. As the request to router.local is more private than the attacker’s host in the public address space, the browser will initiate a CORS preflight request:

OPTIONS /set_dns?... HTTP/1.1
Host: router.local
Access-Control-Request-Method: GET
Access-Control-Request-Local-Network: true
Origin: https://attacker.com
...

Note the request header Access-Control-Request-Local-Network: true indicating to the router that this request is a local network request. If the router does not understand this request and does not send a valid response, the browser will block access to router.local. If the router wants to allow access from external networks, the router will return the following CORS preflight response:

HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://public.example.com
Access-Control-Allow-Methods: GET
Access-Control-Allow-Credentials: true
Access-Control-Allow-Local-Network: true
Content-Length: 0
...

Note the Access-Control-Allow-Local-Network: true notifying the browser that the router allows external network access.

Local Network Access Bypasses

Now that we have a good foundational understanding of Local Network Access, we can talk about the two known ways to bypass it.

Local Network Access Bypass using 0.0.0.0

What is the 0.0.0.0 IP address? According to Wikipedia, “0.0.0.0 is a non-routable meta-address used to designate an invalid, unknown or non-applicable target”. Nevertheless, using 0.0.0.0 allows us to access the localhost on Linux and macOS systems.

During our initial research of DNS rebinding attacks, we documented this attack vector allowing DNS rebinding protection bypasses.

Using the IP address 0.0.0.0 also bypasses local network access protections in Chrome (and Edge). We filed a Chromium bug report in February 2022; the issue can be tracked in Chromium bug 1300021.

This allows us to perform DNS rebinding attacks targeting services listening on the localhost of Linux and macOS systems in Chrome, in approximately 3 seconds.

Local Network Access Bypass using a Router’s Public IP Address

In 2010, Craig Heffner discovered and developed a DNS rebinding technique, covered during our DEF CON 27 presentation, to exploit the weak host model, which can be used to bypass Chrome’s local network access protection. In this bypass, we access an internal router’s web interface (e.g. WiFi router) through the public IP address instead of the internal (private) IP address.

Most WiFi routers allow access to their management web interface only through the internal interface using the private IP address to prevent access from the Internet. As the router usually has a public IP address assigned, some routers allow access to the web interface through the public IP address if the access comes from the internal network interface (Martian packet).

This allows us to perform DNS rebinding attacks targeting the public IP address where local network access does not apply. We have successfully tested DNS rebinding in Chrome targeting a home router’s public IP address. The attack works particularly well with Netgear routers.

Local Network Access Affects Singularity’s JavaScript Port Scanner

Singularity includes a browser based JavaScript port scanner to discover HTTP services accessible from the victim’s host, including internal networks, and to launch DNS rebinding attacks in an automated manner. The port scanner is implemented using the JavaScript Fetch API. If a Fetch request does not return an error, or does not timeout, the port is determined as being accessible (open and not firewalled), and a candidate for DNS rebinding.

Local network access blocks Fetch requests if the target is less public than the request’s address space, as explained above. This prevents the port scanning of loopback and local direct IP address spaces in Chrome based on the Fetch API. While this affects the port scanner when using Chrome, the scanner now only returns ports that we can rebind to; this means that the port scanner is still well suited for its purpose of identifying potentially exploitable services using DNS rebinding. The local network access Chrome bypass using the IP address 0.0.0.0 also works for port scanning, and permits attackers to (indirectly) access services bound to the victim host internal network interfaces. Note that the JavaScript port scanner still works in non-Chrome browsers such as Firefox and Safari.

Full HTTP service enumeration (including services that are not exploitable using DNS rebinding) in Chrome is still possible despite local network access using techniques exploiting timing side channel leaks, such as implemented in Nikolai Tschacher’s port scanner.

WebRTC Leaking the Local IP Address

Web Real-Time Communication (WebRTC) allows browsers to manage real-time peer-to-peer connections with the websites they visit. WebRTC enables voice and video communication to work in web pages, without the need of extensions or other additional software.

Previous implementations of WebRTC in browsers accidentally exposed a user’s local IP address, and associated network range. The local IP address is the client’s IP address in the private home, or corporate network. These are commonly private network IP addresses behind a NAT gateway.

Knowing the local IP address allows attackers to perform targeted DNS rebinding attacks without the need to know or guess the victim’s network IP range. Singularity includes IP address and network range detection functionality by abusing WebRTC in the attack automation feature as well as the port scan functionality.

Chrome, Edge, Firefox, and Safari now all obfuscate the private IP addresses of endpoints to prevent the leak during the ICE candidate gathering. Singularity can therefore no longer discover the victim’s local IP address in recent browsers. The Singularity attack framework can use the local IP address leak during its IP address scan to improve the efficiency of automated DNS rebinding attacks for older browsers. For recent browsers, automated DNS rebinding attacks still work, but may require an attacker to know or guess the victim’s private IP address range, or it will take longer to identify vulnerable targets within that range. Note that this does not affect the detection, and exploitation of vulnerable services bound to 0.0.0.0, as explained in the previous section.

DNS Bit 0x20

Since around December 2022, we noticed that some DNS rebinding attacks were failing randomly. By looking at the log files of the Singularity attack framework we noticed DNS queries that contained random capitalization in the DNS name.

For example, we saw DNS requests such as the following:

2023/01/05 10:44:08 DNS: Received A query: S-35.185.206.165-127.0.0.1-1672656847789-Rr-e.d.ReBInD.IT. from: 172.253.2.2:28060
2023/01/05 10:44:08 DNS: Parsed query:  {    }, error: cannot find start tag in DNS query

2023/01/02 10:54:08 DNS: Received A query: S-35.185.206.165-127.0.0.1-1672656848109-rr-e.d.REBInd.It. from: 172.253.2.2:34138
2023/01/02 10:54:08 DNS: Parsed query:  {    }, error: cannot find start tag in DNS query

Notice that the DNS name (S-35.185.206.165-127.0.0.1-1672656847789-Rr-e.d.ReBInD.IT) is randomly capitalized (i.e. ReBInD.IT instead of rebind.it). This caused issues with the query parsing functionality. Singularity expects the initial s- as the start of the query and the trailing -e as the end (see the Singularity DNS query documentation). With randomized capitalization, Singularity was unable to correctly parse the query.

The reason for the random capitalization was the introduction of the IETF draft Use of Bit 0x20 in DNS Labels to Improve Transaction Identity. In January 2023, Google started deploying this feature in certain regions. The goal of Bit 0x20 is to make cache poisoning attacks less effective by using the capitalization to expand the range of possibilities of the 16-bit transaction ID in DNS queries.

We improved the reliability of DNS rebinding attacks in Singularity by lowercasing all incoming DNS queries to ensure consistent processing.

Recent DNS Rebinding Vulnerabilities

Security researchers keep discovering DNS rebinding vulnerabilities showing that these issues are still dangerous and exploitable. The following is a list of products that were discovered to be vulnerable to DNS rebinding in the year 2022:

– 2022-01-17 DNS rebinding vulnerability in H2 Console. This vulnerability was discovered by NCC Group and we wrote a payload to exploit this issue with Singularity.

– 2022-07-10 DNS rebinding vulnerability in Node.js (CVE-2022-32212).

– 2022-09-05 WordPress Unauthenticated Blind SSRF Via DNS Rebinding Vulnerability (CVE-2022-3590).

– 2022-11-22 SSRF via DNS Rebinding in Appsmith (CVE-2022-4096).

– 2022-11-22 RCE in Tailscale, DNS Rebinding, and You (CVE-2022-41924): The detailed write-up includes usage of our public Singularity Server, see “How to Create Manual DNS Requests to Singularity of Origin“.

Miscellaneous

Headless Chrome behaves the same as the desktop browser and the 0.0.0.0 IP address can be used to target services listening on the localhost to bypass local network access. Headless Chrome is commonly used for backend operations and can be exploited through Server-Side Request Forgery (SSRF) in many applications.

On the mobile side, DNS rebinding attacks on iOS using Safari still work reliably and fast. Attacks targeting services on the localhost can be exploited in 3 seconds (using 0.0.0.0 and the multiple answers (MA) strategy) and in less than 20 seconds for all other IP addresses (using DNS cache flooding). On Android, the mobile Chrome browser includes the same limiting factors as Chrome on desktop described above.

Conclusion

While Local Network Access makes it harder, it is still possible to execute DNS rebinding attacks. Local Network Access breaks fetch() based HTTP port scanners. Singularity’s port scanner (using Chrome) now only reports DNS rebindable HTTP services. However, it is still feasible to enumerate all (non-rebindable and rebindable) HTTP services through the use of timing side channel leaks. Common browsers have fixed the WebRTC private IP address leak, which makes it more challenging to effectively perform DNS rebinding attacks, as attackers now have to guess or know private IP address ranges.

Author

Roger Meyer (@sanktjodel)

Acknowledgments

The author would like to thank Dave Goldsmith and Gérald Doussot for their thorough and insightful reviews.