This blog is part of our Rails 6 series.
In a DNS Rebinding attack, a malicious webpage runs client-side script when it is loaded, to attack endpoints within a given network.
What is DNS Rebinding attack?
DNS Rebinding can be summarized as follows.
- An unsuspecting victim is tricked into loading rebinding.network which is resolved by a DNS server controlled by a malicious entity.
- Victims web browser sends a DNS query and gets the real IP address, say 24.56.78.99 of http://rebinding.network. This DNS server also sets a very short TTL value ( say 1 second ) on the response so that the client won't cache this response for long.
- The script on this webpage cannot attack services running in local network due to CORS restrictions imposed by victims web browser. Instead it starts sending a suspicious POST request to http://rebinding.network/setup/reboot with a JSON payload {params: factory-reset}.
- First few requests are indeed sent to 24.56.78.99 (real IP address), with the DNS info from the cache, but then the browser sends out a DNS query for rebinding.network when it observes that the cache has gone stale.
- When the malicious DNS server gets the request for a second time, instead of responding with 24.56.78.99 (which is the real IP address of rebinding.network), it responds with 192.168.1.90, an address at which, a poorly secured smart device runs.
Using this exploit, an attacker is able to factory-reset a device which relied on security provided by local network.
This attack is explained in much more detail in this blog post.
How does it affect Rails?
Rails’s web console was particularly vulnerable to a Remote Code Execution (RCE) via a DNS Rebinding.
In this blog post, Ben Murphy goes into technical details of exploiting this vulnerability to open Calculator app (only works in OS X).
How does Rails 6 mitigate DNS Rebinding?
Rails mitigates DNS Rebinding attack by maintaining a whitelist of domains from which it can receive requests. This is achieved with a new HostAuthorization middleware. This middleware leverages the fact that HOST request header is a forbidden header.
1# taken from Rails documentation 2 3# Allow requests from subdomains like `www.product.com` and 4# `beta1.product.com`. 5Rails.application.config.hosts << ".*\.product\.com/"
In the above example, Rails would render a blocked host template, if it receives requests from domains outside of above whitelist.
In development environment, default whitelist includes 0.0.0.0/0, ::0 (CIDR notations for IPv4 and IPv6 default routes) and localhost. For all other environments, config.hosts is empty and host header checks are not done.