Skip to content

Add ASN numbers as scan targets#2741

Open
liquidsec wants to merge 27 commits into3.0from
asn-as-targets
Open

Add ASN numbers as scan targets#2741
liquidsec wants to merge 27 commits into3.0from
asn-as-targets

Conversation

@liquidsec
Copy link
Collaborator

@liquidsec liquidsec commented Oct 17, 2025

Summary

  • ASN as targets: You can now pass ASN numbers (e.g. AS13335) as scan targets. They are automatically expanded into their constituent IP ranges before the scan begins.
  • Migrated to asndb library: ASN lookups now use the asndb library instead of hand-rolled API calls. This handles ASN→CIDR expansion, IP→ASN reverse lookups, and caching.
  • Migrated to radixtarget 4.x: BBOTTarget now uses composition (owns a RadixTarget) instead of inheritance. This aligns with the radixtarget 4.x string-only API.
  • Replaced SHA-1 hashing with seahash/FNV-1a: Target and blacklist hashing now uses faster 64-bit hash functions instead of SHA-1.
  • BBOTTarget.generate_children(): New async method on the target object that expands compound seed types (like ASNs) into child events before the scan begins.
  • shodan_enterprise module cleanup: Removed redundant ASN emission (handled by asn report module via asndb). Fixed scope filtering to use framework's in_scope_only attribute properly.
  • Engine subprocess leak fix: Fixed a bug where DNS/web engine subprocesses were not properly shut down, causing resource accumulation across tests.
  • install_core_deps performance: Core dependency installation now caches properly, reducing redundant 15s Ansible invocations to ~0s on subsequent runs.
  • Graceful handling for missing module deps: Modules with uninstallable dependencies no longer crash the scan; they are skipped with a warning. Non-TTY sudo prompts are also handled gracefully.
  • Test fixes: Fixed several test reliability issues including test_python_api preset checks and scope accuracy tests. Added scope filtering tests for shodan_enterprise. Removed mocks in favor of real asndb lookups.

# Test ASN with other targets
target = BBOTTarget("ASN:15169", "evilcorp.com", "1.2.3.4/24")
assert "ASN:15169" in target.seeds.inputs
assert "evilcorp.com" in target.seeds.inputs

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization

The string [evilcorp.com](1) may be at an arbitrary position in the sanitized URL.

Copilot Autofix

AI 5 months ago

The code currently checks for the presence of "evilcorp.com" as a substring in target.seeds.inputs, which is subject to the vulnerabilities described. To fix this, the test should specifically check if "evilcorp.com" is present as an actual host, not as a substring within any input string. This can be done by parsing the inputs and extracting their hostnames for comparison, or, if target.seeds provides a .hosts attribute containing canonicalized hosts, use that for the assertion. Thus, change the assertion on line 377 to ensure "evilcorp.com" is in the normalized or parsed hosts. This may require referencing the hosts set or parsing the inputs using a standard library (e.g., urlparse).

Make the following changes in bbot/test/test_step_1/test_target.py:

  • On line 377, replace the substring-in check with an explicit hostname check using either the .hosts attribute (if available), or by parsing input values using urlparse.
  • If using urlparse, import it from the standard library.
Suggested changeset 1
bbot/test/test_step_1/test_target.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/bbot/test/test_step_1/test_target.py b/bbot/test/test_step_1/test_target.py
--- a/bbot/test/test_step_1/test_target.py
+++ b/bbot/test/test_step_1/test_target.py
@@ -374,7 +374,7 @@
     # Test ASN with other targets
     target = BBOTTarget("ASN:15169", "evilcorp.com", "1.2.3.4/24")
     assert "ASN:15169" in target.seeds.inputs
-    assert "evilcorp.com" in target.seeds.inputs
+    assert "evilcorp.com" in [str(host) for host in target.seeds.hosts]
     assert "1.2.3.0/24" in target.seeds.inputs  # IP ranges are normalized to network address
 
     # Test ASN targets must be expanded before being useful in whitelist/blacklist
EOF
@@ -374,7 +374,7 @@
# Test ASN with other targets
target = BBOTTarget("ASN:15169", "evilcorp.com", "1.2.3.4/24")
assert "ASN:15169" in target.seeds.inputs
assert "evilcorp.com" in target.seeds.inputs
assert "evilcorp.com" in [str(host) for host in target.seeds.hosts]
assert "1.2.3.0/24" in target.seeds.inputs # IP ranges are normalized to network address

# Test ASN targets must be expanded before being useful in whitelist/blacklist
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
@github-actions
Copy link
Contributor

github-actions bot commented Oct 17, 2025

📊 Performance Benchmark Report

Comparing 3.0 (baseline) vs asn-as-targets (current)

📈 Detailed Results (All Benchmarks)

📋 Complete results for all benchmarks - includes both significant and insignificant changes

🧪 Test Name 📏 Base 📏 Current 📈 Change 🎯 Status
Bloom Filter Dns Mutation Tracking Performance 4.41ms 4.34ms -1.7%
Bloom Filter Large Scale Dns Brute Force 19.03ms 17.88ms -6.1%
Large Closest Match Lookup 361.64ms 357.92ms -1.0%
Realistic Closest Match Workload 192.06ms 196.75ms +2.4%
Event Memory Medium Scan 1767 B/event 1768 B/event +0.1%
Event Memory Large Scan 1757 B/event 1757 B/event +0.0%
Event Validation Full Scan Startup Small Batch 498.55ms 385.78ms -22.6% 🟢🟢🟢 🚀
Event Validation Full Scan Startup Large Batch 786.38ms 562.15ms -28.5% 🟢🟢🟢 🚀
Make Event Autodetection Small 30.98ms 31.45ms +1.5%
Make Event Autodetection Large 313.63ms 323.11ms +3.0%
Make Event Explicit Types 13.96ms 14.23ms +1.9%
Excavate Single Thread Small 4.121s 4.011s -2.7%
Excavate Single Thread Large 9.738s 9.657s -0.8%
Excavate Parallel Tasks Small 4.294s 4.166s -3.0%
Excavate Parallel Tasks Large 7.399s 7.270s -1.8%
Is Ip Performance 3.17ms 3.17ms -0.1%
Make Ip Type Performance 11.45ms 11.40ms -0.4%
Mixed Ip Operations 4.53ms 4.47ms -1.2%
Typical Queue Shuffle 63.06µs 62.83µs -0.4%
Priority Queue Shuffle 702.72µs 709.64µs +1.0%

🎯 Performance Summary

+ 2 improvements 🚀
  18 unchanged ✅

🔍 Significant Changes (>10%)

  • Event Validation Full Scan Startup Small Batch: 22.6% 🚀 faster
  • Event Validation Full Scan Startup Large Batch: 28.5% 🚀 faster

🐍 Python Version 3.11.14

@codecov
Copy link

codecov bot commented Oct 17, 2025

Codecov Report

❌ Patch coverage is 88.45750% with 110 lines in your changes missing coverage. Please review.
✅ Project coverage is 91%. Comparing base (b90f1d3) to head (a294f89).
⚠️ Report is 8 commits behind head on 3.0.

Files with missing lines Patch % Lines
bbot/core/helpers/misc.py 57% 22 Missing ⚠️
bbot/core/helpers/asn.py 59% 18 Missing ⚠️
bbot/test/conftest.py 0% 16 Missing ⚠️
bbot/scanner/target.py 92% 10 Missing ⚠️
bbot/core/engine.py 56% 8 Missing ⚠️
bbot/core/helpers/simhash.py 86% 7 Missing ⚠️
bbot/core/helpers/depsinstaller/installer.py 45% 5 Missing ⚠️
bbot/modules/baddns.py 67% 5 Missing ⚠️
bbot/cli.py 88% 4 Missing ⚠️
bbot/scanner/scanner.py 94% 4 Missing ⚠️
... and 7 more
Additional details and impacted files
@@          Coverage Diff           @@
##             3.0   #2741    +/-   ##
======================================
- Coverage     92%     91%    -0%     
======================================
  Files        436     434     -2     
  Lines      36320   36452   +132     
======================================
+ Hits       33059   33141    +82     
- Misses      3261    3311    +50     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@TheTechromancer
Copy link
Collaborator

This PR is currently waiting on two things:

@liquidsec liquidsec changed the base branch from dev to 3.0 February 26, 2026 23:12
@liquidsec liquidsec changed the title ASN Helper / Add ASN's as an available type type Add ASN numbers as scan targets Feb 28, 2026
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of this will be replaced by the asndb pypi library, which currently needs API key + tests passing in order to publish.

Comment on lines +479 to +482
raise BBOTError(
log.warning(
f"Error loading module {module_name}: {e}. You may have leftover artifacts from an older version of BBOT. Try deleting/renaming your '~/.bbot' directory."
) from e
)
module = None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error was intentional to stop the scan if a module failed to load

Comment on lines +293 to +304
if self._target is None:
raise ValueError("Cannot access target before preset is baked (use ._seeds instead)")
return self._target

@property
def seeds(self):
if self._target is None:
raise ValueError("Cannot access target before preset is baked (use ._seeds instead)")
return None
return self.target.seeds

@property
def blacklist(self):
if self._target is None:
raise ValueError("Cannot access blacklist before preset is baked (use ._blacklist instead)")
return None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these errors are designed to catch situations where these attributes are accessed prematurely (i.e. before bake). if they're returning None, we shouldn't need to access them

let's put it back and see what breaks

Comment on lines +1168 to +1221
j["target"] = self.preset.target.json
j["preset"] = self.preset.to_dict(redact_secrets=True)
if self.preset is not None:
j["target"] = self.preset.target.json
j["preset"] = self.preset.to_dict(redact_secrets=True)
else:
j["target"] = {}
j["preset"] = {}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we try reverting this to see why it had to be introduced? a scan should never exist without a preset (it should be impossible)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after migrating to asndb pypi library, passing in helpers shouldn't be necessary

Copy link
Collaborator

@TheTechromancer TheTechromancer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asdf

kwargs["stdin"] = asyncio.subprocess.PIPE

log.hugeverbose(f"run: {' '.join(command)}")
log.debug(f"run: {' '.join(command)}")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we must show commands when -v. if necessary, we can add a exclusion flag

Copy link
Collaborator

@TheTechromancer TheTechromancer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asdf

liquidsec added 15 commits March 5, 2026 15:01
- BaseTarget no longer subclasses RadixTarget; uses composition instead
- Rename strict_dns_scope -> strict_scope everywhere
- Update host_size_key import path for radixtarget 4.x
- Handle radixtarget 4.x API changes (strings-only, no _add, hash is int)
- Skip acl_mode when strict_scope is True (mutually exclusive in 4.x)
- Update test assertions for new hash values and string-based hosts

Work in progress - more test fixes needed.
# Conflicts:
#	bbot/scanner/scanner.py
#	bbot/test/test_step_1/test_python_api.py
…cope filtering

- Remove ASN event emission (already handled by asn report module via asndb)
- Replace scope_distance_modifier+filter_event with proper in_scope_only class attr
- Dynamically set scope_distance_modifier=1 when in_scope_only option is disabled
- Add tests for in_scope_only=True and in_scope_only=False behavior
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants