THREAT-Recon-CloudAssetShadowITDiscovery CrowdStrike LogScale · LogScale

Detect Cloud Asset & Shadow IT Discovery via Internet-Wide Scanning Services in CrowdStrike LogScale

Adversaries performing Search Open Technical Databases (T1596) rarely scan a target's network directly — instead they query commercial internet-wide scan-database services such as Shodan, Censys, BinaryEdge, ZoomEye, and ONYPHE, which continuously crawl the entire public IPv4/IPv6 space and index open ports, service banners, TLS certificates, and known CVEs for every internet-facing host. This lets an adversary map an organization's external attack surface — including forgotten dev/staging environments, misconfigured cloud storage endpoints, unmanaged VMs, and other 'shadow IT' the security team never inventoried — without sending a single packet the target can attribute to them. Because the adversary's actual query happens against the third-party database and is invisible to the defender, the only observable telemetry is the re-indexing traffic these scanning services' own crawler infrastructure generates as they continuously re-scan the internet to keep their databases current. This detection treats that crawler traffic as an early-warning signal: it flags (1) perimeter traffic from known scanning-service IP ranges probing many distinct ports on a single asset (the banner-grab pattern used to populate these databases), and, more importantly, (2) scanning-service traffic that reaches a destination IP absent from the organization's own asset inventory — meaning a commercial scan database has just indexed infrastructure the defender did not know was internet-facing. That second signal is functionally identical to what an adversary running T1596 would discover, giving defenders a chance to find and remediate the shadow IT asset before it is weaponized under T1190 (Exploit Public-Facing Application).

MITRE ATT&CK

Tactic
Reconnaissance

LogScale Detection Query

CrowdStrike LogScale (LogScale)
cql
// Alert 1: Inbound connections from known internet-wide scanning service ranges touching 5+ distinct local ports on a Falcon-monitored perimeter/DMZ host
#event_simpleName=NetworkConnectIP4
| ConnectionDirection=Inbound
| RemoteAddressIP4=/^(198\.20\.(69|70|71)\.|167\.94\.(138|145|146)\.|162\.142\.125\.|199\.45\.15[24]\.|195\.154\.108\.|71\.6\.135\.|64\.62\.202\.)/
| stats count(as=HitCount), distinct_count(field="LocalPort", as=DistinctPorts), earliest(ConnectionStartTime, as=FirstSeen), latest(ConnectionStartTime, as=LastSeen) by ComputerName, RemoteAddressIP4
| DistinctPorts>=5
| table([ComputerName, RemoteAddressIP4, DistinctPorts, HitCount, FirstSeen, LastSeen])
| sort(LastSeen, order=desc)

// Alert 2: run as a separate scheduled search — same scanner ranges reaching a LocalAddressIP4 not present in the KnownAssets watchlist
#event_simpleName=NetworkConnectIP4
| ConnectionDirection=Inbound
| RemoteAddressIP4=/^(198\.20\.69\.|167\.94\.138\.|162\.142\.125\.|195\.154\.108\.)/
| !in(field="LocalAddressIP4", values=$KnownAssetsWatchlist)
| stats count(as=HitCount), distinct_count(field="RemoteAddressIP4", as=DistinctSourceScanners) by LocalAddressIP4
medium severity medium confidence

Two CrowdStrike CQL queries against ProcessRollup2-adjacent network telemetry (NetworkConnectIP4), applicable to Falcon-monitored internet-facing hosts. The first matches inbound connections from known internet-wide scanning-service ranges touching 5 or more distinct local ports on a single host. The second filters the same scanner ranges for connections reaching a LocalAddressIP4 not present in an imported KnownAssetsWatchlist, surfacing unmanaged/shadow hosts running the Falcon sensor.

Data Sources

CrowdStrike Falcon NetworkConnectIP4 eventsFalcon Data Replicator (FDR) network telemetry

Required Tables

NetworkConnectIP4

False Positives & Tuning

  • Authorized red team or third-party pentest infrastructure overlapping with commercial internet-scanning IP ranges
  • Uptime/monitoring SaaS providers probing multiple ports for health checks from ranges not yet allowlisted
  • Newly provisioned intentionally public-facing Falcon-monitored hosts not yet added to KnownAssetsWatchlist

Other platforms for THREAT-Recon-CloudAssetShadowITDiscovery


Testing Methodology

Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1Linux — Multi-Port TCP Connect Sweep Simulating Scanner Breadth Probe

    Expected signal: Perimeter firewall/NSG flow log entries (CommonSecurityLog or CEF equivalent) recording 15-20 distinct DestinationPort values from the test source IP to <TARGET_IP> within a short window, with an allow or deny verdict per port.

  2. Test 2Linux — HTTP Request Using Known Scan-Database Crawler User-Agent

    Expected signal: Web/application server access log entry for <TEST_WEB_HOST> recording the User-Agent string 'CensysInspect/1.1 (+https://about.censys.io/)' against the source IP that issued the request.

  3. Test 3Linux — Scanner Traffic Reaching an Asset Absent From the KnownAssets Watchlist

    Expected signal: Perimeter firewall/flow log entries for the test source IP reaching <SHADOW_TEST_IP> on the probed ports, with no corresponding entry for <SHADOW_TEST_IP> in the KnownAssets watchlist or known_assets.csv lookup.


Response Playbook

Triage

  1. Confirm whether the source IP(s) genuinely belong to a known internet-wide scanning service (Shodan, Censys, BinaryEdge, Rapid7 Project Sonar, ZoomEye, ONYPHE) by checking the vendor's published scanning-range documentation or a threat-intel/GreyNoise lookup — distinguish an attributed benign scanner from unattributed or adversary-controlled infrastructure reusing similar ranges.
  2. For ScannerBreadthProbe alerts, review the full set of destination ports probed on the target asset — a broad sweep across common service ports (22, 3389, 443, 8080, 9200, 27017, etc.) indicates automated banner-grabbing consistent with a re-indexing crawl rather than a targeted human operator.
  3. For ShadowAssetDiscoveredByScanner alerts, treat the finding as primary regardless of adversary intent: query the same scan database (Shodan.io / Censys.io) directly for the flagged destination IP to see exactly what banner/service information is now publicly indexed — this is the same view an adversary running T1596 would have.
  4. Cross-reference the flagged destination IP against your cloud provider's resource inventory (AWS/Azure/GCP tag search by public IP) and CMDB/asset management system to identify the owning team, workload, and whether it was provisioned outside standard change management.
  5. Determine what service is actually listening on the exposed port(s) from an authorized internal vantage point, or read the scan database's own banner data, to assess whether it is an unpatched/default-credentialed service, a forgotten dev/staging environment, or an intentionally public asset simply missing from the watchlist.

Containment

  1. If the discovered asset is unauthorized/unmanaged shadow IT: engage the owning team (identified via cloud tagging/cost-allocation) to either formally onboard it into asset management and firewall/WAF policy, or decommission it if it serves no current business purpose.
  2. If the exposed service should never be internet-facing (a database, RDP, or admin panel discovered by the scan), immediately restrict it at the security group/NSG/firewall level to remove public exposure while the owning team is engaged.
  3. Submit a de-listing/opt-out request to the relevant scanning service where supported (Shodan and Censys both offer opt-out/exclusion mechanisms for verified asset owners) in addition to closing the exposure itself.
  4. Add the confirmed-legitimate asset to the KnownAssets watchlist/lookup used by this detection's second alert so future scanner traffic to it is correctly suppressed, and file a change-management record so the addition is auditable.

Evidence Collection

  1. Export the full set of firewall/perimeter flow log entries (CommonSecurityLog or CEF equivalent) for the source scanner IP and destination asset across the observed window, preserving source IP, destination IP/port, protocol, and allow/deny verdict for every probed port.
  2. Query the originating scan database's public record for the destination IP (Shodan.io/Censys.io search or API lookup) and preserve a timestamped snapshot of the returned banners, open ports, and any vulnerability/CVE tags the service has associated with the host.
  3. Pull the cloud provider's resource metadata for the destination IP (AWS EC2/ELB, Azure Public IP resource, GCP external IP) including creation timestamp, owning subscription/account, and tags, to establish provenance and how long the asset has been internet-facing.
  4. Collect the asset's own service banner/version information from an authorized internal scan or configuration management record, to corroborate or refute what the external scan database is reporting.

Escalation Criteria

  • !The flagged destination asset is confirmed genuinely unknown to the owning organization (not present in CMDB, cloud tagging, or any team's documented inventory) — a confirmed shadow IT / unmanaged attack-surface finding regardless of whether malicious follow-on activity is observed.
  • !The exposed service is a sensitive management or data-plane interface (RDP, SSH with password auth, database ports, Kubernetes API, admin/management consoles) rather than an intentionally public web service.
  • !The scan database's public record shows the asset already carries known CVE/vulnerability tags, indicating both the adversary and the defender are seeing the same exploitable weakness simultaneously.
  • !Multiple previously-unknown destination IPs within the same cloud subscription/account surface in ShadowAssetDiscoveredByScanner alerts within a short window, suggesting a systemic gap in asset registration/change management rather than an isolated one-off asset.

Investigation Guide

Related Techniques

Forensic Artifacts

  • >Firewall/perimeter flow logs (CommonSecurityLog, VPC Flow Logs, NSG Flow Logs) for the scanner source IP and destination asset — retain for the full detection window plus 30 days to support trend analysis of repeat scanning.
  • >Cloud provider public IP resource records (AWS EC2/ELB/NLB, Azure Public IP, GCP external IP) including creation timestamp, owning account/subscription, and associated tags.
  • >Historical Shodan.io / Censys.io / BinaryEdge query results for the destination IP, including first-seen and last-seen indexing dates — these services often expose a change history showing when the asset first appeared in their database.
  • >Web/application server access logs (if the exposed service is HTTP/S) capturing User-Agent strings associated with known scanner crawlers (e.g. CensysInspect/1.1) as corroborating evidence alongside the network-layer alert.
  • >Change management / IaC deployment records (Terraform state, CloudFormation stack events, Azure Resource Manager deployment history) for the destination resource, to establish who provisioned it and when.
  • >KnownAssets watchlist/reference-list version history — confirm what the asset inventory looked like at the time of the alert, to rule out a stale or unsynced inventory as the cause of a false positive.

Tuning Guidance

Scanning-service IP ranges change over time as providers rotate and expand their crawling infrastructure — subscribe to Shodan's and Censys's published scanning-range feeds (or a threat-intel source that classifies benign internet scanners, such as GreyNoise) and refresh the ScannerRanges list on at least a monthly cadence, or the detection will silently lose coverage. The single highest-leverage tuning input is the KnownAssets watchlist/lookup used by the second alert: it must be kept in sync with actual cloud/on-prem public IP inventory (ideally via an automated feed from your CMDB or cloud asset-tagging API) or every newly-provisioned legitimate asset will generate a false ShadowAssetDiscoveredByScanner alert until the watchlist catches up. Raise the DistinctPorts threshold in Alert 1 for environments that also run legitimate broad-port uptime/monitoring services, and consider excluding known-good monitoring-provider ranges alongside the scanner ranges. Periodically run the hunting queries even without an active alert, since scan-database re-indexing cadence varies and an asset may only be re-probed every few weeks — a point-in-time hunt catches drift the near-real-time detection can miss between crawls.


Hunting Queries

Hunt for destination IPs that have been probed by 2 or more distinct known scanning-service ranges within 7 days. Independent indexing by multiple commercial scan databases is a strong indicator the asset is broadly discoverable and should be prioritized for asset-inventory reconciliation and exposure review even if it is not yet flagged as a shadow asset by the primary detection.

Hunting — KQL
kql
// Hunt: destination IPs receiving traffic from 2+ distinct known scanning-service ranges within 7 days — indicates the asset has been independently indexed by multiple public scan databases
let ScannerRanges = dynamic(["198.20.69.0/24", "198.20.70.0/24", "198.20.71.0/24", "167.94.138.0/24", "167.94.145.0/24", "167.94.146.0/24", "162.142.125.0/24", "199.45.152.0/23", "199.45.154.0/23", "195.154.108.0/24"]);
CommonSecurityLog
| where TimeGenerated > ago(7d)
| where ipv4_is_in_any_range(SourceIP, ScannerRanges)
| summarize DistinctScannerSources = dcount(SourceIP), ScannerIPs = make_set(SourceIP, 10), DistinctPorts = dcount(DestinationPort), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by DestinationIP
| where DistinctScannerSources >= 2
| sort by LastSeen desc
Hunting — SPL
spl
index=firewall sourcetype=cef
| eval IsScanner=if(cidrmatch("198.20.69.0/24",src_ip) OR cidrmatch("167.94.138.0/24",src_ip) OR cidrmatch("162.142.125.0/24",src_ip) OR cidrmatch("199.45.152.0/23",src_ip) OR cidrmatch("195.154.108.0/24",src_ip), 1, 0)
| where IsScanner=1
| stats dc(src_ip) as DistinctScannerSources, values(src_ip) as ScannerIPs, dc(dest_port) as DistinctPorts, earliest(_time) as FirstSeen, latest(_time) as LastSeen by dest_ip
| where DistinctScannerSources >= 2
| sort - LastSeen

Hunt for week-over-week changes in the set of ports a known scanner successfully reaches (allowed) on the same asset. A newly-open port that did not appear in the prior week's scanner-visible port set indicates a new service was exposed — useful for catching configuration drift on already-known assets, complementing the primary detection's focus on entirely unknown assets.

Hunting — KQL
kql
// Hunt: destination ports that changed state (newly open) between consecutive scanner probes of the same asset — indicates a new service was exposed on a previously-scanned host
let ScannerRanges = dynamic(["198.20.69.0/24", "167.94.138.0/24", "162.142.125.0/24", "195.154.108.0/24"]);
CommonSecurityLog
| where TimeGenerated > ago(30d)
| where ipv4_is_in_any_range(SourceIP, ScannerRanges) and DeviceAction =~ "allow"
| summarize Ports = make_set(DestinationPort), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by DestinationIP, bin(TimeGenerated, 7d)
| order by DestinationIP, TimeGenerated asc
Hunting — SPL
spl
index=firewall sourcetype=cef
| eval IsScanner=if(cidrmatch("198.20.69.0/24",src_ip) OR cidrmatch("167.94.138.0/24",src_ip) OR cidrmatch("162.142.125.0/24",src_ip) OR cidrmatch("195.154.108.0/24",src_ip), 1, 0)
| where IsScanner=1 AND action="allow"
| bin _time span=7d
| stats values(dest_port) as Ports, earliest(_time) as FirstSeen, latest(_time) as LastSeen by dest_ip, _time
| sort dest_ip, _time

Atomic Red Team Tests

Test 1 Linux — Multi-Port TCP Connect Sweep Simulating Scanner Breadth Probe
linux

Runs an nmap TCP connect scan against the top 20 common ports on a lab-controlled target to generate the firewall/flow-log signature of a scanning service probing many distinct destination ports on one asset. Validates the ScannerBreadthProbe aggregation logic (dcount of destination ports per source/destination pair).

Command

bash
nmap -Pn -sT --top-ports 20 <TARGET_IP>

Expected Telemetry

Perimeter firewall/NSG flow log entries (CommonSecurityLog or CEF equivalent) recording 15-20 distinct DestinationPort values from the test source IP to <TARGET_IP> within a short window, with an allow or deny verdict per port.

Expected Detection

ScannerBreadthProbe fires once DistinctPorts >= 5 for the source/destination pair. Production logic additionally requires the source IP to fall within a known scanning-service CIDR range (ScannerRanges) — for lab validation, temporarily add the test host's IP to that list, since it will not otherwise match a real commercial scanner's published range.

Test 2 Linux — HTTP Request Using Known Scan-Database Crawler User-Agent
linux

Sends an HTTP request bearing the self-identifying User-Agent string used by Censys's scan crawler against a lab-controlled web endpoint, generating the web-log corroborating evidence documented under forensicArtifacts for this detection.

Command

bash
curl -s -A "CensysInspect/1.1 (+https://about.censys.io/)" http://<TEST_WEB_HOST>/ -o /dev/null -w "%{http_code}\n"

Expected Telemetry

Web/application server access log entry for <TEST_WEB_HOST> recording the User-Agent string 'CensysInspect/1.1 (+https://about.censys.io/)' against the source IP that issued the request.

Expected Detection

Not matched by the primary KQL/SPL network-layer alerts, which key on source-IP CIDR ranges rather than HTTP User-Agent. This test validates the web-log evidence-collection artifact only; add an HTTP-layer rule matching known scanner User-Agent strings if User-Agent-based alerting is required in your environment.

Test 3 Linux — Scanner Traffic Reaching an Asset Absent From the KnownAssets Watchlist
linux

Runs a targeted port probe against a lab test IP that is deliberately not present in the KnownAssets watchlist/lookup table, simulating a known scanning service discovering an unmanaged/shadow asset. Validates the leftanti join (KQL) / lookup-miss (SPL) logic behind ShadowAssetDiscoveredByScanner.

Command

bash
nmap -Pn -sT -p 22,80,443,3389,8080 <SHADOW_TEST_IP>

Cleanup

bash
Confirm <SHADOW_TEST_IP> was not accidentally added to the KnownAssets watchlist/known_assets.csv during testing.

Expected Telemetry

Perimeter firewall/flow log entries for the test source IP reaching <SHADOW_TEST_IP> on the probed ports, with no corresponding entry for <SHADOW_TEST_IP> in the KnownAssets watchlist or known_assets.csv lookup.

Expected Detection

ShadowAssetDiscoveredByScanner fires because the leftanti join (KQL) / lookup miss (SPL) finds no KnownAssets match for the destination IP, given the source IP falls within (or was temporarily added to) ScannerRanges for the test.

Related Detections