Building A Subdomain Takeover Monitor
In a previous article, we talked about the different types of subdomain takeovers and how hackers can use them to attack SSO systems. The impact of a subdomain takeover can vary. At the very least, subdomain takeovers enable attackers to launch sophisticated phishing campaigns. In some cases, this can lead to Cross-Site Scripting (XSS) attacks or malicious redirects. And, when a site uses shared-session SSO, this could even lead to session theft and account takeovers! Unfortunately, subdomain takeover attacks are nearly impossible to detect. However, you can reliably prevent them. In this post, let’s discuss how you can build a subdomain takeover monitoring system!
Subdomain Takeover Recap
A subdomain takeover is when an attacker takes control of a company’s unused subdomain. This happens when a stale DNS entry points to a domain that is available for registration. Let’s say a company hosts its site on a third-party service, such as AWS or GitHub Pages. When this third-party site is deleted, a CNAME record that points from the company’s subdomain to that third-party site will remain unless someone removes it. But since the third-party site is now unclaimed, anyone who registers that site on the third-party service gains control over the company’s subdomain. For example, an organization hosts its subdomain,
abc.example.com
, on the GitHub page abc_example.github.io
. The company later decides to delete the GitHub page but forgets to remove the CNAME record pointing abc.example.com
to abc_example.github.io
. Since abc_example.github.io
is now unclaimed, an attacker can create a GitHub page at abc_example.github.io
. And, because abc.example.com
still points to abc_example.github.io
, the attacker now has full control over abc.example.com
. Now when a user browses abc.example.com
, the user would see an attacker-controlled site. The key to preventing subdomain takeovers is to routinely go through all of your DNS entries and remove the entries that are pointing to unused external services.Find Your Subdomains
First, you need to build a list of all your subdomains. You can produce a list of subdomains you want to monitor for takeovers by going through your DNS entries. Compile a list of subdomains with CNAME entries that point to a live, third-party site. Whenever you start using a new service with a new subdomain, add it to this list of monitored subdomains.
a1.example.com
b1.example.com
support.example.com
external.example.com
Try To Takeover Subdomains
Next, list the third-party providers that your websites use. Even in the case of a dangling CNAME, not all providers are vulnerable to takeovers. If your sites are exclusively hosted on services that are not vulnerable to subdomain takeovers, you don’t have to scan them for potential takeovers. You can check if your providers are vulnerable here: Can I take over XYZ? Then, determine the “signature” of a possible subdomain takeover for each external service that you use. Most services would have a custom
404 not found
page that indicates that the page is not registered. You can use these pages to detect a potential takeover. For example, a page that is hosted on GitHub pages (with github.io
in the URL) is vulnerable if the sentence There isn’t a Github Pages site here
is returned in the HTTP response.SERVICES = {
“AWS/S3”: {
“url_keywords”: [“amazonaws”, “s3”],
“signatures”: [
“The specified bucket does not exist”, “NoSuchBucket”, “randombucket-assets”,
],
},
"Github": {
"url_keywords": ["github.io"],
"signatures": [
"There isn't a Github Pages site here",
],
},
"BitBucket": {
"url_keywords": ["bitbucket"],
"signatures": [
"Repository not found",
],
},
"Heroku": {
"url_keywords": ["herokudns", "herokuapp", "herokussl"],
"signatures": [
"no such app", "no-such-app"
],
},
}
Python
Once you have identified all the providers in use, you are ready to begin scanning your subdomains for takeovers! The next step is to determine the provider for each subdomain and see if the corresponding signatures show up on the pages. For example, if
a1.example.com
points to a1_example.github.io
, the page should be scanned for the phrase There isn’t a Github Pages site here
. Send an HTTP request for each subdomain and scan for the signatures in the HTTP response. If one of the signatures is detected, the page might be vulnerable to takeover. Here's some Python code illustrating this:import dns.resolver
import requests
import config
def resolve_cname(host):
# find the base domain of the CNAME
def determine_provider(domain, providers):
# determine the provider based on url_keywords
def request_page(host):
# send a get request to host and returns the HTTP response status code and response content
def scan_content(content, signatures):
# check if the signatures of that provider are in the contents of the returned page
def scan_for_takeovers(subdomains, providers):
for d in subdomains:
print("Checking subdomain: %s." % d)
base_domain = resolve_cname(d)
provider, signatures = determine_provider(base_domain, providers)
status, content = request_page(d)
if status: # if request successful
scan_content(content, signatures)
Python
Remember to also check for the wildcard DNS entry. If you point a wildcard DNS entry to an external service and do not add a wildcard entry in your third-party configurations, attackers might be able to claim any subdomain they want on the service! You can check for the wildcard entry by adding a random subdomain to your list of subdomains to scan.
Monitor for Second-Order Bugs
Monitoring for second-order takeovers is similar to monitoring for regular subdomain takeovers. First, you’ll need to keep track of all the links that you are embedding on your websites. You can extract these URLs and their domain names from the JS, CSS, link, and header tags on your pages. Next, you need to check these URLs for subdomain takeovers using the monitoring script that you have written!
Continuous Monitoring
Monitoring for subdomain takeovers should be a continuous process. You never know when a site is going to be taken down and when a subdomain takeover vulnerability could be introduced into your assets. A way of making this process more efficient is to let it run in the background and only notify you once a suspected takeover is found. You can set up a cronjob to run the script regularly, and email you once the monitoring system detects something fishy.
30 10 * * * cd /Users/vickie/scripts/security; python subdomain_takeover.py
And, in your Python script, you can include a notification mechanism that gets triggered if a potential takeover is found.
import dns.resolver
import requests
def scan_for_takeovers(subdomains, providers):
for d in subdomains:
print("Checking subdomain: %s." % d)
base_domain = resolve_cname(d)
provider, signatures = determine_provider(base_domain, providers)
status, content = request_page(d)
if status: # if request successful
if scan_content(content, signatures):
email_me()
Python
After the script notifies you of a potential subdomain takeover, you should verify it as quickly as possible. Attackers can take advantage of a subdomain takeover with very little work: all they need have to do is to register the subdomain on the service! Finally, if you’ve verified a detected subdomain takeover is not a false positive, you can resolve it by removing the dangling DNS record or reclaiming the subdomain on the third-party service. Now, add the continuous monitoring component to your script and you are all set to automatically detect subdomain takeovers!