Subdomain Takeover: Identifying Providers

Recently, I have come across an interesting list of domain suffixes used by cloud providers which are vulnerable to subdomain takeover. Although the list is pretty accurate, it is still a raw list that needs to be further processed. In this post, I will explain how to process this list correctly and how to identify new vulnerable cloud services using simple methods.

List of subdomain takeover domains

Architecture

Firstly, let's recap and begin by explaining how the usual cloud provider becomes vulnerable to subdomain takeover. When people create cloud resources, they want them to be accessible through their domain. After registering, for instance, a new Heroku app, the engine will give you subdomain in form APP_NAME.herokudns.com. Heroku recognizes that customers want such applications to be exposed through their domain (e.g. herokuapp.example.com) so they provide a way to set custom domain to their cloud resource.

Due to the technical simplicity, such architecture is often achieved through the use of virtual hosting. You can see the basic idea on the following diagram:

Heroku virtual hosting

The reason why virtual hosting is preferred is that providers like Heroku don't want to dedicate the whole instance to one application. This also means having dedicated IP address (A record) for each application on *.herokudns.com. It is easier for them to hide the content behind a couple of load balancers and let them decide what content to return based on HTTP Host header. You can confirm this by resolving two different *.herokudns.com domains and comparing the returned A records. They will be the same.

After the HTTP request arrives to load balancer, it determines what content to return based on HTTP Host header assignment:

Heroku virtual hosting request

Custom domains provide a little problem in this architecture. We need to provide the name of custom domain beforehand, so the load balancer knows to which domain it corresponds to when the request arrives. This is the whole problem of subdomain takeover: Having CNAME set to cloud provider domain, but not setting this custom domain in your cloud provider portal.

Some cloud services that use virtual hosting setup:

  • Amazon S3
  • Heroku
  • Shopify
  • Readme.io
  • ...

On the other hand, there are still some cloud providers that don't rely on virtual hosting but simply creates a dedicated instance (and thus IP address) for each cloud resource. We don't rely on Host header, and the target instance thus accepts any HTTP Host header provided. In other terms, this means that we don't need to specify our custom domain beforehand. Any domain with correct CNAME record will work. The prominent cloud provider in this category is Microsoft Azure.

Verification

Based on this explanation, we can divide the cloud providers into two categories:

  • Virtual hosting oriented (VHO) — services that require to specify custom domain beforehand.

  • Non-virtual hosting oriented (NVHO) — services that don't require to specify custom domain beforehand.

As we know from the previous post, subdomain takeover monitoring is a continuous process. We should aim for creating the automation that provides a high success rate in finding potential takeovers. My approach is to create so-called signatures that technically explain each vulnerable cloud service, like so:

{
    "name": "Ghost",
    "formats": ["*.ghost.io"],
    "responses": [
        "403 Forbidden",
        "The thing you were looking for is no longer here, or never was"
    ],
    "response_codes": [404, 403, 302, 200]
}

We have four main parts here:

  • Name — This is the identification of the cloud service
  • Formats — List that describes various formats of domains that the cloud provider uses. These domains are then used in CNAME records.
  • Responses — What strings are we looking for in HTTP responses of vulnerable domain.
  • (Optional) Response Codes — What HTTP response codes are we looking for in vulnerable domain.

These signatures are then used by a scanner that takes a list of domain names for verification and checks their HTTP responses against this signature list (this process was explained in the previous post). Indeed, Ghost is not the only vulnerable cloud provider out there. The next section describes how to identify whether the provider is vulnerable and how to write such signatures correctly.

Virtual hosting oriented

This is the majority of cloud providers out there. A common theme across these providers is the fact that they tend to respond with a predefined error page for HTTP Host header they don't recognize. Imagine this: You request a Heroku application via some *.herokudns.com, but you set the HTTP Host header to a value that is not set in Heroku portal. As I explained before, Heroku has no way of knowing to which application does this domain name relate to, unless explicitly specified in Heroku app settings. So how does Heroku respond to such request?

Heroku Error

We can use this to our advantage:

  1. Identify domains that have CNAME to *.herokudns.com.
  2. Make HTTP request to it (with correct Host header)
  3. Check if the known error page strings (e.g., "Build something amazing") are present in HTTP Response body
  4. If yes, there is a potential for subdomain takeover

Now that we know the motivation behind these error messages let's look on how to create a signature. I always like to have fresh FDNS dataset handy during this task. If I want to check whether some provider is vulnerable, this is my usual workflow:

  1. Identify what domains they use. This can be simply checked using Google or creating the cloud resource on your own. Usually query like <cloud provider name> custom domain will do the job. For Heroku, it is *.herokudns.com and sometimes *.herokuapp.com. Documentation can be found here. The Format part of the signature is now done.
  2. Grep some CNAMEs of such domain from FDNS: zcat fdns.gz | grep cname | grep herokudns.com. You need at least three domains.
  3. Do DNS (A) resolution for these three domains. If the A records match, you have confirmed virtual hosting setup.
  4. Now it is time to identify what the error page looks like. This can be simply done by creating an HTTP request and forging Host header to something non-existing, like so: http GET http://<something>.herokudns.com Host:totallynonexistingdomainhere.com.
  5. From the response, identify some unique strings that are used as error messages. Responses part of the signature is now done.
  6. Now it's time to finish the signature with Name which is trivial.

With that, you are pretty much done. What I also like to do is to register the free account in the cloud provider I am testing and go through the whole workflow of setting the custom domain name. In some cases, the cloud provider is doing domain verification (e.g., Squarespace) so the takeover is not possible whatsoever. In other cases, they require you to have exact CNAME set in your DNS records which are not always possible.

This virtual hosting setup and technique are actually what Domain Fronting is all about.

Non-virtual hosting oriented

This category is pretty simple to check. When following the workflow described above, point #3 is what decides between VHO and NVHO. If you see that the A records of this domain don't match, there is a high chance that the provider is not using virtual hosting. Fortunately, checking these instances is very simple, all you need to do is check, whether the provider generated domain responds with NXDOMAIN or not. There is no need to write full signatures for NVHO providers; they should be check separately.

Microsoft Azure is the best example of NVHO provider. They use several domains for their services:

"*.cloudapp.net"
"*.cloudapp.azure.com"
"*.azurewebsites.net"
"*.blob.core.windows.net"
"*.cloudapp.azure.com"
"*.azure-api.net"
"*.azurehdinsight.net"
...

Now, when you see CNAME pointing to one of these domains, you need to check whether the CNAME domain is NXDOMAIN or not. That's it.

For VHO and NVHO, these are not the strict rules, and there are indeed exceptions. I provided the guidelines which work for the majority of cloud providers that I tested in the previous months.

If you do your research in subdomain takeovers, consider contributing to an open-source project called can-i-take-over-xyz. I will be adding my research there.

Check out my other posts about subdomain takeovers:

Until next time!

Patrik