HIGH dangling dnsbearer tokens

Dangling Dns with Bearer Tokens

How Dangling DNS Manifests in Bearer Tokens

A dangling DNS record occurs when a domain (often a subdomain) points to a service that has been deprovisioned, but the DNS entry remains. If an attacker can claim the underlying resource (e.g., an Azure App Service, an AWS Elastic Beanstalk environment, or a GitHub Pages site), they control the endpoint that the domain resolves to. When an application sends a Bearer token to that domain—typically in an Authorization: Bearer <token> header—the token is transmitted to the attacker‑controlled host.

Typical code paths where this appears include:

  • Configuration‑driven base URLs: const apiUrl = process.env.API_BASE_URL; followed by axios.get(`${apiUrl}/data`). If API_BASE_URL is set to a subdomain that later becomes dangling, every request leaks the token.
  • Dynamic service discovery: applications that resolve a service name from a Consul or Eureka registry and then build URLs like https://{service}.internal.company.com/api. If the registry entry is not removed after the service is decommissioned, the DNS may point to a reclaimable cloud resource.
  • Third‑party SDKs that construct endpoints from a tenant identifier: https://{tenant}.saasprovider.com/v1. A tenant that has been cancelled but whose DNS CNAME still points to the SaaS provider’s domain can be taken over.
  • Real‑world examples include CVE‑2020‑13942 (subdomain takeover of a Microsoft Azure subdomain leading to token theft) and OWASP API Security Top 10 2023, A1: Broken Object Level Authorization, where token leakage via unintended endpoints amplifies authorization bypasses.

Bearer Tokens‑Specific Detection

Detecting dangling DNS in the context of Bearer token transmission requires two correlated checks:

  1. DNS inventory: verify that each hostname used in outbound requests resolves to an IP address owned by the organization or to a known, non‑claimable service. middleBrick’s Inventory Management check builds a list of hostnames seen during the scan and cross‑references them with public cloud IP ranges and domain ownership data.
  2. Token exposure validation: confirm whether the Authorization header containing a Bearer token is sent to any of those hostnames. middleBrick’s SSRF check monitors outbound HTTP requests and flags when a token‑bearing request is directed to a host that resolves to a potentially claimable resource.

When middleBrick scans an API endpoint, it:

  • Extracts all URLs from OpenAPI/Swagger specifications (including $ref‑resolved paths) and from observed traffic.
  • Performs a DNS lookup for each hostname.
  • Compares the resolved IPs against AWS, Azure, GCP, and SaaS provider ranges that are susceptible to subdomain takeover.
  • If a match is found, it checks whether the scan traffic included an Authorization: Bearer header for requests to that hostname.
  • Reports the finding with severity, the affected hostname, and the specific endpoint that leaked the token.
  • Example of a middleBrick CLI invocation that would surface this issue:

    middlebrick scan https://api.example.com --output json
    

    The resulting JSON includes a dangling_dns finding under the ssrf category, with remediation guidance such as "Restrict outbound calls to an allow‑list of verified domains" and "Rotate any Bearer tokens that may have been exposed."

    Because middleBrick does not require agents or credentials, the check works purely from the unauthenticated attack surface, making it suitable for continuous monitoring in CI/CD pipelines via the GitHub Action:

    - name: Run middleBrick scan
      uses: middlebrick/action@v1
      with:
        api-url: https://staging.api.example.com
        fail-below: B   # fail the workflow if score drops below B
    

Bearer Tokens‑Specific Remediation

Remediation focuses on preventing the application from sending Bearer tokens to unverified or potentially claimable hostnames. The fixes are implemented at the client side where outbound requests are constructed.

1. **Strict hostname allow‑list** – maintain a list of domains that are owned and managed. Before issuing an HTTP request, validate that the URL’s hostname ends with an allowed suffix.

Example in Node.js using the built‑in url module:

const { URL } = require('url');
const ALLOWED_SUFFIXES = ['api.example.com', 'partner.example.net'];

function isAllowedHost(urlString) {
  try {
    const { hostname } = new URL(urlString);
    return ALLOWED_SUFFIXES.some(suffix => hostname.endsWith('.' + suffix) || hostname === suffix);
  } catch (_) {
    return false;
  }
}

async function fetchData(token) {
  const apiBase = process.env.API_BASE_URL; // e.g., https://api.example.com
  if (!isAllowedHost(apiBase)) {
    throw new Error(`Outbound call to unapproved host: ${apiBase}`);
  }

  const response = await fetch(`${apiBase}/resource`, {
    headers: {
      Authorization: `Bearer ${token}`
    }
  });
  return response.json();
}

2. **Short‑lived, audience‑bound tokens** – issue tokens with a short expiry (e.g., 5‑15 minutes) and include an aud claim that matches the intended service’s identifier. The recipient service validates the aud claim, rejecting tokens presented to a different host.

Example using the jsonwebtoken library when creating a token:

const jwt = require('jsonwebtoken');

function generateToken(userId) {
  return jwt.sign({
    sub: userId,
    aud: 'api.example.com',   // audience bound to the legitimate host
    iat: Math.floor(Date.now() / 1000),
    exp: Math.floor(Date.now() / 1000) + 300   // 5 minutes
  }, process.env.JWT_SECRET, { algorithm: 'HS256' });
}

The resource server then verifies:

jwt.verify(token, process.env.JWT_SECRET, { audience: 'api.example.com' });

3. **Certificate pinning or mutual TLS** – for critical APIs, pin the server’s TLS certificate or require mTLS, ensuring that even if DNS is hijacked, the TLS handshake fails unless the presenter possesses the legitimate private key.

4. **DNS hygiene** – implement automated DNS record cleanup as part of service decommissioning pipelines. Use infrastructure‑as‑code tools (Terraform, CloudFormation) to delete DNS records when the associated resource is destroyed.

By combining runtime hostname validation, audience‑restricted short‑lived tokens, and robust DNS lifecycle management, the risk of Bearer token leakage via dangling DNS is reduced to a low residual level.

Frequently Asked Questions

Can middleBrick detect a dangling DNS issue if the API never sends a Bearer token to the vulnerable host?
middleBrick’s detection correlates DNS inventory with observed outbound requests that include an Authorization: Bearer header. If no token‑bearing request is made to the dangling host during the scan, the issue will not be flagged because there is no actual token exposure to report.
Does fixing the DNS record alone eliminate the risk of token leakage?
Correcting the DNS record removes the immediate takeover vector, but residual risk remains if tokens are long‑lived or not audience‑bound. Best practice is to combine DNS hygiene with short‑lived, audience‑restricted tokens and client‑side hostname allow‑lists to defend against future misconfigurations.