Introduction
To secure your external attack surface, you first need to know what the internet can actually reach.
That sounds simple, but most exposure does not live in one place. It spreads across domains, subdomains, DNS records, certificates, cloud services, CDNs, APIs, login pages, admin panels, public files, ports, third-party vendors, and old URLs that teams forgot about.
A one-time scan helps, but it is not enough. External attack surfaces change whenever someone ships a release, creates a preview app, changes DNS, adds a SaaS integration, opens a cloud rule, points a CNAME at a vendor, or forgets to remove a staging hostname.
This guide gives you a practical step-by-step workflow to discover, reduce, harden, verify, and monitor internet-facing exposure.
What you need before you start
Before you scan anything, define scope. Only test domains, subdomains, IPs, cloud resources, and applications you own or have explicit permission to assess.
You also need a basic owner map. The goal is not only to find exposure; it is to route each issue to the team that can fix it.
Start with a small inventory file. It does not need to be perfect on day one, but it should make ownership, environment, and expiry visible.
Example inventory format:
```json { "assets": [ { "domain": "example.com", "owner": "platform-security", "environment": "production", "business_purpose": "public website", "data_classification": "public", "expiry_date": null, "monitoring_required": true }, { "domain": "preview-42.example.com", "owner": "frontend-team", "environment": "preview", "business_purpose": "temporary release preview", "data_classification": "internal-test-data", "expiry_date": "2026-06-30", "monitoring_required": true }, { "domain": "api.example.com", "owner": "backend-team", "environment": "production", "business_purpose": "customer API", "data_classification": "customer-data", "expiry_date": null, "monitoring_required": true } ] } ```
| Field | Why it matters | Example |
|---|---|---|
| Asset | Defines what is in scope | api.example.com |
| Owner | Routes findings to the team that can fix them | backend-team |
| Environment | Separates production, staging, preview, and test exposure | production |
| Business purpose | Explains why the asset is public | customer API |
| Data classification | Helps prioritize sensitive systems | customer-data |
| Expiry date | Prevents temporary assets from becoming permanent | 2026-06-30 |
| Monitoring required | Marks assets that need recurring checks | true |
Step 1 — Build a complete external asset map
The first step to secure your external attack surface is asset discovery.
Start from known root domains, then expand outward through DNS, certificate transparency, passive DNS, public search, cloud records, vendor CNAMEs, and historical URLs.
For DNS basics, list authoritative name servers and core records:
```bash dig NS example.com +short dig A example.com +short dig AAAA example.com +short dig MX example.com +short dig TXT example.com +short ```
For certificate transparency discovery, use a source such as crt.sh to identify hostnames that have appeared in certificates:
```bash curl -s 'https://crt.sh/?q=%25.example.com&output=json' \ | jq -r '.[].name_value' \ | tr '\r' '\n' \ | sort -u ```
Expected output may include production, staging, API, CDN, and forgotten hostnames:
```text api.example.com app.example.com cdn.example.com staging-api.example.com old-vendor.example.com ```
Certificate transparency output can include duplicates, wildcard names, stale names, and names that no longer resolve. Treat it as discovery input, not verified exposure.
Step 2 — Verify what is actually reachable
A hostname is not automatically a live asset. After discovery, resolve and check what responds.
Use DNS resolution first:
```bash while read host; do ip=$(dig +short "$host" | tail -n 1) if [ -n "$ip" ]; then echo "$host,$ip" fi done < subdomains.txt ```
Expected output should map live names to resolved targets:
```text api.example.com,203.0.113.20 app.example.com,203.0.113.30 staging-api.example.com,198.51.100.42 ```
Then check HTTP and HTTPS safely for assets you own:
```bash while read host; do echo "== $host ==" curl -I -L --max-time 10 "https://$host" 2>/dev/null | head -n 20 done < live-hosts.txt ```
Expected evidence should include status code, server behavior, redirects, security headers, and whether the endpoint is reachable over HTTPS.
Do not mark a hostname safe only because it returns 404. A 404 page can still reveal a live service, framework, CDN route, login page, or misconfigured backend.
| Signal | Why it matters | Example action |
|---|---|---|
| DNS resolves | Asset still points somewhere | Confirm owner and purpose |
| HTTP responds | Web surface is reachable | Check headers, redirects, login, and sensitive files |
| HTTPS fails | TLS or certificate issue may affect users and security | Fix certificate, TLS config, or redirect behavior |
| Redirect chain | Can expose old hosts, vendor domains, or downgrade paths | Validate final destination and HTTPS enforcement |
| Unknown server banner | May reveal unmanaged infrastructure | Assign owner or decommission |
| Preview or staging label | Often weaker than production | Restrict access or remove public exposure |
Step 3 — Lock down exposed services and ports
External attack surface is not only web pages. Open ports can expose databases, caches, admin interfaces, remote access services, CI/CD tools, message queues, and internal services.
Only scan IPs and hosts you own or are authorized to test. For a small owned range, use a focused service check:
```bash nmap -Pn -sV --top-ports 100 203.0.113.10 ```
`--top-ports 100` is a fast triage setting, not complete port coverage. Use a broader approved scan profile for high-value production assets.
For a specific owned host:
```bash nmap -Pn -sV -p 22,80,443,8080,8443 api.example.com ```
Expected output should show only intentional public services:
```text PORT STATE SERVICE VERSION 80/tcp open http nginx 443/tcp open https nginx 8080/tcp closed http-proxy 8443/tcp closed https-alt ```
Anything unexpected needs an owner, business reason, authentication review, and exposure decision.
High-risk examples include exposed Redis, MongoDB, Elasticsearch, PostgreSQL, MySQL, RDP, SSH without restrictions, Kubernetes dashboards, Jenkins, admin panels, and unauthenticated monitoring tools.
| Exposure | Priority | Recommended fix |
|---|---|---|
| Public database or cache | Critical | Remove public access, restrict network path, rotate credentials, and check logs |
| Public admin panel | High | Move behind SSO, VPN, allowlist, or private network |
| SSH open to internet | Medium to high | Restrict source IPs, require keys, disable passwords, and monitor login attempts |
| Old app server on 8080 or 8443 | High if unmanaged | Assign owner, patch, restrict, or decommission |
| Expected public HTTPS | Normal | Validate TLS, headers, redirects, authentication, and sensitive routes |
| Unknown service banner | High until owned | Identify owner and decide whether it should remain public |
Step 4 — Harden DNS, email, TLS, and HTTP headers
After finding what is reachable, harden the controls that define trust at the edge.
Start with DNS and email authentication:
```bash dig TXT example.com +short dig TXT _dmarc.example.com +short dig CAA example.com +short dig DNSKEY example.com +short dig DS example.com +short ```
Expected healthy output depends on your policy, but it may look like this:
```text "v=spf1 include:_spf.example-mailer.com -all" "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com" 0 issue "letsencrypt.org" 257 3 13 AbCdEfExampleDnskeyMaterial 12345 13 2 2BB183AF5F22588179A53B0A98631FAD1A292118 ```
Look for SPF, DKIM, DMARC, CAA, DNSSEC status, and unexpected verification tokens. A weak DMARC policy such as `p=none` may be acceptable during rollout, but production sending domains should have a plan to move toward stronger enforcement.
Treat DNSSEC as a policy and risk decision. If your organization requires DNSSEC for the domain, missing DS or DNSKEY evidence should become a finding; otherwise record it as posture context.
Then verify TLS and HTTPS behavior:
```bash curl -I -L https://example.com openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -issuer -subject -dates ```
Expected TLS output should show a valid certificate subject, issuer, and date range:
```text issuer=C = US, O = Example CA, CN = Example TLS CA subject=CN = example.com notBefore=May 01 00:00:00 2026 GMT notAfter=Jul 30 23:59:59 2026 GMT ```
Finally, check browser security headers:
```bash curl -I https://example.com | grep -Ei 'strict-transport-security|content-security-policy|x-frame-options|referrer-policy|permissions-policy|x-content-type-options' ```
Expected header output on a sensitive authenticated app may look like this:
```http Strict-Transport-Security: max-age=31536000; includeSubDomains Content-Security-Policy: default-src 'self'; object-src 'none'; frame-ancestors 'none' X-Content-Type-Options: nosniff Referrer-Policy: strict-origin-when-cross-origin Permissions-Policy: geolocation=(), camera=(), microphone=() ```
Missing headers are not all equal. Prioritize headers on authenticated apps, admin surfaces, payment flows, account pages, and APIs that return sensitive data.
| Control | What good looks like | Risk if weak |
|---|---|---|
| DMARC | Policy aligned with sender maturity, moving toward quarantine or reject | Email spoofing and phishing support |
| SPF | Only approved senders listed; avoid excessive includes | Unauthorized sending paths |
| DKIM | Outbound mail is signed by approved senders | Weak sender authentication |
| CAA | Approved certificate authorities defined where appropriate | Unexpected certificate issuance paths |
| DNSSEC | Enabled when required by organizational policy or risk model | DNS integrity posture gap where DNSSEC is required |
| TLS | Valid certificate, modern protocols, secure ciphers | Downgrade risk, user trust failures, weak transport security |
| HSTS | Enabled after HTTPS is stable across required hosts | Protocol downgrade and accidental HTTP access |
| CSP | Restricts script, frame, object, and connection sources | Higher impact from XSS and content injection |
| X-Frame-Options or frame-ancestors | Clickjacking protection for sensitive pages | UI redress attacks |
Step 5 — Find public files, secrets, and risky historical URLs
Some of the highest-impact external findings are simple files that should not be public.
Check common sensitive paths on assets you own. Use safe, low-volume requests and avoid downloading large files.
Example controlled checks:
```bash for path in /.env /.git/config /backup.zip /db.sql /config.json /admin /swagger.json /openapi.json; do echo "== $path ==" curl -sI --max-time 10 "https://example.com$path" | head -n 10 done ```
Expected safe output is usually a 404, 403, or redirect to an approved authentication layer:
```http HTTP/2 404 content-type: text/html ```
Risky output may look like this:
```http HTTP/2 200 content-type: text/plain content-length: 842 ```
A `200 OK` does not always mean exposure, and a `403` can still reveal a sensitive path. Follow suspicious owned paths with a small controlled read only when authorized:
```bash curl -s --range 0-300 https://example.com/.env ```
Do not use `-k` by default because it disables TLS certificate validation. Use it only in a controlled troubleshooting case where the TLS failure itself is already recorded as a finding.
Also review historical URLs from sources such as the Internet Archive. Old paths can reveal abandoned admin routes, backups, API versions, debug files, and forgotten parameters.
Do not paste secrets or sensitive file contents into broad tickets. Record the minimum evidence needed, rotate exposed credentials, remove the file, and invalidate cached copies where possible.
| Finding | Why it matters | Immediate action |
|---|---|---|
| .env file | May expose credentials, tokens, database URLs, or cloud secrets | Remove file, rotate secrets, review logs |
| .git/config | May expose repository origin and source structure | Block access and review source exposure |
| Backup archive | May contain source, data, or credentials | Remove, investigate access, rotate secrets |
| Swagger or OpenAPI file | Can reveal hidden endpoints and auth patterns | Confirm whether public docs are intentional |
| Old admin URL | May expose unmanaged authentication surface | Restrict, decommission, or move behind approved access |
| JavaScript endpoint leakage | Can expose API paths, feature flags, or keys | Classify keys and remove sensitive values |
Step 6 — Check cloud, third-party, and takeover exposure
External exposure often comes from services outside the main app repository.
Review cloud storage, object buckets, Firebase-style backends, CDN routes, vendor CNAMEs, abandoned SaaS assets, and public preview environments.
For AWS S3, check account-level public access block first:
```bash aws s3control get-public-access-block --account-id 123456789012 ```
Expected output should show public access blocks enabled:
```json { "PublicAccessBlockConfiguration": { "BlockPublicAcls": true, "IgnorePublicAcls": true, "BlockPublicPolicy": true, "RestrictPublicBuckets": true } } ```
Then inspect specific buckets you own:
```bash aws s3api get-bucket-policy-status --bucket example-bucket aws s3api get-public-access-block --bucket example-bucket ```
Expected bucket policy status for a private bucket:
```json { "PolicyStatus": { "IsPublic": false } } ```
For DNS takeover candidates, look for CNAMEs pointing to vendors that are no longer configured:
```bash dig CNAME old-app.example.com +short curl -I https://old-app.example.com ```
Expected risky clues include vendor error pages, unclaimed project messages, dangling CNAMEs, and records pointing to deleted cloud resources:
```text old-app.vendor-hosting.example. HTTP/2 404 server: vendor-edge x-error: project-not-found ```
Cloud provider behavior differs across AWS, Azure, GCP, Firebase, CDNs, and SaaS vendors. Validate each finding against the provider’s current documentation before declaring takeover impact.
| Area | What to check | Fix |
|---|---|---|
| Object storage | Public bucket policy, public ACL, public website hosting, exposed backups | Block public access unless explicitly required and reviewed |
| Vendor CNAME | DNS points to a vendor service that no longer has an active claim | Reclaim the vendor resource or delete the DNS record |
| Preview apps | Public preview environments without auth or expiry | Require access control and expiry dates |
| Firebase or backend services | Public database or storage rules | Restrict rules and test unauthenticated access |
| CDN routes | Origin exposure, header drift, cache leaks, weak redirects | Restrict origin access and validate cache behavior |
| Cloud IPs | Unknown services attached to public IPs | Assign owner, restrict security group, or remove |
Step 7 — Prioritize, fix, and verify remediation
A secure external attack surface workflow needs prioritization. Otherwise, every missing header competes with every exposed database.
Prioritize based on exploitability, sensitivity, exposure path, authentication, business criticality, and whether multiple findings form an attack chain.
Use a simple finding record that engineers can act on:
```json { "asset": "staging-api.example.com", "finding": "public admin login surface", "severity": "high", "owner": "backend-team", "evidence": "https://staging-api.example.com/admin returned 200 OK", "risk": "admin workflow exposed to public internet", "fix": "move behind SSO or restrict source networks", "validation": "external request from untrusted network returns 403 or redirects to SSO", "due_date": "2026-05-18" } ```
After a fix, retest the exact condition. Do not close the ticket only because the code was merged or the firewall rule was changed.
The validation step should prove that the risky external behavior is gone.
Expected validation evidence should be concrete:
```http HTTP/2 403 content-type: application/json {"error":"access denied"} ```
| Finding | Priority | Why |
|---|---|---|
| Public database, cache, or internal service | Critical | Direct exposure can lead to data compromise or service abuse |
| Sensitive file or secret exposed | Critical | Credentials may already be compromised and must be rotated |
| Confirmed subdomain takeover candidate | High | Trusted hostname may be claimable by an attacker |
| Public admin panel without approved controls | High | Credential attacks and admin workflow abuse become possible |
| Weak DMARC on production sending domain | Medium to high | Can support phishing and brand impersonation |
| Missing security headers on authenticated app | Medium | Can increase browser-side attack impact |
| Unknown asset without owner | High until resolved | Unowned systems usually stay unpatched and unmonitored |
How to automate and monitor this continuously
Securing the external attack surface is not a one-time project.
Create a recurring monitoring loop for verified domains, high-value applications, production APIs, login surfaces, and cloud-exposed assets.
At minimum, monitor for new subdomains, new exposed services, DNS changes, certificate changes, header drift, TLS changes, sensitive files, takeover candidates, weak email authentication, admin panels, and score or severity changes.
Use alerts carefully. Alert on new high-risk exposure immediately, but route lower-risk hygiene drift into scheduled review so teams do not ignore the channel.
A useful monitoring loop looks like this:
```text Discover assets → classify exposure → assign owner → fix → validate → compare history → alert on drift → repeat ```
| Check | Suggested cadence | Why |
|---|---|---|
| New subdomains and certificates | Daily or continuous | New assets often appear outside release review |
| Exposed services and ports | Daily or weekly depending on risk | Cloud and firewall changes can publish services suddenly |
| Sensitive files and admin panels | Daily or after deployment | Deployment mistakes can expose high-impact paths |
| DNS and email security | Weekly and after DNS changes | Provider migrations can weaken SPF, DKIM, DMARC, or CAA |
| TLS and headers | After deploy and recurring | CDN, proxy, and framework changes can remove protections |
| Unowned or temporary assets | Weekly until resolved | Temporary assets become permanent without expiry enforcement |
How ExternalSight helps secure your external attack surface
ExternalSight is built for security teams that need to secure internet-facing domains with repeatable external attack surface monitoring.
It combines on-demand asynchronous scans, continuous monitoring for verified domains, issue classification, remediation planning, historical comparison, alerting, PDF export, JSON export on supported plans, and plan-gated notifications and webhooks.
Its scanner workflow covers DNS, certificate transparency, subdomains, technology detection, SSL/TLS, HTTP headers, TLS configuration, subdomain takeover, subdomain HTTPS, API discovery, JavaScript endpoints, cookie security, CORS, mixed content, redirects, credentials, secrets, phishing, ports, cloud exposure, email spoofing, zone transfer, admin panels, HTTP configuration, infrastructure, login surface, sensitive files, open redirects, host header issues, GraphQL, exposed services, Firebase, Wayback, supply chain, asset discovery, IP intelligence, WAF, robots.txt, security.txt, sitemap, reputation, WHOIS, CSP, Shodan, passive DNS, OTX, and attack-chain evaluation.
Continuous monitoring is available for verified domains on supported plans. Domain verification can use a DNS TXT record or an HTTPS file under `/.well-known/externalsight.txt`.
Some external-source checks may report unavailable when API keys or upstream services are not configured. Review scan coverage before treating a clean scan as a clean surface.
ExternalSight does not replace secure engineering, cloud security controls, a SIEM, a SOC, a WAF, vulnerability management, or penetration testing. Its role is to help teams discover, classify, remediate, export, alert on, and monitor externally visible exposure.
Common mistakes and how to avoid them
Most teams do not fail because they lack tools. They fail because ownership, scope, and validation are unclear.
Avoid these mistakes when building your workflow.
- Scanning once and stopping — A clean scan today does not cover DNS, cloud, CDN, or release drift tomorrow.
- Ignoring scan coverage — Unavailable scanners, missing API keys, and upstream errors mean the scan is incomplete, not clean.
- No owner field — Findings without owners become dashboard debt.
- Treating subdomains as low risk — Forgotten subdomains can expose admin panels, staging data, or takeover candidates.
- Fixing symptoms instead of exposure paths — Closing a port is not enough if the same service reappears through another host or cloud rule.
- Skipping validation — A merged fix is not proof that the external exposure is gone.
- Trusting only one data source — DNS, CT logs, passive DNS, Wayback, cloud inventory, and active checks reveal different parts of the surface.
- Testing assets without authorization — Only test systems you own or have explicit permission to assess.
Key takeaways
- {'text': 'To secure your external attack surface, start with owned scope, asset inventory, and clear owners.'}
- {'text': 'Discovery should combine DNS, certificate transparency, live reachability checks, ports, web surfaces, cloud exposure, vendors, and historical URLs.'}
- {'text': 'Prioritize public databases, sensitive files, takeover candidates, admin panels, exposed services, and unowned assets before lower-risk hygiene findings.'}
- {'text': 'Fixes must be validated from the outside, not only marked complete after a code or firewall change.'}
- {'text': 'Monitoring is required because external exposure changes through releases, DNS edits, cloud changes, CDN updates, and vendor lifecycle events.'}
- {'text': 'Review scan coverage before treating a clean result as proof that the external surface is clean.'}
Frequently asked questions
- How do I secure my external attack surface?
- Start by defining owned scope, discovering external assets, verifying what is reachable, reducing exposed services, hardening DNS, email, TLS, and headers, checking for secrets and sensitive files, assigning owners, validating fixes, and monitoring for drift.
- What should I check first on my external attack surface?
- Check for public databases, caches, admin panels, sensitive files, exposed secrets, takeover candidates, unowned subdomains, weak email authentication, and unknown services. These usually create more immediate risk than lower-priority hygiene gaps.
- Is one scan enough to secure an external attack surface?
- No. One scan gives a point-in-time view. External attack surfaces change when teams deploy code, change DNS, modify cloud rules, add vendors, create preview apps, or remove infrastructure. Recurring monitoring is required.
- What is the difference between asset discovery and attack surface security?
- Asset discovery finds domains, subdomains, IPs, services, and public endpoints. Attack surface security goes further by classifying risk, assigning owners, fixing exposure, validating remediation, comparing history, and monitoring for new drift.
- How does ExternalSight help secure an external attack surface?
- ExternalSight scans internet-facing domains, classifies findings, generates remediation planning, compares scan history, sends alerts, exports reports, reviews scan coverage, and monitors verified domains on supported plans.
References and further reading
- OWASP Web Security Testing Guide — Information gathering — https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/01-Information_Gathering/
- OWASP Web Security Testing Guide — Configuration and deployment management testing — https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/02-Configuration_and_Deployment_Management_Testing/
- CIS Controls v8.1 — https://www.cisecurity.org/controls/v8
- CISA — Known Exploited Vulnerabilities Catalog — https://www.cisa.gov/known-exploited-vulnerabilities-catalog
- CISA — Reduce the likelihood of damaging intrusions — https://www.cisa.gov/resources-tools/resources/reduce-likelihood-damaging-intrusions
- MITRE ATT&CK — Reconnaissance — https://attack.mitre.org/tactics/TA0043/
- MITRE ATT&CK — External Remote Services — https://attack.mitre.org/techniques/T1133/
- NIST SP 800-53 Rev. 5 — https://csrc.nist.gov/publications/detail/sp/800-53/rev-5/final
- RFC 9116 — security.txt — https://www.rfc-editor.org/rfc/rfc9116
Start securing your external attack surface
ExternalSight helps teams scan internet-facing domains, classify external findings, generate remediation plans, compare scan history, receive alerts, export reports, review scan coverage, and monitor verified domains on supported plans. Use it to turn external exposure into owner-assigned, validated security work.