Skip to content

Fix non-functional DNS brute-force canary check#3005

Open
aconite33 wants to merge 4 commits into3.0from
fix-dnsbrute-canary-check
Open

Fix non-functional DNS brute-force canary check#3005
aconite33 wants to merge 4 commits into3.0from
fix-dnsbrute-canary-check

Conversation

@aconite33
Copy link
Copy Markdown
Contributor

Summary

Fixes #3004 -- three bugs that made the canary-based false-positive detection in brute.py completely non-functional:

  • Exhausted generator: The canaries generator was consumed by list() on line 61, then reused for in membership checks on line 71 which always returned False. Replaced with a set built from the already-materialized list for correct (and O(1)) lookups.
  • Trailing dot: hostname.split(domain)[0] produces a trailing dot (e.g. "sub.") that never matched canary strings like "sub". Added .rstrip(".") to normalize the extracted subdomain.
  • Variable shadowing: The for domain, rdtypes in wildcard_domains.items() loop overwrote the domain function parameter, which corrupted the abort warning message. Renamed the loop variable to wildcard_domain.

Impact

On wildcard domains, massdns returns results for every queried subdomain including canaries. The canary safety net is supposed to detect this and abort, but the three bugs above prevented it from ever triggering. This caused scans to flood with thousands of false-positive DNS_NAME events and wildcard detection log entries.

Changes

  • bbot/core/helpers/dns/brute.py -- all three bug fixes
  • bbot/test/test_step_1/test_dns.py -- unit test that validates the canary check logic (exhausted generator, trailing dot, variable shadowing, and end-to-end canary detection)

Test plan

  • New test_dnsbrute_canary_check unit test passes
  • Run full test suite
  • Manual scan against a known wildcard domain to verify canaries trigger abort

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 31, 2026

📊 Performance Benchmark Report

Comparing 3.0 (baseline) vs fix-dnsbrute-canary-check (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.21ms 4.18ms -0.5%
Bloom Filter Large Scale Dns Brute Force 17.42ms 17.35ms -0.4%
Large Closest Match Lookup 351.33ms 342.55ms -2.5%
Realistic Closest Match Workload 186.52ms 189.25ms +1.5%
Event Memory Medium Scan 1776 B/event 1776 B/event +0.0%
Event Memory Large Scan 1760 B/event 1760 B/event +0.0%
Event Validation Full Scan Startup Small Batch 405.82ms 404.23ms -0.4%
Event Validation Full Scan Startup Large Batch 580.04ms 562.80ms -3.0%
Make Event Autodetection Small 30.53ms 30.57ms +0.2%
Make Event Autodetection Large 311.26ms 313.59ms +0.7%
Make Event Explicit Types 13.69ms 13.62ms -0.5%
Excavate Single Thread Small 3.886s 3.933s +1.2%
Excavate Single Thread Large 9.441s 9.809s +3.9%
Excavate Parallel Tasks Small 4.066s 4.089s +0.6%
Excavate Parallel Tasks Large 7.157s 7.186s +0.4%
Is Ip Performance 3.17ms 3.20ms +1.0%
Make Ip Type Performance 11.52ms 11.59ms +0.7%
Mixed Ip Operations 4.50ms 4.56ms +1.2%
Typical Queue Shuffle 64.38µs 62.29µs -3.2%
Priority Queue Shuffle 731.91µs 695.73µs -4.9%

🎯 Performance Summary

No significant performance changes detected (all changes <10%)


🐍 Python Version 3.11.15

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 31, 2026

Codecov Report

❌ Patch coverage is 92.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 91%. Comparing base (8b02acb) to head (751df73).
⚠️ Report is 11 commits behind head on 3.0.

Files with missing lines Patch % Lines
...t/test_step_2/module_tests/test_module_dnsbrute.py 90% 2 Missing ⚠️
Additional details and impacted files
@@          Coverage Diff           @@
##             3.0   #3005    +/-   ##
======================================
- Coverage     91%     91%    -0%     
======================================
  Files        436     440     +4     
  Lines      37072   37250   +178     
======================================
+ Hits       33677   33748    +71     
- Misses      3395    3502   +107     

☔ 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.

The canary-based false-positive detection in brute.py was completely
non-functional due to three bugs:

1. Exhausted generator: `canaries` generator was consumed by `list()`
   but then used for `in` membership checks, which always returned
   False. Fixed by using a set built from the list.

2. Trailing dot: `hostname.split(domain)[0]` produces a trailing dot
   (e.g. "sub.") that never matches canary strings. Fixed by stripping
   the trailing dot.

3. Variable shadowing: the `for domain, rdtypes in ...` loop overwrote
   the `domain` function parameter, corrupting the abort log message.
   Fixed by renaming the loop variable.
@aconite33 aconite33 force-pushed the fix-dnsbrute-canary-check branch from c4eb3eb to f848f04 Compare March 31, 2026 23:35
@aconite33 aconite33 changed the base branch from dev to 3.0 March 31, 2026 23:35
@TheTechromancer
Copy link
Copy Markdown
Collaborator

Thanks for catching these bugs. However the tests don't actually test any of the fixed code. They need to exercise the actual module code in order to be valid.

This should be possible though our standard methods of subprocess output and DNS mocking.

…y code

Move canary check test from test_dns.py into test_module_dnsbrute.py as
a proper integration test. Mocks massdns to return results for every
input subdomain (simulating a wildcard domain), then verifies that the
canary detection aborts and no DNS_NAME events are emitted.
@aconite33
Copy link
Copy Markdown
Contributor Author

Thanks for catching these bugs. However the tests don't actually test any of the fixed code. They need to exercise the actual module code in order to be valid.

This should be possible though our standard methods of subprocess output and DNS mocking.

Got it. I've updated the tests to align with the current tests.

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