Subdomain Takeover: Going for High Impact

When I and other guys in the web application security started posting stuff around subdomain takeover, it has become increasingly hard to find new cases in the public bug bounty programs. There was more competition than ever, but also, cloud providers such as AWS or Heroku started to implement mitigations to prevent subdomain takeovers in the first place. At the same time, bug bounty programs begin to set clear rules for subdomain takeover reports, mostly falling into Medium severity.

High Impact Subdomain Takeover

For someone like me, who deeply explored the realms of takeovers as well as their implications, this bothered me a lot. Not the fact that I am unable to find more "low hanging fruit", but rather that companies are taking a blindfolded view about the impact of subdomain takeovers in their infrastructure. I thus started to think about every possible escalation you can make to showcase the high impact this problem can have. This post explains my conclusions.

Cloud Provider Matter

Don't get me wrong. I still get a lot of subdomain takeover cases each month. However, as I explained above, most vulnerable cloud providers took a radical step and started to mitigate such problems in different ways:

  • Disallowing to register a custom domain name under a different account. For instance, if a domain takeover.example.com was registered under account1, the provider doesn't allow to register it under account2
  • Adding domain verification. In order to add a custom domain, you are required to provide proof that you actually own the domain. This usually takes form in adding TXT records to the DNS which of course you, unfortunately, don't have access to.
  • Adding entropy. Some services generate a random string that is a required part of the CNAME record in order to prevent takeovers. This is usually a strong enough defense since API rate limits won't allow you to brute force it (or the range of possibilities is really large). This is done for example in AWS ELB.

You should refer to https://github.com/EdOverflow/can-i-take-over-xyz in order to verify whether some provider is vulnerable or not.

In order to plan the possible escalation paths, you also need to know what the cloud provider allows you to do with the takeover domain. Unless you are able to point the domain to your VPS instance, you will pretty much be limited with some functionality. For instance:

  • Amazon S3 — Allows to host static content, but you won't be able to execute dynamic content such as Python scripts in the backend.
  • Microsoft Azure CloudApp — Allows specifying dynamic container, however, you don't get the freedom of fully controlling the deployed environment.

The best takeover you can hope for is Microsoft TrafficManager. This allows you to specify your own A records once the victim does a DNS resolution. Once you point it to your VPS instance, you are pretty much unrestricted.

It is important to think about obtaining a valid SSL certificate. When the domain points to your VPS instance, it is straightforward to just request a Let's Encrypt cert using certbot and the full process is done automatically. In cases such as Amazon Elasticbeanstalk, you are not able to install certbot in the environment. You are still able to obtain it manually by creating a valid HTTP endpoint with the specified string and signed nonce as requested by Let's Encrypt validation. Certificates will be an important part of the next sections.

Before going forward, I want to share a pretty interesting story I had when obtaining a certificate for a domain I just took over. The setting was just perfect: I was able to point the domain to my server and went for a high impact. The first thing I tried was obtaining a valid SSL certificate. However, the automatic certbot process failed without any indication of why. My manual effort for Let's Encrypt failed as well. Then I opted for a paid certificate using a provider that accepted HTTP validation. It failed as well. When I tried a third provider, that's where things started to get clear. My request for a certificate was denied with the message that the policy forbids to issue a new certificate for a domain ███.com. It was the first time I came across something like that. You know a company is taking web security seriously if they have this kind of defense-in-depth measures in place.

All of the following escalation paths pretty much go hand in hand. I would assume that the takeover we got is the most liberal (in other words, you are controlling the whole instance). Other restricted environments such as Elasticbeanstalk might require a couple of tweaks to work.

XSS

My first use-case is to showcase a stored XSS on the domain that was taken. The proof-of-concept is as straightforward as creating a new HTML file and pasting the Javascript code in it. Sometimes, stored XSS are valued more than subdomain takeover. For the XSS payload itself, I usually go with alert(document.cookie).

With the XSS possibility, you can also showcase a possible phishing scenario where you clone the login page of the targeted organization and place it in the domain you now "own". I was able to take over a domain that had a form of auth.example.com which is the perfect candidate for phishing attacks.

Account Takeover

Usually, a session cookie for the login session is set to have secure and httpOnly. The former means that you can access cookies only if the page has a valid SSL certificate and the latter says that it cannot be accessed using Javascript, only in HTTP requests to the backend server.

It is fairly common to bound a session cookie to a wildcard domain such as *.example.com. For instance, let's say there is a login gateway on auth.example.com, but there are multiple apps such as customer.example.com, app.example.com that want to be able to access the login session. An SSO solution thus tends to work on the wildcard domain. With the domain you have just taken over, you can access this session cookie easily.

To achieve a full account takeover, you need to force the victim into visiting the domain that was vulnerable to subdomain takeover. Then a simple backend script can retrieve the session cookie (note that this example simply reflects the value to the user but it can be easily modified to store the values):

#python3

import Flask

app = flask.Flask(__name__)

@app.route('/')
def gimme_my_cookies():
    return flask.jsonify(flask.request.cookies)

if __name__ == '__main__':
    app.run(port=80)

Once you have the correct session token, you can change the cookie in the browser and access the victim's account (assuming there is no other security prevention).

CSRF

Similar to the examples above, CSRF can be sometimes done when the target application is assuming that the wildcard domain is safe. This is also true for inter-app communication using postMessage API where the Javascript code is responsible for detecting the sender and based on that allowing the action. The regexes for this verification are usually set for *.example.com.

Authentication Bypass

Rather than explaining it on my own, I would point you to the great report submitted by Arne Swinnen on HackerOne. Although the attack complexity is pretty high, in some cases you can achieve the same behavior.

Hopefully, this shines a new light on how you can think of subdomain takeover bugs in the future. If you know about any other escalation path, I will be more than happy to update the post with the credits.

Until next time!

Patrik

Buy Me A Coffee