Dominating and Escalating Subdomain Takeovers

For information on automating the detection of vulnerable subdomains, see Rupert, the script I wrote for just that.

A subdomain takeover is a vulnerability that enables an attacker to take control of one of your subdomains. This happens when the 3rd-party domain a CNAME is pointing to is maliciously influenced. The impact is easy to see if an old Shopify instance is claimed and now "shop.example.com" points to a Shopify not owned by the root organization. The impact extends past fake shops and simple defacement, however. Let's take a look at some ways a simple subdomain takeover can be used to fully compromise user accounts.

During the authentication process if the "response_type" parameter is set to "code" a one-time code is sent to the value of the "redirect_uri" parameter. This code is used to validate identities across products. To avoid a malicious link redirecting to "attacker.com" the "redirect_uri" is limited to the root domain, so codes can only be sent domestically. Some OAuth2 configurations fail to validate properly and can be bypassed in a multitude of ways, but the most common by far is allowing arbitrary subdomain. For example, the root domain "example.com" will allow "shop.example.com" as well as "does-not-exist.example.com". By taking over a subdomain we can then use that as the "redirect_uri" and craft a malicious link that once clicked will send us the user's OAuth2 code.

BONUS: redirect_uri's are notoriously misconfigured, try "example.com.attacker.com" and skip the takeover process.

When setting cookies some are set with *.example.com, essentially allowing every subdomain to access that cookie. Oftentimes session management cookies can be accessed via any subdomain, including the one just taken over.

Cross-origin resource sharing (CORS) is how browsers prevent "attacker.com" from sending a client-side request to "Gmail.com" and stealing your data. An "Access-Control-Allow-Origin'' response header can be returned to tell the browser which domain the website trusts to access its data. CORS is limited, however, only allowing one domain to be specified in the response header (comma delimited does not work). As a result, CORS response headers are commonly dynamically generated by checking the origin of the request and validating. This is useful for when you want user API data, for example, to be available across all of the organization's subdomain. The problem is when developers want to increase performance and eliminate a traditional domain whitelist and instead validate using regular expressions, matching every subdomain regardless of if it really needs access or not. An attacker controlled subdomain can make an Ajax request on behalf of the user and successfully siphon data through the browser.