Fundamentalsattack surfaceexposureendpointsenumerationminimisation

Attack Surface

The attack surface is the set of places an attacker can send input or trigger behaviour — and reducing it is usually cheaper, more durable and more measurable than defending every entry you leave open.

▶ Run the labFollow the failure

Frame the problem

Security starts with a concrete asset, attacker capability and trust crossing.

Asset
Every capability reachable through an exposed interface: reading data, writing data, spending money, running code, granting access.
Attacker & capability
An unauthenticated internet client to begin with; then an authenticated low-privilege user; then a compromised internal component. Each sees a different surface.
Trust boundary
The outermost boundary — everything that answers a request from somewhere you do not control.
AssetThreatAttack SurfaceTrust BoundaryVulnerabilityExploit PathImpactMitigationDefense in DepthResidual Risk

Three questions, in order

Attack surface analysis is a triage tool. List every entry point, then answer three questions about each one, and the priority order falls out without argument.

Which of these can an attacker reach? Not "which are documented" — which *answer*. Old API versions still routed, a staging host with production data, a health endpoint that dumps configuration, an object store with a guessable name, a mobile app's hard-coded base URL pointing at an internal service.

Which require authentication? An unauthenticated endpoint is available to the entire internet in parallel, forever. That is a different risk class from something behind login, and it is where scanning finds things first.

Which perform privileged actions? An endpoint that reads a public product catalogue and an endpoint that issues a refund are both "an API route". Only one of them turns a bug into money. Sorting by privilege rather than by traffic is what stops teams from hardening the busiest endpoint instead of the most dangerous one.

The standard surface inventory, and what to ask about each
Entry pointTypically reachable byThe question that matters
Public endpointsAnyone on the internetWhat can be done here with no account at all?
Login and registrationAnyoneCan it be used to enumerate users, or to try credentials in bulk?
Authenticated APIAny customerCan one customer name another customer's resource id and get it?
Admin endpointsStaff — in theoryIs that enforced server-side, or by not linking to it in the UI?
File uploadsAny customerWhere does the file land, who can fetch it, and what parses it?
WebhooksAnyone who knows the URLIs the signature verified before the payload is trusted?
External integrationsA partner — and anyone who compromises themWhat can that integration do inside our system?
Database accessServices, operators, backup jobsHow many identities can read the whole table, and why?
Cloud APIsAnything holding a credentialWhat is the widest policy attached to a workload that faces the internet?
AI toolsWhatever the model decides to callWhich tools have side effects, and who authorizes them?

Surface is a function of who you are

A single map is not enough, because the surface visible to an anonymous scanner is not the surface visible to a paying customer, and neither resembles the surface visible to a compromised background worker. Model at least three vantage points, and the interesting findings are usually in the second and third.

From anonymous, the surface is login, registration, password reset, public content, webhooks, and whatever DNS and certificate transparency reveal. From authenticated low-privilege, it expands to the entire product API — and this is where object-level authorization bugs live, because now every resource id is guessable and reachable. From compromised internal component, the surface is the internal network: service-to-service endpoints with no authentication, the metadata service, admin tooling, and the database itself.

That third vantage point is why Server-Side Request Forgery (SSRF) is so valuable to an attacker and why Egress Security exists: turning "I can make the server fetch a URL" into "I am now an internal client" collapses two of the three surfaces into one.

The same system seen from three vantage points
AnonymousAuthenticated userCompromised workerLogin · signup · reset · public APIProduct API (every resource id)Internal services · metadata · adminDatabase · object storage · secrets
UserLLMAgentToolDataDecisionHumanGuardrail

Reduction beats hardening

Every entry point you keep must be defended forever, by every future engineer, through every refactor. Every entry point you remove is defended permanently for free. This asymmetry is why surface reduction is the highest-return security work available to most teams and why it rarely appears in a vulnerability scanner's output.

Concretely: delete the API version nobody calls; require authentication on the endpoint that "does not return anything sensitive" (it returns timing, existence and error text); move the admin panel behind a separate network path rather than a role check alone; take the debug route out of the production build rather than gating it on a flag; stop the service from being able to make arbitrary outbound requests at all.

Surface also grows silently, which is the real problem. Each deploy can add routes, each dependency can add a listener, each cloud resource defaults to some exposure. The durable fix is an inventory that is generated rather than maintained by hand — routes enumerated from the router, cloud resources from the provider API, public buckets from a scheduled check — so that "what is exposed?" has a current answer rather than a last-quarter answer.

Key points

  • Ask in order: reachable, authenticated, privileged. The last one sets priority; the first one is the one teams get wrong.
  • Map the surface separately for anonymous, authenticated and internal-compromise vantage points — the last two hold the interesting findings.
  • Removing an entry point defends it forever; hardening one defends it until the next refactor.
  • Surface grows with every deploy, so the inventory must be generated from the running system, not maintained in a document.
  • SSRF is valuable precisely because it converts the outer surface into the internal one.

Attack Surface Mapper

Change the system and observe which assumption moves.

1Click a component to place it in the system
Placed components appear in the diagram below, left to right.
5 placed
2Click a link between two components to mark a trust boundary
A boundary is any point where you stop assuming the other side is well behaved.
User
PUBLIC / REACHABLE
Browser
PUBLIC / REACHABLE
API
PUBLIC / REACHABLE
Backend
PRIVILEGED
Database
SENSITIVE
3Read what the model says
These are questions to verify in code and configuration, not conclusions.
Boundary review 2 marked
  • Browser → API: authenticate the caller, validate the data and authorize the operation.
  • Backend → Database: authenticate the caller, validate the data and authorize the operation.
  • Unmarked: User → Browser, API → Backend. If the other side were hostile, would anything here need checking?
Possible threats
  • • Identity question: which component authenticates human and machine principals?

The builder suggests questions, not certainty. Verify each control in code, policy and production configuration; record residual risks and unknowns.

Follow the attack

Safe conceptual simulation: capability → missing control → crossed boundary → asset impact.

  1. 1
    Attacker → enumeration: DNS records, certificate transparency logs, JavaScript bundles, mobile app strings, error messages, and simple path guessing.
  2. 2
    Enumeration → inventory: a list of hosts and routes, sorted by "answers without credentials" and "sounds privileged".
  3. 3
    Inventory → probing: send malformed, oversized, unexpected-type and unauthorized-id requests and read the differences in response codes, timing and error text.
  4. 4
    Probing → foothold: the endpoint that behaves differently is the one with the bug; the surface analysis just told the attacker where to spend time.
Blast radius
  • A forgotten endpoint has no owner, no tests and no monitoring, so a bug there is both more likely and less likely to be noticed.
  • Staging and preview environments with production data turn a low-priority environment into a full data-exposure path.
  • Every additional exposed integration adds not only its own risk but the risk of the partner who holds its credentials.

Defend, detect, recover

One prevention is a single point of security failure. Layer it and make failure observable.

Prevent
  • • Generate the route and resource inventory automatically and diff it on every deploy; new public exposure should require a decision, not a merge.
  • • Default new endpoints to authenticated and new storage to private; make "public" the explicit, reviewed exception.
  • • Delete deprecated API versions on a schedule rather than leaving them routed indefinitely.
  • • Separate admin surfaces by network path and identity, not only by a role check inside the same application.
Detect
  • • Scheduled external scans from outside your own network, so you see what an attacker sees rather than what your VPN shows you.
  • • Alert on cloud configuration changes that increase exposure: a bucket policy, a security group opened to `0.0.0.0/0`, a load balancer added.
  • • Watch for traffic to routes that receive no legitimate traffic — an endpoint whose only callers are scanners is a candidate for deletion.
Respond & recover
  • • Remove exposure first (close the route, make the bucket private, revoke the integration), then work out what was reached.
  • • Treat any data in a wrongly exposed store as exposed for the entire period it was exposed, not from the moment you noticed.
  • • Add the missing inventory check as part of the fix, since the same class of exposure will recur otherwise.
Residual risk
  • • You cannot enumerate what you do not own: partner integrations, third-party scripts and vendor subdomains extend your surface outside your control.
  • • Authenticated surface remains large by necessity; reduction helps least exactly where object-level authorization matters most.
  • • Removal is politically hard — someone is always using the old version — so surface tends to ratchet up.

Misconceptions

Claim
“It is not linked from anywhere, so nobody will find it.”
Reality
Route enumeration is automated and cheap. JavaScript bundles list API paths, certificate transparency lists hostnames, and scanners try common paths continuously.
Claim
“Staging does not matter.”
Reality
Staging with a copy of production data is production data with weaker controls, weaker monitoring and shared credentials.