Skip to content

Commit

Permalink
Merge pull request #1568 from blacklanternsecurity/discovery-ids
Browse files Browse the repository at this point in the history
Include event IDs in discovery path
  • Loading branch information
TheTechromancer authored Jul 28, 2024
2 parents 17c3f7e + df89030 commit 274b881
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 14 deletions.
2 changes: 1 addition & 1 deletion bbot/core/event/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ def discovery_path(self):
This event's full discovery context, including those of all its parents
"""
full_event_chain = list(reversed(self.get_parents())) + [self]
return [e.discovery_context for e in full_event_chain if e.type != "SCAN"]
return [[e.id, e.discovery_context] for e in full_event_chain if e.type != "SCAN"]

@property
def words(self):
Expand Down
4 changes: 3 additions & 1 deletion bbot/modules/output/csv.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ def writerow(self, row):

async def handle_event(self, event):
# ["Event type", "Event data", "IP Address", "Source Module", "Scope Distance", "Event Tags"]
discovery_path = getattr(event, "discovery_path", [])
discovery_path = [e[-1] for e in discovery_path]
self.writerow(
{
"Event type": getattr(event, "type", ""),
Expand All @@ -64,7 +66,7 @@ async def handle_event(self, event):
"Source Module": str(getattr(event, "module_sequence", "")),
"Scope Distance": str(getattr(event, "scope_distance", "")),
"Event Tags": ",".join(sorted(list(getattr(event, "tags", [])))),
"Discovery Path": " --> ".join(getattr(event, "discovery_path", [])),
"Discovery Path": " --> ".join(discovery_path),
}
)

Expand Down
22 changes: 12 additions & 10 deletions bbot/test/test_step_1/test_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ async def test_events(events, helpers):
db_event._resolved_hosts = {"127.0.0.1"}
db_event.scope_distance = 1
assert db_event.discovery_context == "test context"
assert db_event.discovery_path == ["test context"]
assert db_event.discovery_path == [["OPEN_TCP_PORT:5098b5e3fc65b13bb4a5cee4201c2e160fa4ffac", "test context"]]
timestamp = db_event.timestamp.isoformat()
json_event = db_event.json()
assert json_event["scope_distance"] == 1
Expand All @@ -417,15 +417,17 @@ async def test_events(events, helpers):
assert json_event["host"] == "evilcorp.com"
assert json_event["timestamp"] == timestamp
assert json_event["discovery_context"] == "test context"
assert json_event["discovery_path"] == ["test context"]
assert json_event["discovery_path"] == [["OPEN_TCP_PORT:5098b5e3fc65b13bb4a5cee4201c2e160fa4ffac", "test context"]]
reconstituted_event = event_from_json(json_event)
assert reconstituted_event.scope_distance == 1
assert reconstituted_event.timestamp.isoformat() == timestamp
assert reconstituted_event.data == "evilcorp.com:80"
assert reconstituted_event.type == "OPEN_TCP_PORT"
assert reconstituted_event.host == "evilcorp.com"
assert reconstituted_event.discovery_context == "test context"
assert reconstituted_event.discovery_path == ["test context"]
assert reconstituted_event.discovery_path == [
["OPEN_TCP_PORT:5098b5e3fc65b13bb4a5cee4201c2e160fa4ffac", "test context"]
]
assert "127.0.0.1" in reconstituted_event.resolved_hosts
hostless_event = scan.make_event("asdf", "ASDF", dummy=True)
hostless_event_json = hostless_event.json()
Expand Down Expand Up @@ -596,7 +598,7 @@ async def handle_event(self, event):
if e.type == "DNS_NAME"
and e.data == "evilcorp.com"
and e.discovery_context == f"Scan {scan.name} seeded with DNS_NAME: evilcorp.com"
and e.discovery_path == [f"Scan {scan.name} seeded with DNS_NAME: evilcorp.com"]
and [_[-1] for _ in e.discovery_path] == [f"Scan {scan.name} seeded with DNS_NAME: evilcorp.com"]
]
)
assert 1 == len(
Expand All @@ -606,7 +608,7 @@ async def handle_event(self, event):
if e.type == "DNS_NAME"
and e.data == "one.evilcorp.com"
and e.discovery_context == "module_1 invoked forbidden magick to discover DNS_NAME one.evilcorp.com"
and e.discovery_path
and [_[-1] for _ in e.discovery_path]
== [
f"Scan {scan.name} seeded with DNS_NAME: evilcorp.com",
"module_1 invoked forbidden magick to discover DNS_NAME one.evilcorp.com",
Expand All @@ -621,7 +623,7 @@ async def handle_event(self, event):
and e.data == "two.evilcorp.com"
and e.discovery_context
== "module_1 pledged its allegiance to cthulu and was awarded DNS_NAME two.evilcorp.com"
and e.discovery_path
and [_[-1] for _ in e.discovery_path]
== [
f"Scan {scan.name} seeded with DNS_NAME: evilcorp.com",
"module_1 invoked forbidden magick to discover DNS_NAME one.evilcorp.com",
Expand All @@ -636,7 +638,7 @@ async def handle_event(self, event):
if e.type == "DNS_NAME"
and e.data == "three.evilcorp.com"
and e.discovery_context == "module_2 asked nicely and was given DNS_NAME three.evilcorp.com"
and e.discovery_path
and [_[-1] for _ in e.discovery_path]
== [
f"Scan {scan.name} seeded with DNS_NAME: evilcorp.com",
"module_1 invoked forbidden magick to discover DNS_NAME one.evilcorp.com",
Expand All @@ -658,11 +660,11 @@ async def handle_event(self, event):
if e.type == "DNS_NAME"
and e.data == "four.evilcorp.com"
and e.discovery_context == "module_2 used brute force to obtain DNS_NAME four.evilcorp.com"
and e.discovery_path == final_path
and [_[-1] for _ in e.discovery_path] == final_path
]
assert 1 == len(final_event)
j = final_event[0].json()
assert j["discovery_path"] == final_path
assert [_[-1] for _ in j["discovery_path"]] == final_path

await scan._cleanup()

Expand All @@ -675,6 +677,6 @@ async def handle_event(self, event):
events = [e async for e in scan.async_start()]
blsops_event = [e for e in events if e.type == "DNS_NAME" and e.data == "blsops.com"]
assert len(blsops_event) == 1
assert blsops_event[0].discovery_path[1] == "URL_UNVERIFIED has host DNS_NAME: blacklanternsecurity.com"
assert blsops_event[0].discovery_path[1][-1] == "URL_UNVERIFIED has host DNS_NAME: blacklanternsecurity.com"

await scan._cleanup()
6 changes: 4 additions & 2 deletions bbot/test/test_step_2/module_tests/test_module_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def check(self, module_test, events):
assert scan_json["data"]["target"]["whitelist"] == ["blacklanternsecurity.com"]
assert dns_json["data"] == dns_data
assert dns_json["discovery_context"] == context_data
assert dns_json["discovery_path"] == [context_data]
assert dns_json["discovery_path"] == [["DNS_NAME:1e57014aa7b0715bca68e4f597204fc4e1e851fc", context_data]]

# event objects reconstructed from json
scan_reconstructed = event_from_json(scan_json)
Expand All @@ -37,7 +37,9 @@ def check(self, module_test, events):
assert scan_reconstructed.data["target"]["whitelist"] == ["blacklanternsecurity.com"]
assert dns_reconstructed.data == dns_data
assert dns_reconstructed.discovery_context == context_data
assert dns_reconstructed.discovery_path == [context_data]
assert dns_reconstructed.discovery_path == [
["DNS_NAME:1e57014aa7b0715bca68e4f597204fc4e1e851fc", context_data]
]


class TestJSONSIEMFriendly(ModuleTestBase):
Expand Down

0 comments on commit 274b881

Please sign in to comment.