---
name: rt-attack-surface-map
description: "Build complete attack surface map aggregating all recon data — subdomains, services, technologies, credentials, and CVEs — into a prioritized exploitation plan. The master document bridging Phase 2 (Recon) and Phase 3 (Exploitation). Creates attack-surface-map.md with prioritized target list."
---

# rt-attack-surface-map

## Overview

The Attack Surface Map is the **pivot document** of every Red Team engagement. It aggregates all Phase 2 reconnaissance output — subdomains, open ports, running services, detected technologies, leaked credentials, and identified CVEs — and converts that raw intelligence into a **ranked exploitation queue** for Phase 3.

Without this step, operators waste time in Phase 3 chasing low-value targets. With it, the first hour of exploitation focuses on the highest-probability, highest-impact vectors.

**When to run this skill:**
- After all passive and active recon is complete (subdomains, ports, web fingerprinting, credential hunting, CVE lookup)
- Before any exploitation begins
- When a new recon sweep reveals significant new data mid-engagement

**Output:** `_rtexit-output/docs/attack-chains/attack-surface-map.md`

---

## Skill Levels

### BEGINNER
Basic surface mapping using automated scanners with default settings. Suitable for CTF environments and simple single-domain scopes.

```bash
# 1. Run basic subdomain enumeration
subfinder -d target.com -o /tmp/subdomains.txt

# 2. Resolve live hosts
cat /tmp/subdomains.txt | httpx -o /tmp/live-hosts.txt -status-code -title -tech-detect

# 3. Port scan top 1000 ports on live hosts
nmap -iL /tmp/live-hosts.txt --top-ports 1000 -oN /tmp/nmap-basic.txt

# 4. Run nuclei with default templates
nuclei -l /tmp/live-hosts.txt -o /tmp/nuclei-results.txt

# 5. Manually review and create attack-surface-map.md
```

**Deliverable:** A basic table of hosts, open ports, and flags from nuclei.

---

### INTERMEDIATE
Multi-tool aggregation with technology fingerprinting, credential hunting, and CVE correlation. Standard for professional engagements.

```bash
# 1. Comprehensive subdomain enumeration (passive + active)
subfinder -d target.com -silent | anew /tmp/subdomains.txt
amass enum -passive -d target.com | anew /tmp/subdomains.txt
assetfinder --subs-only target.com | anew /tmp/subdomains.txt
cat /tmp/subdomains.txt | sort -u > /tmp/subdomains-unique.txt

# 2. DNS resolution + live host probing
cat /tmp/subdomains-unique.txt | dnsx -silent -a -resp | anew /tmp/resolved.txt
cat /tmp/subdomains-unique.txt | httpx \
  -status-code -title -tech-detect -content-length \
  -follow-redirects -threads 50 \
  -o /tmp/live-web.txt

# 3. Full port scan on resolved IPs
cat /tmp/resolved.txt | awk '{print $2}' | sort -u > /tmp/ips.txt
nmap -iL /tmp/ips.txt -p- --min-rate 5000 -T4 -sV \
  --script=banner,http-title,ssl-cert \
  -oA /tmp/nmap-full

# 4. Technology fingerprinting
whatweb -i /tmp/live-web.txt --log-json /tmp/whatweb.json

# 5. CVE lookup for detected services
# Extract service/version from nmap, query NVD
python3 /tmp/cve_lookup.py --nmap /tmp/nmap-full.xml --output /tmp/cves.json

# 6. Credential hunting
trufflehog git https://github.com/target-org --json | tee /tmp/trufflehog.json
gitleaks detect --source /tmp/cloned-repos/ --report-path /tmp/gitleaks.json

# 7. Aggregate and generate map
python3 _rtexit/scripts/autodoc_engine.py surface-map \
  --subdomains /tmp/subdomains-unique.txt \
  --live-hosts /tmp/live-web.txt \
  --nmap /tmp/nmap-full.xml \
  --nuclei /tmp/nuclei-results.txt \
  --cves /tmp/cves.json \
  --output _rtexit-output/docs/attack-chains/attack-surface-map.md
```

**Deliverable:** Structured attack-surface-map.md with prioritized target list and CVE annotations.

---

### ADVANCED
Full-spectrum surface mapping including cloud asset discovery, API endpoint enumeration, JavaScript analysis, and historical data mining. Used for complex multi-perimeter engagements.

```bash
# === PASSIVE RECON LAYER ===

# Certificate transparency — enumerate all issued certs
curl -s "https://crt.sh/?q=%.target.com&output=json" | \
  jq -r '.[].name_value' | sed 's/\*\.//g' | sort -u | \
  anew /tmp/subdomains.txt

# Historical DNS records
curl -s "https://api.securitytrails.com/v1/domain/target.com/subdomains" \
  -H "APIKEY: $SECURITYTRAILS_KEY" | jq -r '.subdomains[]' | \
  sed 's/$/.target.com/' | anew /tmp/subdomains.txt

# Shodan org/IP discovery
shodan search "org:\"Target Organization\"" --fields ip_str,port,hostnames \
  --separator , > /tmp/shodan-results.csv
shodan search "ssl.cert.subject.cn:target.com" --fields ip_str,port \
  --separator , >> /tmp/shodan-results.csv

# FOFA / Censys (alternative)
python3 -c "
import censys.search
c = censys.search.CensysHosts()
for host in c.search('(parsed.names: target.com) and services.port: {443,80,8080,8443}'):
    print(host['ip'])
" | anew /tmp/ips.txt

# ASN enumeration
amass intel -org "Target Corp" | tee /tmp/asn.txt
for asn in $(cat /tmp/asn.txt | grep -oP 'AS\d+'); do
  whois -h whois.radb.net -- "-i origin $asn" | grep -oP '\d+\.\d+\.\d+\.\d+/\d+' | \
    anew /tmp/cidr-ranges.txt
done

# === ACTIVE RECON LAYER ===

# DNS brute-force with targeted wordlists
puredns bruteforce \
  /usr/share/seclists/Discovery/DNS/dns-Jhaddix.txt \
  target.com \
  --resolvers /usr/share/seclists/Miscellaneous/dns-resolvers.txt \
  -q | anew /tmp/subdomains.txt

# VHOST discovery on each IP
for ip in $(cat /tmp/ips.txt); do
  ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt \
    -u "http://$ip" -H "Host: FUZZ.target.com" \
    -mc 200,301,302,401,403 \
    -o /tmp/vhost-$ip.json -of json
done

# === WEB LAYER ===

# JavaScript file discovery and secret extraction
cat /tmp/live-web.txt | getJS --complete | anew /tmp/js-files.txt
cat /tmp/js-files.txt | xargs -P 10 -I{} bash -c \
  'curl -sk {} | grep -oP "(api_key|secret|password|token|aws_|slack_)[^\s\"'\'']{8,}" >> /tmp/secrets-js.txt'

# API endpoint extraction from JS
cat /tmp/js-files.txt | xargs -P 5 -I{} \
  python3 /opt/tools/LinkFinder/linkfinder.py -i {} -o cli 2>/dev/null | \
  anew /tmp/api-endpoints.txt

# Directory/endpoint brute-force on high-value targets
for host in $(grep -E "CRITICAL|HIGH" /tmp/live-web.txt | awk '{print $1}'); do
  ffuf -w /usr/share/seclists/Discovery/Web-Content/api/api-endpoints.txt \
    -u "$host/FUZZ" \
    -mc 200,201,204,301,401,403,405 \
    -t 50 -o /tmp/ffuf-$host.json -of json 2>/dev/null
done

# === CLOUD LAYER ===

# S3 bucket enumeration
python3 /opt/tools/cloud_enum/cloud_enum.py \
  -k target -k targetcorp -k target-corp \
  --disable-azure --disable-gcp \
  -l /tmp/s3-buckets.txt

# Azure storage
python3 /opt/tools/cloud_enum/cloud_enum.py \
  -k target -k targetcorp \
  --disable-aws --disable-gcp \
  -l /tmp/azure-storage.txt

# Google Cloud buckets
for keyword in target targetcorp target-corp target-prod target-dev target-backup; do
  gsutil ls gs://$keyword 2>/dev/null && echo "FOUND: gs://$keyword" >> /tmp/gcp-buckets.txt
done

# === CVE CORRELATION ===

# Parse nmap XML for service versions
python3 << 'EOF'
import xml.etree.ElementTree as ET
import json, requests

tree = ET.parse('/tmp/nmap-full.xml')
services = []
for host in tree.findall('host'):
    ip = host.find('address').get('addr')
    for port in host.findall('ports/port'):
        svc = port.find('service')
        if svc is not None and svc.get('version'):
            services.append({
                'ip': ip,
                'port': port.get('portid'),
                'product': svc.get('product', ''),
                'version': svc.get('version', '')
            })

with open('/tmp/services.json', 'w') as f:
    json.dump(services, f, indent=2)
print(f"Extracted {len(services)} service/version pairs")
EOF

# === CREDENTIAL HUNTING ===

# GitHub dork for leaked secrets
python3 /opt/tools/GitDorker/GitDorker.py \
  -tf /opt/tools/GitDorker/Dorks/BHUSA.txt \
  -q target.com \
  -d /opt/tools/GitDorker/Dorks/medium_dorks.txt \
  -o /tmp/github-dorks.txt

# Paste sites
python3 /opt/tools/pwnedOrNot/pwnedornot.py \
  --domain target.com \
  --output /tmp/pwned-accounts.txt

# Breach data correlation (if haveibeenpwned API access)
curl -s "https://haveibeenpwned.com/api/v3/breacheddomain/target.com" \
  -H "hibp-api-key: $HIBP_KEY" | jq '.'

# === AGGREGATE AND SCORE ===

python3 _rtexit/scripts/autodoc_engine.py surface-map \
  --subdomains /tmp/subdomains.txt \
  --live-hosts /tmp/live-web.txt \
  --nmap /tmp/nmap-full.xml \
  --nuclei /tmp/nuclei-results.txt \
  --cves /tmp/cves.json \
  --js-secrets /tmp/secrets-js.txt \
  --cloud /tmp/s3-buckets.txt \
  --credentials /tmp/pwned-accounts.txt \
  --output _rtexit-output/docs/attack-chains/attack-surface-map.md \
  --format detailed
```

**Deliverable:** Full attack surface map with cloud assets, leaked credentials, JS secrets, and CVSS-scored CVE list. Prioritized exploitation queue ready for Phase 3.

---

### EXPERT
Adversarial simulation-grade mapping. Mimics APT reconnaissance patterns. Includes supply chain analysis, third-party exposure, and automated attack path generation using graph analysis.

```bash
# === SUPPLY CHAIN & THIRD-PARTY EXPOSURE ===

# DNS CNAME chain analysis — find dangling CNAMEs
cat /tmp/subdomains-unique.txt | while read sub; do
  cname=$(dig +short CNAME $sub 2>/dev/null | head -1)
  if [ -n "$cname" ]; then
    # Check if CNAME target is unclaimed (dangling)
    dig +short $cname | grep -q "^$" && \
      echo "DANGLING CNAME: $sub -> $cname" >> /tmp/dangling-cnames.txt
  fi
done

# Third-party JS library analysis (supply chain)
cat /tmp/js-files.txt | grep -E "cdn\.|unpkg\.|jsdelivr\." | \
  while read jsurl; do
    version=$(echo $jsurl | grep -oP '(\d+\.\d+\.\d+)')
    lib=$(echo $jsurl | grep -oP '[a-z-]+\.\d+' | head -1)
    echo "$lib $version $jsurl" >> /tmp/third-party-libs.txt
  done

# Retire.js — detect vulnerable JS libraries
retire --js --outputpath /tmp/retire-results.json \
  --outputformat json /tmp/downloaded-js/

# === ATTACK PATH GRAPH ANALYSIS ===

# Build relationship graph for attack path calculation
python3 << 'EOF'
import json
import networkx as nx
from itertools import combinations

# Load all recon data
with open('/tmp/services.json') as f:
    services = json.load(f)
with open('/tmp/cves.json') as f:
    cves = json.load(f)

G = nx.DiGraph()

# Add nodes for each discovered asset
for svc in services:
    node_id = f"{svc['ip']}:{svc['port']}"
    cvss_score = max(
        [c['cvss'] for c in cves if c['ip'] == svc['ip'] and c['port'] == svc['port']],
        default=0
    )
    G.add_node(node_id, type='service', ip=svc['ip'],
               port=svc['port'], product=svc['product'],
               cvss=cvss_score)

# Add edges based on network reachability (same subnet = connected)
nodes = list(G.nodes(data=True))
for n1, d1 in nodes:
    for n2, d2 in nodes:
        if n1 != n2 and d1['ip'].rsplit('.', 1)[0] == d2['ip'].rsplit('.', 1)[0]:
            G.add_edge(n1, n2, weight=1)

# Find highest-value attack paths
internet_node = 'INTERNET'
G.add_node(internet_node, type='external')

# Connect internet to all public-facing services
for node, data in nodes:
    if data.get('port') in ['80', '443', '8080', '8443']:
        G.add_edge(internet_node, node, weight=1)

# Calculate centrality to find pivot points
centrality = nx.betweenness_centrality(G)
top_pivots = sorted(centrality.items(), key=lambda x: x[1], reverse=True)[:10]

print("TOP PIVOT POINTS (by betweenness centrality):")
for node, score in top_pivots:
    print(f"  {node}: {score:.4f}")

# Export graph for visualization
nx.write_graphml(G, '/tmp/attack-surface-graph.graphml')
with open('/tmp/pivot-analysis.json', 'w') as f:
    json.dump({'top_pivots': top_pivots, 'node_count': G.number_of_nodes()}, f, indent=2)
EOF

# === AUTOMATED NUCLEI EXPERT MODE ===

# Run nuclei with ALL templates including CVEs, exposed panels, and misconfigs
nuclei -l /tmp/live-web.txt \
  -t /root/nuclei-templates/cves/ \
  -t /root/nuclei-templates/exposed-panels/ \
  -t /root/nuclei-templates/misconfiguration/ \
  -t /root/nuclei-templates/exposures/ \
  -t /root/nuclei-templates/default-logins/ \
  -severity critical,high,medium \
  -rl 150 -c 50 \
  -j -o /tmp/nuclei-expert.json \
  -stats -si 60

# === FINAL AGGREGATION WITH SCORING ===

python3 _rtexit/scripts/autodoc_engine.py surface-map \
  --subdomains /tmp/subdomains.txt \
  --live-hosts /tmp/live-web.txt \
  --nmap /tmp/nmap-full.xml \
  --nuclei /tmp/nuclei-expert.json \
  --cves /tmp/cves.json \
  --js-secrets /tmp/secrets-js.txt \
  --cloud /tmp/s3-buckets.txt \
  --credentials /tmp/pwned-accounts.txt \
  --graph /tmp/attack-surface-graph.graphml \
  --dangling-cnames /tmp/dangling-cnames.txt \
  --third-party /tmp/third-party-libs.txt \
  --output _rtexit-output/docs/attack-chains/attack-surface-map.md \
  --format expert \
  --generate-exploitation-queue
```

**Deliverable:** Expert-grade attack surface map with graph-based attack path analysis, supply chain risk, dangling CNAME takeover candidates, and auto-generated Phase 3 exploitation queue sorted by CVSS score and exploitability.

---

## Step-by-Step Workflow

### Step 1 — Collect All Recon Output

Verify all Phase 2 artifacts exist before aggregating:

```bash
# Check for required recon artifacts
RECON_DIR="_rtexit-output/docs/reconnaissance"
REQUIRED=(
  "$RECON_DIR/subdomains.txt"
  "$RECON_DIR/live-hosts.txt"
  "$RECON_DIR/nmap-full.xml"
  "$RECON_DIR/technologies.json"
)
for f in "${REQUIRED[@]}"; do
  [ -f "$f" ] && echo "[OK] $f" || echo "[MISSING] $f"
done
```

If artifacts are missing, run the appropriate recon skill first (rt-recon-passive or rt-recon-active).

---

### Step 2 — Normalize and Deduplicate Subdomain Data

```bash
# Merge all subdomain sources
cat \
  _rtexit-output/docs/reconnaissance/subdomains-passive.txt \
  _rtexit-output/docs/reconnaissance/subdomains-active.txt \
  _rtexit-output/docs/reconnaissance/subdomains-cert.txt \
  2>/dev/null | \
  sed 's/\*\.//g' | \
  tr '[:upper:]' '[:lower:]' | \
  grep -E "^[a-z0-9][a-z0-9\.\-]+[a-z0-9]$" | \
  sort -u > /tmp/subdomains-final.txt

TOTAL=$(wc -l < /tmp/subdomains-final.txt)
echo "[*] Total unique subdomains: $TOTAL"
```

---

### Step 3 — Probe Live Hosts and Extract Metadata

```bash
# Probe all subdomains for live web services
cat /tmp/subdomains-final.txt | httpx \
  -silent \
  -status-code \
  -title \
  -tech-detect \
  -content-length \
  -follow-redirects \
  -threads 100 \
  -timeout 10 \
  -o /tmp/live-web-full.txt

# Parse live count
LIVE=$(wc -l < /tmp/live-web-full.txt)
echo "[*] Live web endpoints: $LIVE"

# Extract IP addresses from resolved subdomains
cat /tmp/subdomains-final.txt | dnsx -silent -a -resp-only | \
  sort -u > /tmp/resolved-ips.txt

echo "[*] Unique IPs: $(wc -l < /tmp/resolved-ips.txt)"
```

---

### Step 4 — Service and Port Enumeration

```bash
# Fast initial scan — top 1000 ports
nmap -iL /tmp/resolved-ips.txt \
  --top-ports 1000 \
  -T4 \
  --min-rate 3000 \
  -sV \
  --open \
  -oA /tmp/nmap-top1000

# Full port scan on critical IPs (IPs with interesting services from step above)
CRITICAL_IPS=$(grep -E "21|22|23|25|53|110|143|389|445|1433|3306|3389|5432|5900|6379|27017" \
  /tmp/nmap-top1000.gnmap | awk '{print $2}' | sort -u)

if [ -n "$CRITICAL_IPS" ]; then
  echo "$CRITICAL_IPS" > /tmp/critical-ips.txt
  nmap -iL /tmp/critical-ips.txt \
    -p- \
    --min-rate 5000 \
    -T4 \
    -sV \
    --script=banner,http-title,ssl-cert,smtp-commands,ftp-anon,ssh-hostkey \
    -oA /tmp/nmap-critical-full
fi

# UDP scan for key services (DNS, SNMP, NTP)
nmap -iL /tmp/resolved-ips.txt \
  -sU \
  -p 53,67,68,69,123,161,162,500,1900 \
  --min-rate 1000 \
  -oA /tmp/nmap-udp
```

---

### Step 5 — Technology Stack Fingerprinting

```bash
# Whatweb detailed scan
whatweb \
  --input-file /tmp/live-web-full.txt \
  --log-json /tmp/whatweb-detailed.json \
  --aggression 3 \
  --quiet

# Extract unique technologies for CVE correlation
python3 << 'EOF'
import json

with open('/tmp/whatweb-detailed.json') as f:
    data = json.load(f)

tech_versions = {}
for entry in data:
    target = entry.get('target', '')
    plugins = entry.get('plugins', {})
    for tech, info in plugins.items():
        version = info.get('version', [''])[0] if info.get('version') else ''
        if version:
            if tech not in tech_versions:
                tech_versions[tech] = []
            tech_versions[tech].append({'target': target, 'version': version})

with open('/tmp/tech-versions.json', 'w') as f:
    json.dump(tech_versions, f, indent=2)

print(f"Found {len(tech_versions)} technologies with version info")
for tech, instances in sorted(tech_versions.items()):
    print(f"  {tech}: {instances[0]['version']} ({len(instances)} hosts)")
EOF
```

---

### Step 6 — CVE Correlation

```bash
# Query NVD API for each detected technology/version
python3 << 'EOF'
import json, requests, time

with open('/tmp/tech-versions.json') as f:
    tech_versions = json.load(f)

NVD_API = "https://services.nvd.nist.gov/rest/json/cves/2.0"
NVD_KEY = "YOUR_NVD_API_KEY"  # Register at https://nvd.nist.gov/developers/request-an-api-key

findings = []

for tech, instances in tech_versions.items():
    version = instances[0]['version']
    params = {
        'keywordSearch': f"{tech} {version}",
        'resultsPerPage': 10,
        'cvssV3SeverityV2': 'CRITICAL,HIGH'
    }
    headers = {'apiKey': NVD_KEY} if NVD_KEY else {}
    
    try:
        r = requests.get(NVD_API, params=params, headers=headers, timeout=10)
        if r.status_code == 200:
            cves = r.json().get('vulnerabilities', [])
            for cve in cves:
                metrics = cve['cve'].get('metrics', {})
                cvss = 0
                if 'cvssMetricV31' in metrics:
                    cvss = metrics['cvssMetricV31'][0]['cvssData']['baseScore']
                elif 'cvssMetricV30' in metrics:
                    cvss = metrics['cvssMetricV30'][0]['cvssData']['baseScore']
                
                findings.append({
                    'technology': tech,
                    'version': version,
                    'cve_id': cve['cve']['id'],
                    'cvss': cvss,
                    'description': cve['cve']['descriptions'][0]['value'][:200],
                    'affected_hosts': [i['target'] for i in instances]
                })
        time.sleep(0.6)  # NVD rate limit: 50 requests per 30 seconds with key
    except Exception as e:
        print(f"Error querying {tech}: {e}")

# Sort by CVSS score
findings.sort(key=lambda x: x['cvss'], reverse=True)

with open('/tmp/cve-findings.json', 'w') as f:
    json.dump(findings, f, indent=2)

print(f"\nFound {len(findings)} CVEs")
print("\nTop CVEs by CVSS:")
for f in findings[:10]:
    print(f"  [{f['cvss']}] {f['cve_id']} — {f['technology']} {f['version']}")
EOF

# Also run searchsploit for offline CVE/exploit matching
searchsploit --nmap /tmp/nmap-critical-full.xml -j > /tmp/searchsploit-results.json 2>/dev/null
```

---

### Step 7 — Credential and Secret Hunting

```bash
# TruffleHog — scan git repos for secrets
for repo_url in $(cat _rtexit-output/docs/reconnaissance/github-repos.txt 2>/dev/null); do
  trufflehog git "$repo_url" \
    --json \
    --no-update \
    2>/dev/null >> /tmp/trufflehog-all.json
done

# Gitleaks — scan locally cloned repos
if [ -d /tmp/cloned-repos ]; then
  gitleaks detect \
    --source /tmp/cloned-repos \
    --report-format json \
    --report-path /tmp/gitleaks-results.json \
    --no-banner
fi

# GitDorker — GitHub search for target-specific secrets
python3 /opt/tools/GitDorker/GitDorker.py \
  -tf ~/.tokens/github.tok \
  -q "target.com" \
  -d /opt/tools/GitDorker/Dorks/BHUSA.txt \
  | tee /tmp/gitdorker-results.txt

# Parse and summarize credential findings
python3 << 'EOF'
import json

secrets = []

# Parse TruffleHog output
try:
    with open('/tmp/trufflehog-all.json') as f:
        for line in f:
            try:
                entry = json.loads(line.strip())
                if entry.get('SourceMetadata'):
                    secrets.append({
                        'source': 'TruffleHog',
                        'type': entry.get('DetectorName', 'Unknown'),
                        'location': str(entry.get('SourceMetadata', {}).get('Data', '')),
                        'raw': entry.get('Raw', '')[:50] + '...'
                    })
            except:
                pass
except FileNotFoundError:
    pass

# Parse Gitleaks output
try:
    with open('/tmp/gitleaks-results.json') as f:
        for finding in json.load(f):
            secrets.append({
                'source': 'Gitleaks',
                'type': finding.get('RuleID', 'Unknown'),
                'location': finding.get('File', '') + ':' + str(finding.get('StartLine', '')),
                'raw': finding.get('Secret', '')[:20] + '...'
            })
except (FileNotFoundError, json.JSONDecodeError):
    pass

with open('/tmp/credentials-summary.json', 'w') as f:
    json.dump(secrets, f, indent=2)

print(f"Found {len(secrets)} potential credentials/secrets")
for s in secrets:
    print(f"  [{s['source']}] {s['type']} at {s['location']}")
EOF
```

---

### Step 8 — Run Nuclei Vulnerability Scanner

```bash
# Targeted nuclei scan with severity filtering
nuclei \
  -l /tmp/live-web-full.txt \
  -t /root/nuclei-templates/cves/ \
  -t /root/nuclei-templates/exposed-panels/ \
  -t /root/nuclei-templates/misconfiguration/ \
  -t /root/nuclei-templates/exposures/configs/ \
  -t /root/nuclei-templates/default-logins/ \
  -t /root/nuclei-templates/takeovers/ \
  -severity critical,high,medium \
  -rl 100 \
  -c 25 \
  -timeout 10 \
  -j \
  -o /tmp/nuclei-findings.json \
  -stats \
  -si 30 \
  2>/tmp/nuclei-stderr.txt

# Parse nuclei output
python3 << 'EOF'
import json

findings = []
try:
    with open('/tmp/nuclei-findings.json') as f:
        for line in f:
            try:
                findings.append(json.loads(line.strip()))
            except:
                pass
except FileNotFoundError:
    pass

severity_order = {'critical': 0, 'high': 1, 'medium': 2, 'low': 3, 'info': 4}
findings.sort(key=lambda x: severity_order.get(x.get('info', {}).get('severity', 'info'), 99))

print(f"Nuclei findings: {len(findings)}")
severity_counts = {}
for f in findings:
    sev = f.get('info', {}).get('severity', 'unknown')
    severity_counts[sev] = severity_counts.get(sev, 0) + 1

for sev, count in sorted(severity_counts.items(), key=lambda x: severity_order.get(x[0], 99)):
    print(f"  {sev.upper()}: {count}")
EOF
```

---

### Step 9 — Score and Prioritize All Targets

```bash
# Calculate composite exploitation score for each target
python3 << 'EOF'
import json
from collections import defaultdict

# Load all data sources
def load_json(path, default=None):
    try:
        with open(path) as f:
            return json.load(f)
    except:
        return default or []

nuclei_findings = []
try:
    with open('/tmp/nuclei-findings.json') as f:
        for line in f:
            try:
                nuclei_findings.append(json.loads(line.strip()))
            except:
                pass
except:
    pass

cve_findings = load_json('/tmp/cve-findings.json', [])
credentials  = load_json('/tmp/credentials-summary.json', [])

# Score each target
target_scores = defaultdict(lambda: {
    'score': 0,
    'factors': [],
    'nuclei_findings': [],
    'cves': [],
    'credentials': [],
    'services': []
})

SEVERITY_SCORES = {'critical': 40, 'high': 25, 'medium': 10, 'low': 3, 'info': 0}

# Score from nuclei
for finding in nuclei_findings:
    host = finding.get('host', '').split('//')[1].split('/')[0] if '//' in finding.get('host','') else finding.get('host','')
    sev = finding.get('info', {}).get('severity', 'info')
    score = SEVERITY_SCORES.get(sev, 0)
    target_scores[host]['score'] += score
    target_scores[host]['nuclei_findings'].append({
        'template': finding.get('templateID', ''),
        'severity': sev,
        'name': finding.get('info', {}).get('name', '')
    })
    target_scores[host]['factors'].append(f"Nuclei {sev}: {finding.get('info',{}).get('name','')}")

# Score from CVEs
for cve in cve_findings:
    cvss = cve.get('cvss', 0)
    for host in cve.get('affected_hosts', []):
        h = host.split('//')[1].split('/')[0] if '//' in host else host
        target_scores[h]['score'] += cvss * 2
        target_scores[h]['cves'].append({'id': cve['cve_id'], 'cvss': cvss})
        target_scores[h]['factors'].append(f"CVE {cve['cve_id']} (CVSS {cvss})")

# Bonus for credentials
for cred in credentials:
    # Broad bonus — credentials give access to many targets
    for host in target_scores:
        target_scores[host]['score'] += 5
        target_scores[host]['credentials'].append(cred.get('type', 'Unknown'))

# Sort by score
sorted_targets = sorted(target_scores.items(), key=lambda x: x[1]['score'], reverse=True)

# Save prioritized list
output = [{'host': h, **d} for h, d in sorted_targets]
with open('/tmp/prioritized-targets.json', 'w') as f:
    json.dump(output, f, indent=2)

print("\n=== PRIORITIZED EXPLOITATION QUEUE ===")
print(f"{'Rank':<5} {'Score':<8} {'Host':<50} {'Top Finding'}")
print("-" * 100)
for i, (host, data) in enumerate(sorted_targets[:20], 1):
    top = data['factors'][0] if data['factors'] else 'Service exposure'
    print(f"{i:<5} {data['score']:<8.1f} {host:<50} {top}")
EOF
```

---

### Step 10 — Generate Attack Surface Map Document

```bash
# Generate the final attack-surface-map.md
python3 << 'PYEOF'
import json
from datetime import datetime

def load_json(path, default=None):
    try:
        with open(path) as f:
            content = f.read().strip()
            if not content:
                return default or []
            # Handle JSONL format
            if content.startswith('{'):
                return [json.loads(line) for line in content.split('\n') if line.strip()]
            return json.loads(content)
    except:
        return default or []

targets      = load_json('/tmp/prioritized-targets.json', [])
cves         = load_json('/tmp/cve-findings.json', [])
credentials  = load_json('/tmp/credentials-summary.json', [])

now = datetime.now().strftime("%Y-%m-%d %H:%M")

subdomains_count = 0
try:
    with open('/tmp/subdomains-final.txt') as f:
        subdomains_count = sum(1 for _ in f)
except:
    pass

live_count = 0
try:
    with open('/tmp/live-web-full.txt') as f:
        live_count = sum(1 for _ in f)
except:
    pass

nuclei_findings = load_json('/tmp/nuclei-findings.json', [])
severity_counts = {}
SEVERITY_ORDER = ['critical', 'high', 'medium', 'low', 'info']
for f in nuclei_findings:
    sev = f.get('info', {}).get('severity', 'info')
    severity_counts[sev] = severity_counts.get(sev, 0) + 1

doc = f"""# Attack Surface Map

**Generated:** {now}
**Classification:** CONFIDENTIAL — Authorized Red Team Use Only

---

## Executive Summary

| Metric | Count |
|--------|-------|
| Total Subdomains Discovered | {subdomains_count} |
| Live Web Endpoints | {live_count} |
| Prioritized Targets | {len(targets)} |
| Critical/High Nuclei Findings | {severity_counts.get('critical', 0) + severity_counts.get('high', 0)} |
| CVEs Identified | {len(cves)} |
| Credential Leaks | {len(credentials)} |

---

## Nuclei Finding Summary

| Severity | Count |
|----------|-------|
"""

for sev in SEVERITY_ORDER:
    count = severity_counts.get(sev, 0)
    doc += f"| {sev.upper()} | {count} |\n"

doc += """
---

## Prioritized Exploitation Queue

> Targets ranked by composite exploitation score (nuclei severity + CVSS + credential exposure)

| Rank | Score | Host | Top Vectors | Action |
|------|-------|------|-------------|--------|
"""

for i, t in enumerate(targets[:30], 1):
    host = t.get('host', '')
    score = t.get('score', 0)
    factors = t.get('factors', [])
    top_vector = factors[0] if factors else 'Service exposure'
    cve_count = len(t.get('cves', []))
    nuclei_count = len(t.get('nuclei_findings', []))
    action = "EXPLOIT IMMEDIATELY" if score >= 80 else "HIGH PRIORITY" if score >= 40 else "STANDARD PRIORITY"
    doc += f"| {i} | {score:.0f} | `{host}` | {top_vector} | **{action}** |\n"

doc += """
---

## CVE Inventory

| CVE ID | CVSS | Technology | Description | Affected Hosts |
|--------|------|------------|-------------|----------------|
"""

top_cves = sorted(cves, key=lambda x: x.get('cvss', 0), reverse=True)[:20]
for cve in top_cves:
    cve_id = cve.get('cve_id', '')
    cvss = cve.get('cvss', 0)
    tech = f"{cve.get('technology','')} {cve.get('version','')}"
    desc = cve.get('description', '')[:80] + '...' if len(cve.get('description','')) > 80 else cve.get('description','')
    hosts = ', '.join(cve.get('affected_hosts', [])[:3])
    if len(cve.get('affected_hosts',[])) > 3:
        hosts += f" +{len(cve.get('affected_hosts',[])) - 3} more"
    doc += f"| [{cve_id}](https://nvd.nist.gov/vuln/detail/{cve_id}) | {cvss} | {tech} | {desc} | {hosts} |\n"

doc += """
---

## Credential Exposure

| Source | Type | Location |
|--------|------|----------|
"""

for cred in credentials[:20]:
    doc += f"| {cred.get('source','')} | {cred.get('type','')} | {cred.get('location','')} |\n"

doc += """
---

## Recommended Attack Paths

### Path A — External Vulnerability Exploitation
```
INTERNET
  → [Rank #1 Target] (highest nuclei/CVE score)
  → Service exploitation
  → Initial foothold
  → Internal pivot
```

### Path B — Credential-Based Access
```
INTERNET
  → Leaked credentials (from breach data / git secrets)
  → Direct authentication to VPN/Admin/SSH
  → Authenticated enumeration
  → Privilege escalation
```

### Path C — Subdomain Takeover / Dangling CNAME
```
INTERNET
  → Dangling CNAME identified (see /tmp/dangling-cnames.txt)
  → Register unclaimed third-party service
  → Host malicious content / phishing
  → Harvest credentials from target users
```

---

## Phase 3 Entry Points

Based on this attack surface map, Phase 3 (Exploitation) should begin with:

1. **Immediate targets** (score ≥ 80): Begin exploitation within first engagement session
2. **High-priority targets** (score 40-79): Schedule within first 48 hours
3. **Standard targets** (score < 40): Exploit after higher-value targets

---

## Evidence & Artifacts

All source files for this attack surface map are located at:

```
_rtexit-output/docs/reconnaissance/     # Raw recon data
/tmp/nuclei-findings.json               # Nuclei raw output
/tmp/cve-findings.json                  # CVE correlation data
/tmp/credentials-summary.json           # Credential findings
/tmp/prioritized-targets.json           # Scoring data
```

---

*Generated by RTExit rt-attack-surface-map skill*
"""

output_path = '_rtexit-output/docs/attack-chains/attack-surface-map.md'
import os
os.makedirs(os.path.dirname(output_path), exist_ok=True)
with open(output_path, 'w') as f:
    f.write(doc)

print(f"[+] Attack surface map written to: {output_path}")
print(f"[+] {len(targets)} targets prioritized")
print(f"[+] Top target: {targets[0]['host'] if targets else 'N/A'} (score: {targets[0]['score'] if targets else 0:.0f})")
PYEOF
```

---

### Step 11 — Register with RTExit Autodoc Engine

```bash
# Register the attack surface map with the autodoc engine
python3 _rtexit/scripts/autodoc_engine.py register-artifact \
  --type attack-surface-map \
  --path _rtexit-output/docs/attack-chains/attack-surface-map.md \
  --phase 2 \
  --status complete

# Update engagement status
python3 _rtexit/scripts/autodoc_engine.py update-phase \
  --phase 2 \
  --status complete \
  --next-phase 3 \
  --summary "Attack surface map complete. $(wc -l < /tmp/prioritized-targets.json) targets prioritized."

echo "[+] RTExit autodoc engine updated"
echo "[+] Ready to begin Phase 3: Exploitation"
```

---

## Tools Referenced

| Tool | Purpose | URL |
|------|---------|-----|
| Subfinder | Passive subdomain enumeration | https://github.com/projectdiscovery/subfinder |
| Amass | Active/passive subdomain enumeration | https://github.com/owasp-amass/amass |
| Assetfinder | Subdomain discovery via multiple sources | https://github.com/tomnomnom/assetfinder |
| httpx | HTTP probing with tech detection | https://github.com/projectdiscovery/httpx |
| dnsx | Fast DNS resolver and query tool | https://github.com/projectdiscovery/dnsx |
| puredns | Bruteforce subdomain resolver | https://github.com/d3mondev/puredns |
| anew | Append unique lines to files | https://github.com/tomnomnom/anew |
| Nmap | Port scanning and service detection | https://github.com/nmap/nmap |
| Nuclei | Vulnerability scanning with templates | https://github.com/projectdiscovery/nuclei |
| Nuclei Templates | Community vulnerability templates | https://github.com/projectdiscovery/nuclei-templates |
| WhatWeb | Web technology fingerprinting | https://github.com/urbanadventurer/WhatWeb |
| TruffleHog | Secret scanning in git repos | https://github.com/trufflesecurity/trufflehog |
| Gitleaks | Secret and credential scanner | https://github.com/gitleaks/gitleaks |
| GitDorker | GitHub dorking for target secrets | https://github.com/obheda12/GitDorker |
| cloud_enum | Multi-cloud asset enumeration | https://github.com/initstring/cloud_enum |
| Retire.js | Vulnerable JS library detection | https://github.com/RetireJS/retire.js |
| LinkFinder | JavaScript endpoint discovery | https://github.com/GerbenJavado/LinkFinder |
| ffuf | Fast web fuzzer for content/vhost | https://github.com/ffuf/ffuf |
| Shodan CLI | Internet-wide scan data queries | https://github.com/achillean/shodan-python |
| searchsploit | Local exploit database search | https://github.com/offensive-security/exploitdb |
| SecLists | Security wordlists collection | https://github.com/danielmiessler/SecLists |
| networkx | Python graph analysis library | https://github.com/networkx/networkx |

---

## SecLists Wordlists Used

```bash
# DNS brute-force (subdomain discovery)
/usr/share/seclists/Discovery/DNS/dns-Jhaddix.txt
/usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt
/usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt

# Web content discovery
/usr/share/seclists/Discovery/Web-Content/api/api-endpoints.txt
/usr/share/seclists/Discovery/Web-Content/common.txt
/usr/share/seclists/Discovery/Web-Content/big.txt
/usr/share/seclists/Discovery/Web-Content/raft-large-directories.txt

# DNS resolvers (for puredns)
/usr/share/seclists/Miscellaneous/dns-resolvers.txt

# Virtual host brute-force
/usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt
```

Install SecLists on Kali:
```bash
sudo apt install seclists -y
# Or manually:
git clone https://github.com/danielmiessler/SecLists /usr/share/seclists
```

---

## Output Instructions

### Files Created by This Skill

| File | Location | Description |
|------|----------|-------------|
| `attack-surface-map.md` | `_rtexit-output/docs/attack-chains/` | **Master output** — prioritized exploitation plan |
| `subdomains-final.txt` | `/tmp/` (copy to recon dir) | Deduplicated subdomain list |
| `live-web-full.txt` | `/tmp/` (copy to recon dir) | Live web endpoints with metadata |
| `nuclei-findings.json` | `/tmp/` (copy to evidence dir) | Raw nuclei results |
| `cve-findings.json` | `/tmp/` (copy to evidence dir) | CVE correlation data |
| `prioritized-targets.json` | `/tmp/` (copy to attack-chains dir) | Scored target list |
| `credentials-summary.json` | `/tmp/` (copy to findings dir) | Credential exposure summary |

### Copy Artifacts to Permanent Storage

```bash
RECON="_rtexit-output/docs/reconnaissance"
EVIDENCE="_rtexit-output/evidence"
CHAINS="_rtexit-output/docs/attack-chains"
FINDINGS="_rtexit-output/docs/findings"

mkdir -p "$RECON" "$EVIDENCE" "$CHAINS" "$FINDINGS"

cp /tmp/subdomains-final.txt   "$RECON/subdomains-complete.txt"
cp /tmp/live-web-full.txt      "$RECON/live-web-endpoints.txt"
cp /tmp/resolved-ips.txt       "$RECON/resolved-ips.txt"
cp /tmp/nuclei-findings.json   "$EVIDENCE/nuclei-$(date +%Y%m%d).json"
cp /tmp/cve-findings.json      "$FINDINGS/cve-inventory.json"
cp /tmp/prioritized-targets.json "$CHAINS/target-scores.json"
cp /tmp/credentials-summary.json "$FINDINGS/credential-exposure.json"

# Compress all evidence
tar czf "$EVIDENCE/attack-surface-evidence-$(date +%Y%m%d).tar.gz" \
  /tmp/nmap-*.xml /tmp/nmap-*.gnmap /tmp/whatweb-detailed.json \
  /tmp/nuclei-findings.json /tmp/trufflehog-all.json 2>/dev/null

echo "[+] All artifacts saved to permanent storage"
ls -lh "$CHAINS/attack-surface-map.md"
```

---

## Resources

### Documentation and References
- NVD API Documentation: https://nvd.nist.gov/developers/vulnerabilities
- Nuclei Template Writing Guide: https://docs.projectdiscovery.io/templates/introduction
- Amass User Guide: https://github.com/owasp-amass/amass/blob/master/doc/user_guide.md
- Shodan API Reference: https://developer.shodan.io/api
- Censys Search Language: https://search.censys.io/search/language

### Attack Surface Methodology References
- OWASP Testing Guide (Recon): https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing/01-Information_Gathering
- PTES Technical Guidelines: http://www.pentest-standard.org/index.php/Intelligence_Gathering
- Bug Bounty Recon Methodology (Jason Haddix): https://github.com/jhaddix/tbhm
- Subdomain Enumeration Guide: https://blog.projectdiscovery.io/subdomain-enumeration/

### Vulnerability Databases
- NVD (NIST): https://nvd.nist.gov/vuln/search
- CVE Details: https://www.cvedetails.com
- ExploitDB: https://www.exploit-db.com
- Vulhub (Docker PoC environments): https://github.com/vulhub/vulhub
- PacketStorm Security: https://packetstormsecurity.com

### Credential Exposure Sources
- HaveIBeenPwned API: https://haveibeenpwned.com/API/v3
- LeakCheck API: https://leakcheck.io/api
- DeHashed API: https://www.dehashed.com/docs
- IntelligenceX: https://intelx.io/

### Cloud Attack Surface
- AWS S3 Bucket Finder: https://github.com/clarketm/s3finder
- CloudSploit Scans: https://github.com/aquasecurity/cloudsploit
- ScoutSuite (Multi-cloud): https://github.com/nccgroup/ScoutSuite

---

## Troubleshooting

### Nuclei returns no results
```bash
# Update templates
nuclei -update-templates

# Test connectivity
nuclei -l /tmp/live-web-full.txt -t /root/nuclei-templates/http/technologies/ -debug
```

### NVD API rate limiting (403 errors)
```bash
# Register for free API key at https://nvd.nist.gov/developers/request-an-api-key
# Without key: 5 requests per 30 seconds
# With key: 50 requests per 30 seconds

# Increase sleep between requests in cve_lookup.py
time.sleep(6)  # Without key — 6 seconds per request
```

### httpx missing technology detections
```bash
# Ensure wappalyzer data is up to date
httpx -update

# Fallback: use gowitness for screenshot-based fingerprinting
gowitness scan file -f /tmp/subdomains-final.txt --write-db
gowitness report export --zip /tmp/gowitness-screenshots.zip
```

### Slow nmap scans
```bash
# Use masscan for initial port discovery, then nmap for service detection
masscan -iL /tmp/resolved-ips.txt -p 1-65535 --rate 10000 -oL /tmp/masscan-results.txt
grep "open" /tmp/masscan-results.txt | awk '{print $4}' | sort -u > /tmp/masscan-ips.txt
nmap -iL /tmp/masscan-ips.txt -sV --version-intensity 5 -oA /tmp/nmap-services
```
