External Attack Surface Mapping

active intermediate

External Attack Surface Mapping

Hypothesis

We hypothesize that the Prismatic Perimeter EASM discovery engine can identify 90%+ of an organization's externally visible assets within 60 minutes using passive techniques (no active scanning), that combining 5+ independent discovery methods improves asset completeness by 35% over any single method, and that the A-F security rating system correlates with actual incident likelihood at r > 0.75.

Background

External Attack Surface Management is the practice of continuously discovering, monitoring, and assessing an organization's internet-facing assets -- domains, IP addresses, certificates, cloud resources, exposed services, and third-party dependencies. The Prismatic Perimeter application implements a complete EASM solution competing with commercial offerings like BitSight, Black Kite, and SecurityScorecard.

The discovery challenge is fundamentally one of completeness: an attacker needs to find only one unmonitored asset, while the defender must know about all of them. Traditional asset inventories are manually maintained and perpetually incomplete. EASM automates discovery through multiple independent techniques that collectively approach comprehensive coverage.

The Prismatic Perimeter discovery engine uses six independent discovery methods: DNS enumeration (brute-force and zone transfer), Certificate Transparency log analysis, WHOIS and reverse WHOIS lookups, IP range scanning and ASN mapping, cloud resource discovery (AWS, GCP, Azure public resources), and web crawling for linked assets. Each method discovers assets that others miss, and their combination provides comprehensive coverage.

The security rating system assigns A-F grades based on evidence collected across 8 risk categories: Patching Cadence, Network Security, DNS Health, Application Security, Endpoint Security, IP Reputation, Email Security, and Web Application Security. Ratings are calculated using a 300-900 numeric score that maps to letter grades.

The NABLA Infinity Signal Plurality axiom is particularly relevant here: every security rating must be supported by evidence from at least 2 independent sources, and contradictory evidence must be preserved rather than averaged away.

Methodology

Phase 1: Discovery Completeness -- We selected 50 organizations with known asset inventories (obtained through authorized assessment agreements) and ran the discovery engine against each. We measured the percentage of known assets discovered by each method and by all methods combined.

Phase 2: Method Contribution -- For each of the 6 discovery methods, we measured unique asset contribution (assets found only by that method) and overlap with other methods. This determines the marginal value of each additional discovery method.

Phase 3: Rating Accuracy -- We correlated the A-F security ratings assigned by the Prismatic Perimeter engine with actual security incident data from the previous 12 months for 200 organizations. This validates whether the rating system predicts real-world security posture.

Phase 4: Performance -- We measured end-to-end discovery time for organizations of varying sizes (10 to 10,000 known assets) to validate the 60-minute completion target.

Setup

The multi-method discovery orchestrator:

defmodule PrismaticPerimeter.Discovery.Orchestrator do
  @methods [
    PrismaticPerimeter.Discovery.DNS,
    PrismaticPerimeter.Discovery.CertificateTransparency,
    PrismaticPerimeter.Discovery.WHOIS,
    PrismaticPerimeter.Discovery.IPRange,
    PrismaticPerimeter.Discovery.CloudResources,
    PrismaticPerimeter.Discovery.WebCrawler
  ]

  @spec discover(String.t(), keyword()) :: {:ok, map()}
  def discover(target_domain, opts \\ []) do
    timeout = Keyword.get(opts, :timeout_ms, 3_600_000)
    start_time = System.monotonic_time(:millisecond)

    # Run all discovery methods in parallel
    method_results =
      @methods
      |> Task.async_stream(
        fn method ->
          method_start = System.monotonic_time(:millisecond)
          {:ok, assets} = method.discover(target_domain, opts)
          method_elapsed = System.monotonic_time(:millisecond) - method_start

          %{
            method: method.name(),
            assets: assets,
            count: length(assets),
            elapsed_ms: method_elapsed
          }
        end,
        max_concurrency: 6,
        timeout: timeout
      )
      |> Enum.map(fn {:ok, result} -> result end)

    # Merge and deduplicate assets
    all_assets = merge_discovered_assets(method_results)

    # Calculate method contribution metrics
    contributions = calculate_method_contributions(method_results, all_assets)

    elapsed = System.monotonic_time(:millisecond) - start_time

    {:ok, %{
      target: target_domain,
      total_assets: length(all_assets),
      assets: all_assets,
      method_results: method_results,
      contributions: contributions,
      elapsed_ms: elapsed,
      timestamp: DateTime.utc_now()
    }}
  end

  defp merge_discovered_assets(method_results) do
    method_results
    |> Enum.flat_map(& &1.assets)
    |> Enum.uniq_by(&asset_fingerprint/1)
    |> Enum.map(fn asset ->
      sources =
        method_results
        |> Enum.filter(fn result ->
          Enum.any?(result.assets, &(asset_fingerprint(&1) == asset_fingerprint(asset)))
        end)
        |> Enum.map(& &1.method)

      %{asset | discovered_by: sources, source_count: length(sources)}
    end)
  end

  defp asset_fingerprint(asset) do
    :crypto.hash(:sha256, "#{asset.type}:#{asset.identifier}")
  end
end

The security rating calculator:

defmodule PrismaticPerimeter.SecurityRating do
  @risk_categories [
    :patching_cadence,
    :network_security,
    :dns_health,
    :application_security,
    :endpoint_security,
    :ip_reputation,
    :email_security,
    :web_application_security
  ]

  @grade_thresholds [
    {810, :A},
    {720, :B},
    {630, :C},
    {540, :D},
    {0, :F}
  ]

  @spec calculate(String.t()) :: {:ok, map()}
  def calculate(domain) do
    category_scores =
      @risk_categories
      |> Task.async_stream(fn category ->
        evidence = collect_evidence(domain, category)
        score = score_category(category, evidence)
        {category, %{score: score, evidence: evidence, confidence: evidence_confidence(evidence)}}
      end, max_concurrency: 8, timeout: 60_000)
      |> Enum.map(fn {:ok, result} -> result end)
      |> Map.new()

    numeric_score = calculate_weighted_score(category_scores)
    grade = score_to_grade(numeric_score)

    # NABLA compliance: ensure plurality
    plurality_check = verify_signal_plurality(category_scores)

    {:ok, %{
      domain: domain,
      grade: grade,
      score: numeric_score,
      categories: category_scores,
      plurality_compliant: plurality_check,
      industry_percentile: calculate_percentile(numeric_score),
      timestamp: DateTime.utc_now()
    }}
  end

  defp score_to_grade(score) do
    Enum.find_value(@grade_thresholds, :F, fn {threshold, grade} ->
      if score >= threshold, do: grade
    end)
  end

  defp verify_signal_plurality(category_scores) do
    Enum.all?(category_scores, fn {_cat, data} ->
      length(data.evidence) >= 2
    end)
  end
end

Results

Discovery completeness (50 organizations, passive techniques only):

Discovery MethodAssets Found (avg)Coverage (avg)Unique Contribution
DNS Enumeration34267.2%12.4%
Certificate Transparency28756.4%8.7%
WHOIS/Reverse WHOIS19838.9%6.2%
IP Range / ASN22444.1%9.8%
Cloud Resources15630.7%11.3%
Web Crawling18937.2%5.1%
All Combined47192.6%--

Method combination analysis:

Methods CombinedCoverageMarginal Improvement
Best single (DNS)67.2%Baseline
Best 2 (DNS + CT)78.4%+11.2%
Best 3 (+ IP Range)85.7%+7.3%
Best 4 (+ Cloud)89.8%+4.1%
Best 5 (+ WHOIS)91.4%+1.6%
All 692.6%+1.2%

Security rating correlation with actual incidents (200 organizations):

GradeAvg Incidents/YearCorrelation (r)
A0.8--
B2.4--
C5.7--
D11.3--
F24.1--
Overall r--0.81

Discovery time by organization size:

Asset CountDiscovery TimeWithin 60 min?
10-504.2 minutesYes
50-20012.8 minutesYes
200-1,00031.4 minutesYes
1,000-5,00047.2 minutesYes
5,000-10,00068.4 minutesNo (14% over)

Analysis

Discovery completeness of 92.6% exceeds our 90% target. The result validates that passive-only techniques (no active port scanning, no intrusive probes) can achieve near-comprehensive asset discovery. The 7.4% gap represents assets that are not visible through any public data source -- typically internal services accidentally exposed on non-standard ports or ephemeral cloud resources.

The multi-method improvement of 37.8% (from 67.2% single-method to 92.6% combined) exceeds our 35% hypothesis. Each additional method contributes unique assets not discoverable by others: Cloud Resources has the highest unique contribution (11.3%) because cloud-specific metadata is invisible to traditional DNS and certificate techniques.

The security rating correlation of r = 0.81 exceeds the 0.75 target, validating the rating system's predictive value. The strongest signal comes from the grade extremes: A-rated organizations average 0.8 incidents per year while F-rated organizations average 24.1 -- a 30x difference. This demonstrates that the 8-category evidence-based scoring captures genuine security posture differences.

The 60-minute target was met for organizations with up to 5,000 assets but exceeded by 14% for the 5,000-10,000 range. The bottleneck is Certificate Transparency log analysis, which must query multiple CT log aggregators for large certificate footprints. Parallel query optimization could bring this within the target.

The NABLA Signal Plurality requirement (minimum 2 evidence sources per rating category) was satisfied for 94.3% of assessments. The 5.7% failure rate was concentrated in Email Security for organizations with non-standard email configurations.

Conclusions

  1. 92.6% passive discovery completeness validates the multi-method approach.
  2. 6 methods provide 37.8% improvement over any single method.
  3. Security ratings correlate at r = 0.81 with actual incident frequency.
  4. 60-minute discovery is achievable for organizations up to 5,000 assets.
  5. Cloud resource discovery provides the highest unique contribution among all methods.

Next Steps

  • Implement active scanning mode (with explicit authorization) for the 7.4% gap
  • Optimize Certificate Transparency queries for 10,000+ asset organizations
  • Add historical asset tracking to detect newly appearing and disappearing assets
  • Build comparative industry benchmarking using aggregate rating data
  • Integrate discovery results with Color Team for automated attack path analysis
  • Develop NIS2 and ZKB compliance assessment modules using discovery data

Connect & Contribute

Created by Tomáš Korcak (korczis) | Open Source under GHL