Skip to content

Running Reconnaissance

Samuele Giampieri edited this page Oct 26, 2026 · 48 revisions

📖 Canonical version: read this page on the official docs site — https://www.redamon.org/docs/running-reconnaissance. The GitHub wiki is a mirror.

Running Reconnaissance

Interactive walkthrough: Inside the Recon Pipeline

The reconnaissance pipeline is RedAmon's core scanning engine — a fully automated, parallelized process that maps your target's entire attack surface using a fan-out / fan-in architecture. Independent modules run concurrently via ThreadPoolExecutor, while data-dependent steps run sequentially. This page explains how to launch a scan, monitor its progress, and understand the results.


Before You Start

Make sure you have:

  1. A user selected (see User Management)
  2. A project created with a target domain, IP/CIDR targets, or a Domain batch hostname list configured (see Creating a Project and Domain batch below)
  3. The Red Zone open with your project selected (see Red Zone)

Tip: Use a Recon Preset when creating your project to quickly configure the pipeline for your use case (e.g., bug bounty, stealth recon, API security audit).


Step 1: Start the Reconnaissance

  1. On the Red Zone, locate the Recon Actions group (blue) in the toolbar
  2. Click the "Start Recon" button

A confirmation modal appears showing:

  • Your project name and target domain
  • Current graph statistics (how many nodes of each type already exist, if any)
  • If a graph already exists, an Existing Data Found notice with a scan mode choice: Create a new version (recommended) (snapshot the current graph before the scan overwrites it, confirm button Save Version & Start) or Overwrite current version (Discard & Start). This is part of Scan Timeline; "Create a new version" freezes the outgoing graph first (fail-closed) so nothing is lost.

Recon Confirmation Modal

  1. Click "Confirm" to start the scan

The "Start Recon" button changes to a spinner while the scan is running.


Step 2: Monitor Real-Time Logs

Once the scan starts, a Logs button (terminal icon) appears in the Recon Actions group.

  1. Click the Logs button to open the Logs Drawer on the right side
  2. Watch the real-time output as each phase progresses

Recon Logs Drawer

The logs drawer shows:

  • Current phase with phase number (e.g., "Phase 3: HTTP Probing"). It comes from the pipeline's own step headers, so it only moves forward within a scan (a Domain batch starts again at phase 1 for each domain), and it is kept up to date even when nobody has the drawer open: the status the toolbar and MCP get_recon_status report shows it too, refreshed at least every 30 seconds.
  • Log messages streaming in real-time as the scan progresses
  • A Clear button to reset the log display

Stopping and pausing a scan

Stop

Stop (and MCP stop_recon, and a partial recon's stop) is asynchronous. The scan shows Stopping at once, then:

  • the scan's tool containers end at once (naabu, httpx, nuclei, and every other tool the scan started). Only this scan's own: another project's scan running at the same time is never touched;
  • the scan lands the graph writes it had already queued, so what it found up to the stop reaches the graph;
  • it applies your mute rules to what it wrote, so muted noise stays muted;
  • it ends within the stop grace, 45 seconds by default (RECON_STOP_GRACE_S in .env), and the status returns to idle. The scan history records it as canceled.

Requests a scan was already making from inside its own process (security checks, OSINT lookups, JavaScript downloads) are allowed to finish within that grace; the scan starts no new phase and no new tool once you press Stop. A stopped scan never removes earlier findings: that happens only at the end of a scan that ran to completion. You cannot start a new scan of the project while one is stopping.

Deleting a project stops its scans at once, without the grace, so nothing is written into the deleted project.

Pause and Resume

Pause (and Emergency Pause All, which pauses the full recon and stops partial recons) freezes the scan and every tool container it started, so a paused scan sends no more traffic to the target: a Nuclei pass in progress is frozen too, not left to finish. Tools of other scans are not touched.

Resume unfreezes the tools, then the scan. When the project has a Rules of Engagement time window, Resume checks it first: outside the window the resume is refused with the same message a refused start gets, a notice says so, and the scan stays paused. If RedAmon cannot read the project's settings at that moment, the resume is refused too.

A long pause can time out the connections a tool had open, so after a resume some hosts may be marked unreachable for the rest of the scan; the scan's coverage notes list them.


Step 3: Watch the Graph Build

While the reconnaissance runs, the graph canvas auto-refreshes every 5 seconds. You'll see nodes appearing and connecting in real-time:

  • First, Domain and Subdomain nodes appear (GROUP 1 -- parallel: WHOIS + 5 discovery tools + URLScan)
  • Then IP nodes connect to subdomains (GROUP 1 -- DNS with 20 parallel workers)
  • ExternalDomain nodes appear from URLScan enrichment (GROUP 1)
  • New Subdomain, IP, Port, and Endpoint nodes appear from multi-engine search (GROUP 2b -- Uncover queries up to 13 search engines)
  • Port nodes attach to IPs, Shodan enrichment data merges in (GROUP 3 -- parallel: Naabu + Shodan)
  • Threat intelligence properties populate on IP and Domain nodes -- OTX pulse data, VirusTotal reputation scores, Censys service data, FOFA/ZoomEye/Netlas/CriminalIP host intelligence (GROUP 3b -- 7 tools parallel)
  • Port nodes get enriched with product/version/CPE, Technology and Vulnerability nodes appear from NSE scripts (GROUP 3.5 — Nmap service detection)
  • BaseURL, Service, and Technology nodes appear (GROUP 4 — HTTP Probe)
  • Endpoint and Parameter nodes branch out (GROUP 5 -- parallel: Katana + Hakrawler + GAU + Kiterunner, then jsluice + FFuf + ZAP Ajax Spider + Arjun, then OpenAPI)
  • Secret, Endpoint, and JsReconFinding nodes appear from JavaScript analysis (GROUP 5b -- JS Recon: 6 modules parallel)
  • Vulnerability and CVE nodes connect to affected resources (GROUP 6 Phase A -- Nuclei || GraphQL Security || Subdomain Takeover || VHost & SNI || Web Cache Poisoning run in parallel; Phase B -- MITRE enrichment)
  • GraphQL Endpoint capability flags (graphql_graphiql_exposed, graphql_tracing_enabled, graphql_get_allowed, etc.) populate on Endpoint nodes discovered as GraphQL services

Step 4: Download Results

When the scan completes:

  1. The spinner stops and the "Start Recon" button reappears
  2. A Download button (download icon) appears in the Recon Actions group
  3. Click it to download the complete results as a JSON file (recon_{projectId}.json)

Pipeline Architecture (Fan-Out / Fan-In)

The pipeline is organized into execution groups. Modules within each group run concurrently; groups execute sequentially because later groups depend on earlier results. Graph DB updates run in a dedicated background thread so the main pipeline is never blocked.

Settings Tab Phase Tools Type Execution
Discovery & OSINT Subdomain Discovery crt.sh, HackerTarget, Subfinder, Amass, Knockpy Passive* 5 tools parallel
Wildcard Filtering Puredns, then RedAmon's wildcard control Active Sequential
WHOIS + URLScan python-whois, URLScan.io API Passive Parallel
DNS Resolution dnspython Passive 20 parallel workers
OSINT Enrichment Shodan / InternetDB Passive Parallel with port scan
Uncover Expansion ProjectDiscovery Uncover (13 engines) Passive Before port scan (GROUP 2b)
Threat Intel Enrichment Censys, FOFA, OTX (AlienVault), Netlas, VirusTotal, ZoomEye, CriminalIP Passive 7 tools parallel (GROUP 3b)
Port Scanning Port Scanning Masscan, Naabu Active / Passive Both parallel (Naabu supports passive InternetDB mode)
Nmap Service Detection Service Version Detection Nmap (-sV, --script vuln) Active Sequential per target
HTTP Probing HTTP Probing httpx Active Internal parallel
Tech Detection Wappalyzer Passive Sequential (post-probe)
Banner Grabbing Custom (Python sockets: SSH, FTP, SMTP, MySQL, etc.) Active Parallel workers
IP Attribution Built in: the CDN signals already collected, plus one TLS handshake without SNI per IP with port 443 open Passive / Active Sequential, right after HTTP probing
Resource Enum Web Crawling Katana, Hakrawler Active Parallel
Archive Discovery GAU (Wayback, CommonCrawl, OTX) Passive Parallel with crawlers
Parameter Mining ParamSpider (Wayback CDX) Passive Parallel with crawlers
JS Analysis jsluice Active Sequential (post-crawl)
Directory Fuzzing FFuf Active Sequential (post-jsluice)
Browser Crawling ZAP Ajax Spider Active Sequential (post-FFuf), per-seed Docker containers in parallel
Parameter Discovery Arjun Active / Passive Methods parallel (GET/POST/JSON/XML)
API Discovery Kiterunner Active Sequential per wordlist
API Specification Import OpenAPI Active (documents only) Sequential, after every other source
JS Reconnaissance JS Recon 90+ secret patterns, source map discovery, dependency confusion, endpoint extraction, DOM sinks, framework detection Passive 6 modules parallel (GROUP 5b)
Vulnerability Scanning Vulnerability Scanning Nuclei (9,000+ templates + DAST + custom template upload) Active Parallel with GraphQL + Subdomain Takeover + VHost & SNI (GROUP 6 Phase A)
GraphQL Security GraphQL Security Testing Endpoint discovery, introspection test, schema extraction, sensitive-field detection, graphql-cop 12 misconfig checks Active / Passive Parallel with Nuclei + Subdomain Takeover + VHost & SNI (GROUP 6 Phase A)
Subdomain Takeover Subdomain Takeover Detection Subjack + Nuclei takeover templates + BadDNS sidecar, layered detection across CNAME/NS/MX/TXT/SPF Active Parallel with Nuclei + GraphQL + VHost & SNI (GROUP 6 Phase A)
VHost & SNI VHost & SNI Enumeration Hidden virtual host discovery via L7 (HTTP Host header) + L4 (TLS SNI) probes per candidate hostname; reveals reverse-proxy / k8s ingress / Cloudflare routing Active Parallel with Nuclei + GraphQL + Subdomain Takeover + Web Cache Poisoning (GROUP 6 Phase A)
Web Cache Poisoning Web Cache Poisoning WCVS breadth sweep + native 5-phase confirmation (cache oracle, isolated cache-buster, framework hypotheses, baseline→poison→clean persistence, scoring); reflected + non-reflective detection of cache poisoning & deception Active Parallel with Nuclei + GraphQL + Subdomain Takeover + VHost & SNI (GROUP 6 Phase A)
Security Checks Security Checks WAF bypass, direct IP access, TLS expiry, missing headers, cache-control Active Parallel workers
CVE & MITRE CVE Enrichment NVD API, Vulners API Passive Sequential
MITRE Enrichment CWE / CAPEC mapping Passive Sequential

*Amass can run in active mode when configured. Knockpy performs active DNS probing.

Each phase builds on the previous group's output. You can control which modules run via the Scan Modules setting in your project configuration.

Targeting Modes and the Pipeline

The groups below describe the Single Domain pipeline (the default). The other two targeting modes change only where GROUP 1 gets its input:

Single Domain IP / CIDR Domain batch
GROUP 1 Subdomain discovery (5 tools in parallel) + DNS (20 workers) + WHOIS + URLScan CIDR expansion → Reverse DNS (PTR) per IP → IP WHOIS Filtered DNS + WHOIS on the group's listed hostnames only (no discovery)
Graph root Domain node of the target's registrable domain Mock Domain node (ip-targets.{project_id}) One Domain node per registrable domain (groups of one domain share it)
GROUPs 3-6 Unchanged Unchanged Unchanged, run per group

In IP mode, each target IP is resolved via PTR to discover its hostname. When no PTR record exists, a mock hostname is generated (e.g., 192-168-1-1). The remaining groups (port scan through MITRE enrichment) run identically.

Domain batch runs this same Single-Domain pipeline once per domain group, one group after another, accumulating every group into a single graph and a single version. Subdomain discovery is off for the hostnames you listed, so those are scanned exactly as given. An entry written as a wildcard (*.example.com or *example.com) is the exception: that one domain gets the full subdomain enumeration a Single Domain project runs, and the rest of the list stays literal. See Domain batch below for the full walkthrough.


GROUP 1: Domain Discovery + WHOIS + URLScan (parallel)

Purpose: Map the target's subdomain landscape. All three top-level tasks (WHOIS, discovery, URLScan) run concurrently. Within discovery, all 5 tools run in parallel.

Techniques used (all concurrent):

  • Certificate Transparency via crt.sh — finds certificates issued for the domain. When crt.sh gives no answer (an error, a timeout, or paused after repeated failures), the same lookup is sent to crt.name instead. crt.name allows 100 requests per IP per day, so it is asked once per domain per run and stops for the run when that quota is spent. It refuses a domain with too many names (the log says so), and at most the first 50,000 names of an answer are read. Turning crt.sh off turns this fallback off too
  • HackerTarget API — passive DNS lookup
  • Subfinder — passive subdomain enumeration using 50+ online sources (certificate logs, DNS databases, web archives)
  • Amass — OWASP Amass subdomain enumeration using 50+ data sources (certificate logs, DNS databases, web archives, WHOIS). Supports optional active mode (zone transfers, certificate grabs) and DNS brute forcing
  • Knockpy — active subdomain brute-forcing (if useBruteforceForSubdomains is enabled)
  • WHOIS Lookup — registrar, dates, contacts, name servers (runs in parallel with discovery)
  • URLScan.io — historical scan data, subdomains, IPs, TLS metadata (runs in parallel with discovery)
  • DNS Resolution — A, AAAA, MX, NS, TXT, CNAME, SOA records for every discovered subdomain (20 parallel workers)

Output: Domain, Subdomain, IP, and DNSRecord nodes in the graph.

Wildcard DNS. A domain with wildcard DNS (*.example.com) answers every name, so a guessed name "exists". Puredns validates the merged list and drops wildcard answers. When it was meant to run and could not (no resolver list, no output, a timeout, an error), the report's Coverage Limitations shows a puredns line; switched off (or by Stealth Mode), it records nothing. Either way RedAmon's own wildcard control runs after DNS resolution:

  • It resolves up to three random names under each zone: the scan root, and any deeper parent with five or more discovered names. If they resolve, the zone is a wildcard zone.
  • A name whose addresses are all the wildcard's is dropped: it becomes no Subdomain and is never scanned. A name a passive source saw (a CT log, passive DNS) that has a CNAME of its own is kept: it is a real record behind the same CDN or load balancer. A brute-forced name never gets that exception.
  • Names added after puredns go through the same check: certificate SANs, tlsx, JS Recon and Uncover. tlsx links no Subdomain to a certificate name the check dropped.
  • The zone node records the answer: is_wildcard_zone and wildcard_ips on the Domain, or on the Subdomain of a deeper zone.
  • Limits: at most 50 zones per run, lookups paced to the RoE rate ceiling, never a zone the RoE excludes. A lookup that fails drops nothing; that, and the zone cap, are a wildcard_control line in Coverage Limitations.

With DNS Resolution off the control cannot run: discovered names are stored with status unverified (never counted as resolved), and Coverage Limitations says the names were not checked for wildcard DNS unless puredns checked them.

If a specific subdomainList is configured, the pipeline skips active discovery and only resolves those subdomains (WHOIS + URLScan still run in parallel). In IP mode, this group is replaced by reverse DNS lookups and IP WHOIS — see above.

Shodan enrichment (runs in GROUP 3 alongside port scan):

  • Host Lookup — OS, ISP, organization, geolocation, and known vulnerabilities per IP
  • Reverse DNS — discover hostnames missed by standard enumeration
  • Domain DNS — subdomain enumeration via Shodan's DNS records (paid plan required)
  • Passive CVEs — extract known CVEs from host data without active scanning

Passive CVEs are checked against the port scan, and pruned. Shodan's data comes from its own scans, sometimes weeks old. Each Shodan CVE records port_confirmed: true when this run's port scan found its port open, false when the scan looked at that IP and port and did not find it open, and no value when the scan did not look (a port outside the scanned list, a top-100/1000 list, no port scan, a UDP service). A CVE whose port was found closed moves to the Priority Board's resolved section. No extra traffic is sent: the check reads the port scan's own results. A partial Shodan run has no port scan, so it can only confirm a port that an earlier scan found open.

Like every scanner's findings, passive CVEs (Shodan, InternetDB, Netlas, CriminalIP) are now removed at the end of a full scan when the provider no longer reports them, for example after DNS stopped pointing at the IP. Muted and human-judged ones are kept and marked resolved. A provider you switched off, or one without an API key, is removed the same way. A lookup that could not ask about some IPs keeps those IPs' CVEs; one that could ask about nothing (a refused key, an error) keeps all of its CVEs, and the run's coverage notes say so.

No passive CVE on a shared edge. Shodan's CVEs are written after IP Attribution, and none on an IP it tagged shared edge: a CDN edge's CVEs describe the provider and its other tenants. An earlier scan's CVE on such an IP is removed at the end of the scan. Shodan's reverse-DNS and domain-DNS answers still add Subdomain nodes, but the link they create carries source: 'shodan_rdns' or 'shodan_dns' and is not read as the name's current address.

URLScan.io enrichment (runs in GROUP 1 alongside discovery):

  • Queries historical scan data from URLScan.io's Search API
  • Discovers subdomains, IP addresses, URL paths, TLS metadata, server technologies, and domain age
  • Collects external domains encountered in historical scans for situational awareness
  • Works without API key (public results) or with key (higher rate limits)

ExternalDomain nodes: Throughout the pipeline, multiple modules collect out-of-scope domains (URLScan historical data, HTTP probe redirects, Katana/GAU crawling). At the end of the pipeline, these are aggregated, deduplicated, and stored as ExternalDomain nodes linked to the root Domain.

Both modules are independently toggleable in the Discovery & OSINT tab of project settings. If URLScan enrichment runs, the urlscan provider is automatically removed from GAU to avoid duplicate data.


GROUP 2b: Uncover Target Expansion (before port scan)

Purpose: Expand the target surface by querying up to 13 search engines via ProjectDiscovery's uncover tool. Runs before Shodan and port scanning, so a new subdomain it finds is scanned like any other. A bare IP is recorded, not scanned (see below).

How it works:

  1. Builds a provider-config.yaml with only engines that have valid API keys
  2. Runs the projectdiscovery/uncover Docker container with domain-based and SSL cert queries
  3. Deduplicates results by (IP, port), handles engine quirks (Google URL-in-IP, PublicWWW host-only)
  4. Filters non-routable and CDN IPs via ip_filter.py
  5. Merges discovered subdomains into dns.subdomains, through the same scope gates as every other discovered name

Bare IPs are recorded, never scanned. Uncover writes every IP it keeps to the graph as an IP node, with Port nodes for the ports the engine reported, in a full scan and in partial Uncover alike. No port scan or OSINT enricher ever runs on them: those read metadata.expanded_ips only in IP mode, and Uncover does not run in IP mode. In domain mode the IPs go into metadata.expanded_ips only when the group's scan root is its registrable domain. There the key widens the scope of JS Recon's endpoint probe and first-party check, of the graph writers and of the external-domain filter. So JS Recon may probe a URL on such an IP when a script names one. A group whose scan root is deeper (api.example.com) does not take the org-wide addresses into its scope, and a group that lists its hosts exactly keeps none of Uncover's names or IPs.

Engines (only those with configured keys are used):

Engine Key Source Notes
Shodan Reuses existing Shodan key Search-based discovery (different from direct host lookup)
Censys Reuses existing Censys token Platform API v3
FOFA Reuses existing FOFA key
ZoomEye Reuses existing ZoomEye key
Netlas Reuses existing Netlas key
CriminalIP Reuses existing CriminalIP key
Quake Uncover-specific key 360 Quake cyberspace search
Hunter Uncover-specific key Qianxin Hunter
PublicWWW Uncover-specific key Source code search engine
HunterHow Uncover-specific key hunter.how internet search
Google Uncover-specific key + CX Google Custom Search JSON API
Onyphe Uncover-specific key Cyber defense search engine
Driftnet Uncover-specific key Port and service discovery

No extra keys needed if you already have Shodan, Censys, FOFA, etc. configured -- uncover reuses them automatically. The 7 uncover-specific engines are optional extras for broader coverage.

IP filtering: Non-routable IPs (RFC 1918, CGNAT, loopback) and CDN IPs are automatically filtered before results enter the pipeline. This prevents wasting API credits on downstream enrichment of unusable addresses.

Output: Subdomain, IP, Port, and Endpoint nodes in the graph. Discovered hosts are injected into the pipeline so GROUP 3+ modules process them.


GROUP 3: Shodan + Port Scanning (parallel)

Purpose: Discover open ports and enrich IPs with Shodan intelligence. Both tasks run concurrently.

Port Scan (Naabu) capabilities:

  • SYN scanning (default) with CONNECT fallback
  • Top-N port selection (100, 1000, or custom ranges)
  • CDN/WAF detection (Cloudflare, Akamai, AWS CloudFront)
  • Passive mode via Shodan InternetDB (no packets sent)
  • IANA service name mapping (15,000+ entries)

Output: Port nodes linked to IP nodes. Enriched IP nodes from Shodan (OS, ISP, geolocation, passive CVEs).


GROUP 3b: Threat Intelligence Enrichment (parallel with GROUP 3)

Purpose: Passively enrich discovered IPs and domains with threat intelligence from seven specialized OSINT platforms. All seven tools run concurrently via ThreadPoolExecutor(max_workers=5). This group runs in parallel with GROUP 3 (port scanning) — neither blocks the other.

Tools (all concurrent):

Tool Source Input Key Intelligence
Censys Censys Search API v2 IPs Open ports, services, TLS certificate chains, geolocation, ASN, OS fingerprint
FOFA FOFA Search API Domain/IPs IP:port pairs, HTTP titles, server headers, geolocation, certificate info, protocol details
OTX (AlienVault) OTX Indicators API v1 IPs, Domains Threat reputation, malware families, MITRE ATT&CK IDs, passive DNS history, pulse data
Netlas Netlas Responses API Domain/IPs Ports, HTTP metadata, geolocation (lat/lon, timezone), TLS certs, DNS records, WHOIS
VirusTotal VirusTotal API v3 Domains, IPs Reputation score, AV analysis stats, categories, tags, JARM fingerprint
ZoomEye ZoomEye API Domain/IPs Ports, service banners, device/OS, web app fingerprints, geolocation, ASN, SSL info
CriminalIP Criminal IP API v1 IPs Risk score, threat tags (VPN/Tor/proxy/C2/scanner), geo, ISP, abuse history

OTX is enabled by default — it supports anonymous requests (1,000 req/hr) without an API key. All other tools require an API key configured in Global Settings > API Keys.

Rate limiting: Each tool detects HTTP 429 responses and stops further queries for that scan. VirusTotal free-tier users are limited to 4 requests/minute; the pipeline automatically waits 65 seconds and retries on rate limit. CriminalIP retries after 2 seconds.

Key rotation: FOFA, OTX, Netlas, VirusTotal, ZoomEye, and CriminalIP support automatic round-robin key rotation. Configure additional keys in Global Settings to multiply effective rate limits.

Output: Threat intelligence properties added to existing IP and Domain nodes in Neo4j. Data from each tool is stored as properties on the relevant node (no new node types). Results are also included in the recon_domain.json output file under per-tool keys.

Netlas and CriminalIP CVEs are one finding per CVE and IP (Netlas: per IP and port), linked to the IP and to the CVE node. Netlas's domain search returns its whole history for the name: a row for an IP the domain no longer resolves to is kept in recon_domain.json as attribution: historical and is not written to the graph, and a CDN or shared-edge IP (including one IP Attribution tagged shared edge; the Netlas graph write waits for that step) gets its ports but no CVE. A port a passive provider reports never takes over a port the port scan found (Port.source is set by the first tool only).


GROUP 3.5: Nmap Service Detection (after port scan merge)

Purpose: Deep service version detection and NSE vulnerability script scanning on all discovered open ports. Runs after port_scan merge (Masscan + Naabu results combined) so it only probes ports already confirmed as open.

Capabilities:

  • Service version detection (-sV) -- identifies product name, version, and CPE for services running on open ports (e.g. vsftpd 2.3.4, Apache Tomcat/8.5.19)
  • NSE vulnerability scripts (--script vuln) -- runs Nmap Scripting Engine vulnerability checks against discovered services, extracting CVE IDs from script output
  • Configurable timing -- T1 (Sneaky) through T5 (Insane), with per-host and total timeout controls
  • Stealth mode -- automatically reduces timing to T2 (Polite) and disables NSE scripts

Graph enrichment:

  • Port nodes enriched with product, version, cpe, nmap_scanned flag
  • Technology nodes created from detected services ((Service)-[:USES_TECHNOLOGY]->(Technology), (Port)-[:HAS_TECHNOLOGY]->(Technology))
  • Vulnerability nodes created from NSE findings ((Vulnerability)-[:AFFECTS]->(Port), (Vulnerability)-[:FOUND_ON]->(Technology))
  • CVE nodes created from NSE-detected CVEs ((Vulnerability)-[:HAS_CVE]->(CVE), (Technology)-[:HAS_KNOWN_CVE]->(CVE))

Output: Enriched Port and Service nodes, new Technology/Vulnerability/CVE nodes from Nmap. Detected service versions also feed into the CVE lookup pipeline (GROUP 6) for NVD/Vulners enrichment.

Only runs when NMAP_ENABLED is true and port scan results contain discovered ports. Configure in the Nmap Service Detection tab of project settings.


GROUP 4: HTTP Probing & Technology Detection

Purpose: Determine which services are live and what software they run.

httpx probing:

  • Status codes, content types, page titles, server headers
  • TLS certificate inspection (subject, issuer, expiry, ciphers, JARM)
  • Response times, word counts, line counts

Technology detection (dual engine):

  • httpx built-in fingerprinting for major frameworks
  • Wappalyzer second pass (6,000+ fingerprints) for CMS plugins, JS libraries, analytics tools

Banner grabbing:

  • Raw socket connections for non-HTTP services (SSH, FTP, SMTP, MySQL, Redis)
  • Protocol-specific probe strings for version extraction

Output: BaseURL, Service, Technology, Certificate, Header nodes.


IP Attribution (after GROUP 4)

Purpose: Tag every IP of the scan once, so the modules that ask "is this IP the target's?" read one answer instead of guessing on their own. Runs right after HTTP probing (and the certificate SAN feedback), in both domain and IP mode, before GROUP 5 and GROUP 6.

Tag Meaning
Shared edge A CDN edge serving many companies: the IP is in a CDN's published edge range, a scanner's CDN check named an edge-only CDN (naabu, httpx or tlsx), the HTTP responses carry headers only an edge sets, or its ASN belongs to an edge-only CDN and its default certificate is not the target's. A cloud label (AWS, Google, Azure) is never enough
Dedicated The certificate the IP presents to a client that sends no SNI covers one of the target's domains
Unknown Neither could be shown. The step never says an IP is "not the target's": a real server on a cloud provider has a generic reverse-DNS name and the cloud's whois

The only traffic is one TLS handshake without SNI to port 443 of each IP where 443 was found open. It skips hosts the Rules of Engagement exclude, loopback and link-local addresses and hosts marked unreachable, is paced at the engagement rate ceiling, and is capped per scan by Max TLS handshakes per scan (default 500). Stealth mode sets that cap to 0: the tag then uses only the CDN signals already collected, and its reasons say the certificate was not checked. A handshake that fails is never evidence either way. The step never stops the scan; an IP it could not attribute is tagged unknown with the reason.

Who reads the tag:

  • VHost & SNI skips its default wordlist on a shared edge.
  • Origin discovery never reports a shared edge as an origin.
  • Shodan and Netlas write no CVE finding on a shared edge. Both writes now wait for this step: Shodan's ports and names are still written in GROUP 3, its CVEs after the tag; the whole Netlas write moves here.
  • The Priority Board caps the reach of findings on a shared edge, and of passive CVEs on an IP no current DNS name points at.

Output: ownership, ownership_reasons, default_cert_names and current_dns_names on each existing IP node (none is created). Switch it off with IP Attribution in the HTTP Probing tab; it can also be re-run on its own as a partial recon.


GROUP 5: Resource Enumeration (internally parallel + sequential)

Purpose: Discover every reachable endpoint and hidden parameter. Four tools run simultaneously, then jsluice, FFuf, ZAP Ajax Spider, and Arjun run sequentially.

Tool Type Description
Katana Active Web crawler following links to configurable depth, optionally with JavaScript rendering
Hakrawler Active DOM-aware web crawler via Docker, discovers links and forms
GAU Passive Queries Wayback Machine, Common Crawl, AlienVault OTX, URLScan.io for historical URLs
Kiterunner Active API brute-forcer testing REST/GraphQL route wordlists
OpenAPI Active Imports the endpoints declared in OpenAPI/Swagger documents; never calls a declared operation
jsluice Active JavaScript analysis — downloads and extracts URLs, endpoints, and embedded secrets (AWS keys, API tokens, etc.) from .js files discovered by Katana/Hakrawler
FFuf Active Directory/endpoint fuzzing using wordlists (SecLists + custom uploads) to discover hidden content
ZAP Ajax Spider Active Browser-driven crawling via OWASP ZAP — runs headless Firefox to execute JavaScript and capture XHR/fetch endpoints, SPA route changes, cascade-revealed routes, and post-auth surface invisible to static crawlers. Off by default; auto-disabled in stealth mode
Arjun Active / Passive Hidden HTTP parameter discovery — tests ~25,000 parameter names against discovered endpoints. Multiple methods (GET/POST/JSON/XML) run in parallel

Katana, Hakrawler, GAU, and Kiterunner run in parallel. Once crawling completes, jsluice analyzes the discovered JavaScript files sequentially, FFuf brute-forces directory paths using wordlists, ZAP Ajax Spider drives a real browser through the discovered endpoints to capture JS-only XHRs and SPA routes (its own per-seed Docker containers run in parallel up to Parallelism), then Arjun discovers hidden parameters on the discovered endpoints (with selected methods running in parallel).

Results are merged, deduplicated, and classified:

  • Categories: auth, file_access, api, dynamic, static, admin
  • Parameter typing: id, file, search, auth_param

Output: Endpoint, Parameter, and Secret nodes linked to BaseURL nodes.


GROUP 5b: JS Reconnaissance (after resource enumeration)

Purpose: Deep JavaScript analysis to extract secrets, endpoints, dependency confusion risks, source map exposures, DOM XSS sinks, and framework fingerprints from client-side code. Runs whenever JS_RECON_ENABLED is true, independently of resource enumeration. When resource_enum is active, JS Recon analyzes its discovered JS files; when resource_enum is disabled, JS Recon analyzes manually uploaded files only.

How it works:

  1. Collects all JS URLs discovered by Katana, Hakrawler, ZAP Ajax Spider, GAU, and jsluice in GROUP 5
  2. Downloads up to 500 JS files concurrently (10 threads), skipping third-party libraries
  3. Merges with any manually uploaded JS files
  4. Runs six analysis modules in parallel (4-worker thread pool):
Module What It Finds
Pattern Scanning 90+ secret patterns -- cloud credentials, payment keys, auth tokens, infrastructure URLs, info leaks
Secret Validation Live validation of 21 secret types against their APIs (GitHub, Stripe, Slack, AWS, etc.)
Source Map Discovery Exposed .map files via comment parsing, HTTP headers, and path probing
Dependency Confusion Scoped npm packages not registered on public npm -- attacker could register them
Endpoint Extraction REST APIs, GraphQL, WebSocket, router definitions, admin/debug paths, API documentation
Framework & Security Framework detection (12 built-in), DOM XSS sinks (15 patterns), dev comments with sensitive keywords
  1. Extracts new in-scope subdomains from discovered endpoints and feeds them back into the pipeline
  2. Updates Neo4j graph in a background thread

Subdomain feedback loop: JS Recon discovers subdomains embedded in JavaScript code (API base URLs, CDN references, cloud asset URLs) and merges them back into the pipeline's subdomain list. These new subdomains become available for downstream processing.

Output: Secret, Endpoint, and JsReconFinding nodes linked to BaseURL nodes. New subdomains merged into the pipeline.

Full details: See JS Reconnaissance for module details, output structure, API endpoints, and frontend components.


GROUP 5.5: Supply-Chain Recon (after JS Recon)

Purpose: Black-box detection of known-malicious (MAL-) and known-vulnerable (CVE / GHSA) dependencies the live target actually serves. Runs whenever supplyChainReconEnabled is true, in domain and IP projects alike, immediately after JS Recon (whose downloaded JS and detected technologies it reuses), and even when the active scans are skipped. Off by default.

How it works: it harvests npm package names and versions from JS Recon's source maps, the http_probe technologies, and a retire.js pass; synthesizes a CycloneDX SBOM; and verdicts it offline against the local OSV database (zero egress, no new fetch to the target). Version-bearing packages are verdicted; names harvested without a version are recorded as inventory but flagged unverdictable. An optional GuardDog deep-analysis pass adds suspicious behavioural findings on the OSV-flagged packages.

Output: Package and MalPackageFinding nodes plus Vulnerability{source='osv'}, anchored to the target's BaseURL nodes via DEPENDS_ON. Read them in the Supply-Chain SCA table. Needs the offline OSV database populated once (./redamon.sh supply-chain-sync npm).

Full details: See Supply-Chain Scanning for the three layers, the tools (OSV-Scanner, GuardDog, retire.js), and the standalone Other-Scans variant.


GROUP 5c: AI Surface Recon (after resource enumeration)

Purpose: Confirm and characterize AI/LLM/MCP/vector-DB infrastructure that generic web recon can't see. Runs as Phase 4.5 whenever AI_SURFACE_RECON_ENABLED is true (gated on its own toggle, not SCAN_MODULES), after resource enumeration. It is black-box and benign — it sends a 1-token chat "ping", a standard MCP initialize, OpenAPI GETs, declarative fingerprint probes, and vector-DB health reads. It never jailbreaks, injects, fuzzes, or presents credentials, and treats a 401 as a positive signal.

How it works:

  1. Gathers candidate hosts (crawled AI endpoints + http_probe AI flags + AI/vector-DB ports), drops RoE-excluded hosts
  2. Fans candidates across a thread pool (hosts in parallel, workloads sequential per host); runs seven workloads:
# Workload Confirms / extracts
1 Chat-shape probe + latency LLM chat endpoint, dialect, streaming, p50 latency
2 MCP handshake + tools/list + YARA MCP server, tools, capabilities, tool-poisoning findings
3 OpenAPI / manifest / model listing tool/vision/streaming support, model ids + family, cached spec
4 Julius probe pack (YAML) confirmed AI Technology (vLLM, Ollama, …)
5 Vector-DB confirmation reads qdrant / chroma / weaviate / milvus, unauthenticated read exposure
6 / 7 latency baseline + summary glue counters, merged model family
  1. Updates the Neo4j graph in a background thread (annotates Endpoint/Parameter/Technology, adds MCP tool-poisoning Vulnerability nodes)

Output: combined_result["ai_surface_recon"]; graph enrichment via update_graph_from_ai_surface_recon.

Full details: See Adversarial AI Recon.


GROUP 6 Phase A: Nuclei + GraphQL Security + Subdomain Takeover + VHost & SNI + Web Cache Poisoning (parallel)

Purpose: Test discovered endpoints for security vulnerabilities and uncover hidden infrastructure. All five scanners read from the same combined_result dict (each pulls a different slice - BaseURL/Endpoint/Technology for Nuclei + GraphQL + Web Cache Poisoning, Subdomain/DNS/alive URLs for Takeover, IP/Port/SAN list for VHost & SNI) and write Vulnerability nodes, but have zero data dependency on each other - so they run concurrently via ThreadPoolExecutor using _isolated wrappers that deep-copy the shared result dict to avoid race conditions. Wall-time is dominated by Nuclei (5-30 min) and Web Cache Poisoning (WCVS is thorough and slow - hundreds of requests/URL, 1800 s default budget); the other three complete within minutes (Takeover) or seconds (VHost & SNI).

Nuclei capabilities:

  • 9,000+ community templates for known CVEs, misconfigurations, exposed panels
  • DAST mode — active fuzzing with XSS, SQLi, RCE, LFI, SSRF, SSTI payloads
  • Severity filtering — scan for critical, high, medium, and/or low findings
  • Interactsh — out-of-band detection for blind vulnerabilities
  • CVE enrichment — cross-references findings against NVD for CVSS scores

30+ custom security checks (configurable individually):

  • Direct IP access, missing security headers (CSP, HSTS, etc.)
  • TLS certificate expiry, DNS security (SPF, DMARC, DNSSEC, zone transfer)
  • Open services (Redis no-auth, Kubernetes API, SMTP open relay)
  • Insecure form actions, missing rate limiting

GraphQL security scanner capabilities:

  • Endpoint auto-discovery — merges user-specified endpoints with candidates from HTTP probe, resource enumeration, JS Recon, and pattern probing (/graphql, /api/graphql, /v1/graphql, /v2/graphql as primary patterns; /query, /gql, /graphiql, /playground as secondary patterns only on bases with existing GraphQL evidence)
  • Introspection test — probes each endpoint for exposed __schema/__type, extracts the full schema at a configurable TypeRef recursion depth (1-20), counts queries/mutations/subscriptions, and computes a schema hash for change detection
  • Sensitive-field detection — flags schema fields matching password, token, secret, key, api, private, credential, auth, ssn, credit, card, cvv, salary, medical, etc.
  • graphql-cop (opt-in Docker-in-Docker) — runs dolevf/graphql-cop:1.14 for 12 additional checks: alias overloading, batch query DoS, directive overloading, circular introspection DoS, GraphiQL/Playground detection, trace mode, GET-based queries/mutations, POST url-encoded CSRF, field suggestions, unhandled error leakage
  • 5 authentication modes — Bearer, Cookie, custom header, Basic (base64), API key
  • Rate limiting + retries — global RPS cap (0-100), retry with exponential backoff on 429/5xx, configurable concurrency (1-20)
  • RoE enforcement — out-of-scope endpoints (wildcards supported) are skipped and counted in endpoints_skipped
  • Endpoint capability flags — booleans like graphql_graphiql_exposed, graphql_tracing_enabled, graphql_get_allowed, graphql_batching_enabled are persisted on the Endpoint node even for negative results

Web Cache Poisoning scanner capabilities:

  • Two-engine detection - the third-party WCVS (Hackmanit, Docker-in-Docker) sweeps 10+ technique classes for breadth ("find suspects"), then a RedAmon-native 5-phase confirmation engine re-proves every suspect with a safe baseline→poison→clean→persistence sequence ("prove it")
  • Cache oracle - confirms a URL is actually served through a cache via X-Cache/CF-Cache-Status/Age/Via headers, with a behavioural fallback (frozen-Date probe) for silent caches that emit no cache headers; non-cacheable URLs are skipped
  • Isolated, benign testing - every test mints a unique cache-buster so it lands in its own slot and never poisons the real page; payloads are non-resolving .invalid canaries, never live XSS or real domains
  • Native hypotheses - generic unkeyed-header families (X-Forwarded-Host, X-Forwarded-Proto, X-Forwarded-For, URL-override, …) plus fingerprint-gated framework packs for Next.js / Nuxt / Remix
  • Reflected + non-reflective detection - confirms both an echoed canary and a persisted behavioural change (status flip, Location redirect, body diff), the latter guarded against false positives by requiring stability across two clean baselines
  • Confidence scoring - findings are tiered Confirmed / Strong / Tentative / Rejected; only those at or above the Min confidence gate (default 0.8) become Vulnerability {source:'cache_poisoning'} nodes

Output: Vulnerability and CVE nodes linked to Endpoints and Parameters. GraphQL adds: introspection findings (with sensitive field lists), graphql-cop misconfiguration findings, and capability flags on the Endpoint nodes. Web Cache Poisoning adds: scored cache_poisoning Vulnerability nodes carrying the unkeyed vector, cache signals, impact, and a clickable PoC link + curl verification command.

Stealth mode overrides (GraphQL): rate limit forced to 2/s, concurrency to 1 (sequential), timeout to 60s, and the four DoS-class graphql-cop tests (alias overloading, batch query, directive overloading, circular introspection) are forced off.

Stealth mode (Web Cache Poisoning): the module is disabled entirely - active poisoning probes are loud and high-volume, incompatible with stealth. CPDoS stays force-off regardless.


GROUP 6 Phase B: MITRE Enrichment

MITRE Enrichment (runs automatically after Phase A completes — depends on Nuclei CVEs):

  • Maps every CVE to its corresponding CWE weakness and CAPEC attack patterns
  • Uses the CVE2CAPEC repository (auto-updated with 24-hour cache TTL)
  • Provides attack pattern classification for every vulnerability found

Additional MITRE output: MitreData (CWE) and Capec nodes linked to CVE nodes.


Domain batch: scanning many domains in one run

A project set to Domain batch targets a list of hostnames spanning several domains instead of a single target. RedAmon groups the list by domain and scans the groups one after another.

How the list is grouped

A hostname belongs to its registrable domain, read from the Public Suffix List. So suba.sub3.domain3.com belongs to domain3.com, and foo.example.co.uk to example.co.uk (not co.uk).

You paste Group Scan root Hosts
sub1.domain1.com 1 domain1.com sub1.domain1.com
sub2.domain2.it 2 domain2.it sub2.domain2.it
sub3.domain3.com 3 domain3.com sub3.domain3.com, suba.sub3.domain3.com
suba.sub3.domain3.com

Each group (a scope group) is one pass of the pipeline over its scan root. A group of listed hostnames scans exactly those hosts; a wildcard enumerates under its own name, at any depth: *.example.com enumerates example.com, *.api.example.com only api.example.com (its registrable domain is still example.com). A wildcard under another one is covered by it. The project form shows the computed groups, and any line it refuses with the reason, before you save. See Creating a Project - Domain batch for what is refused.

At the start of the run the recon log prints the suffix list's version ([*][PSL]) and one [*][Scope] line per group. A group whose scan root recon's own suffix list calls a public suffix is dropped, and a batch with no usable group refuses to start rather than scanning nothing.

What happens when you run it

  • It is one scan, not many. The batch takes a single row in the Scan queue, one memory reservation and one container. Stop it and the whole batch stops.
  • The graph fills in as it goes. The previous recon data is cleared once, at the start. Each group then finishes its whole pipeline and writes to the graph before the next one begins, so every group accumulates into one graph.
  • You get one new version covering all the domains, exactly as a single-domain scan produces one version. Run it again for a second version.
  • Only your hostnames are scanned. Subdomain discovery runs only for a wildcard group. A listed group never scans a sibling that a certificate, a JavaScript file or uncover reveals, and a scan root is scanned itself only when it is a target (listed, or Root ticked on its wildcard row).
  • Domain-level checks run once per registrable domain. WHOIS, the DNS email checks (SPF, DMARC, DNSSEC) and the threat-intel domain reports (Shodan DNS, OTX, VirusTotal, Criminal IP, FOFA) are asked once per scan for each registrable domain, by its first group that passed the Rules of Engagement and ownership; its other groups reuse the answer (answered earlier this run, reused in the log). Origin-IP discovery searches the registrable domain only when it is itself in scope, otherwise just the scan root.
  • One Domain node per registrable domain. Hosts of *.api.example.com and www.example.com both hang off Domain(example.com); a deeper scan root that is a target is a Subdomain marked is_scan_root. The run's coverage record sits on that Domain, merged across its groups.
  • A DNS outage does not end the batch. If the DNS resolver stops answering during one domain, its remaining lookups are skipped (the log says Resolver appears down), and the next domain checks the resolver again: Resolver answering again: lookups resumed, or Resolver still down: skipping this group's lookups. Every host that could not be looked up keeps its earlier findings and is listed in the scan's coverage limitations, and a name taken from a certificate is not added as a target while it cannot be checked. A partial recon over several root domains does the same for each root.
  • A failing domain does not stop the rest. Failures are listed at the end.

The recon drawer shows Group 2/3 alongside the usual phase progress, since the six phases restart for each group.

Limits

500 hostnames and 50 domains per project. Remember that a batch holds the project's single scan slot until every group is done, so a long list is a long scan.


Scan Duration Estimates

Duration varies based on target size, network conditions, and scan settings:

Target Type Approximate Duration
Small (1-5 subdomains, few ports) 5-15 minutes
Medium (10-50 subdomains) 15-45 minutes
Large (100+ subdomains) 1-3 hours
IP mode (single IP) 5-10 minutes
IP mode (CIDR /24 = 254 hosts) 30-90 minutes

Key factors affecting duration:

  • Bruteforce for subdomains adds significant time for large domains
  • Katana depth > 2 increases crawling time exponentially
  • DAST mode doubles vulnerability scanning time
  • GAU with verification adds 30-60 seconds per domain

After Reconnaissance

Once the scan is complete, you can:

  1. Explore the graph — click nodes to inspect their properties, filter by type using the bottom bar
  2. Switch to Data Table — view all findings in a searchable, sortable table with Excel export
  3. Run GVM scan — complement web-layer findings with network-level vulnerability testing (see GVM Vulnerability Scanning)
  4. Run GitHub Hunt — search for leaked secrets (see GitHub Secret Hunting)
  5. Run the Secret Multiscanner - scan repositories, registries, buckets and CI systems with 1060 secret detectors and live API verification (see Secret Multiscanner)
  6. Use the AI Agent — ask the agent to analyze findings, identify attack paths, and exploit vulnerabilities (see AI Agent Guide)
  7. Compare scans over time — with Scan Timeline, diff this scan against a previous version (Recon Delta) to see new ports, new CVEs, and resolved findings, or schedule scans to run automatically

Next Steps

Home


Getting Started

Core Workflow

Scanning & OSINT

AI & Automation

Plugins

HackLab

Analysis & Reporting

Contributing

Reference & Help

Clone this wiki locally