Skip to content

Commit 2fedca2

Browse files
Merge pull request #41 from blacklanternsecurity/dev
Dev -> Stable
2 parents ec3b927 + 02cb237 commit 2fedca2

File tree

85 files changed

+4633
-571
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+4633
-571
lines changed

.github/workflows/docker-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ concurrency:
1111
cancel-in-progress: true
1212

1313
jobs:
14-
test:
14+
docker-test:
1515
runs-on: self-hosted
1616
steps:
1717
- uses: actions/checkout@v4

README.md

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ BBOT Server is a database and multiplayer hub for all your [BBOT](https://github
2929

3030
```bash
3131
# clone the repo and cd into it
32-
git clone [email protected]:blacklanternsecurity/bbot-server.git && cd bbot_server
32+
git clone [email protected]:blacklanternsecurity/bbot-server.git && cd bbot-server
3333

3434
# Install in editable mode
3535
pipx install -e .
3636
```
3737

38-
Note: to update to the latest version, run `git pull` in the `bbot_server` directory.
38+
Note: to update to the latest version, run `git pull` in the `bbot-server` directory.
3939

4040
## Start the server
4141

@@ -63,7 +63,7 @@ The first time you start BBOT Server, an API key will be auto generated and put
6363

6464
# list of API keys to be considered valid
6565
api_keys:
66-
- 4aa8b3c2-9b4d-4208-890c-4ce9ad3b4710
66+
- deadbeef-9b4d-4208-890c-4ce9ad3b4710
6767
```
6868
6969
The `api_keys` value in `config.yml` is used by both the server (as a database of valid API keys), and by the client (it will pick one from the list and use it). Normally it just works and you don't have to mess with it. But to access BBOT Server remotely, you'll need to copy the API key from the server onto your local system, along with its URL:
@@ -77,6 +77,8 @@ api_keys:
7777

7878
This tells `bbctl` (the client) where the server is, and gives it the means to authenticate.
7979

80+
To utilise the API key and interact with the BBOT Server via the HTTP API, set the `X-API-Key` HTTP header to the value of a valid API key.
81+
8082
### Adding and Revoking API Keys
8183

8284
API keys can be added and removed if you are on the server machine:
@@ -94,13 +96,29 @@ bbctl server apikey delete deadbeef-9b4d-4208-890c-4ce9ad3b4710
9496

9597
## Send a BBOT Scan to the Server
9698

97-
You can output a BBOT scan directly to BBOT server:
99+
You can output a BBOT scan directly to BBOT server with the following preset:
100+
101+
```yaml
102+
# bbot-server.yml
103+
104+
output_modules:
105+
- http
106+
107+
config:
108+
modules:
109+
http:
110+
# URL of BBOT Server
111+
url: http://localhost:8807/v1/events/
112+
# API Key header
113+
headers:
114+
x-api-key: deadbeef-9b4d-4208-890c-4ce9ad3b4710
115+
```
98116

99117
Note that this requires BBOT 3.0 or later (install with `pipx install git+https://github.com/blacklanternsecurity/[email protected]`)
100118

101119
```bash
102120
# Start a BBOT scan, sending output to BBOT server
103-
bbot -t evilcorp.com -p subdomain-enum -om http -c modules.http.url=http://localhost:8807/v1/events/
121+
bbot -t evilcorp.com -p subdomain-enum ./bbot-server.yml
104122
```
105123

106124
## Ingest events from past BBOT scans
@@ -200,10 +218,10 @@ You can list targets like so:
200218

201219
```bash
202220
# List targets
203-
bbctl target list
221+
bbctl scan target list
204222
205223
# Create a new target
206-
bbctl target create --seeds seeds.txt --blacklist blacklist.txt --name custom_target
224+
bbctl scan target create --seeds seeds.txt --blacklist blacklist.txt --name custom_target
207225
208226
# List only the assets that match your new target
209227
bbctl asset list --target custom_target
@@ -331,4 +349,6 @@ After connecting your AI client to BBOT Server, you can ask it sensible question
331349

332350
*REST API*
333351

352+
Connect to the default URL at [http://localhost:8807](http://localhost:8807/) to view and use the interactive API documentation.
353+
334354
![rest-api](https://github.com/user-attachments/assets/567bd266-b047-4005-bc0b-22d5bfd2a12b)

bbot_server/agent/__init__.py

Lines changed: 0 additions & 3 deletions
This file was deleted.

bbot_server/api/_fastapi.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import logging
22
from contextlib import asynccontextmanager
33
from fastapi.openapi.utils import get_openapi
4-
from fastapi import FastAPI, HTTPException, Depends, Request, WebSocket
54
from fastapi.responses import RedirectResponse, ORJSONResponse
5+
from fastapi import FastAPI, HTTPException, Depends, Request, WebSocket
66

7+
from bbot_server import modules # noqa: F401
78
import bbot_server.config as bbcfg
89
from bbot_server.errors import BBOTServerError, handle_bbot_server_error
910

bbot_server/applets/_root.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
11
import bbot_server.config as bbcfg
22

3-
from bbot_server.applets._base import BaseApplet
4-
5-
# applet imports
6-
from bbot_server.applets.stats import StatsApplet
7-
from bbot_server.applets.assets import AssetsApplet
8-
from bbot_server.applets.events import EventsApplet
9-
from bbot_server.applets.scans import ScansApplet
10-
from bbot_server.applets.activity import ActivityApplet
3+
from bbot_server.applets.base import BaseApplet
114

125

136
class RootApplet(BaseApplet):
14-
include_apps = [AssetsApplet, EventsApplet, ScansApplet, ActivityApplet, StatsApplet]
15-
167
name = "Root Applet"
178

9+
attach_to = ""
10+
1811
_nested = False
1912

2013
_route_prefix = ""

bbot_server/applets/agents/__init__.py

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import asyncio
33
import inspect
44
import logging
5+
import traceback
56
from fastapi import APIRouter
67
from omegaconf import OmegaConf
78
from typing import Annotated, Any # noqa
@@ -10,12 +11,14 @@
1011
from pymongo import WriteConcern, ASCENDING
1112
from pymongo.errors import OperationFailure
1213

14+
from bbot_server.assets import Asset
1315
from bbot.models.pydantic import Event
16+
from bbot_server.modules import API_MODULES
1417
from bbot_server.errors import BBOTServerError
1518
from bbot.core.helpers import misc as bbot_misc
1619
from bbot_server.applets._routing import ROUTE_TYPES
1720
from bbot_server.utils import misc as bbot_server_misc
18-
from bbot_server.models.activity_models import Activity
21+
from bbot_server.modules.activity.activity_models import Activity
1922

2023
word_regex = re.compile(r"\W+")
2124

@@ -75,8 +78,8 @@ class BaseApplet:
7578
# the pydantic model this applet uses
7679
model = None
7780

78-
# optionally you can include other applets
79-
include_apps = []
81+
# which other applet should include this one
82+
attach_to = ""
8083

8184
# whether to nest this applet under its parent
8285
# this is typically true for every applet except the root
@@ -85,6 +88,16 @@ class BaseApplet:
8588
# optionally override route prefix
8689
_route_prefix = None
8790

91+
# priority of this applet's handle_activity method, between 1 and 5, inclusive
92+
# higher numbers are higher priority
93+
# this is used to determine the order in which applets' .handle_activity methods are called
94+
_activity_priority = 3
95+
96+
# priority of this applet's handle_event method, between 1 and 5, inclusive
97+
# higher numbers are higher priority
98+
# this is used to determine the order in which applets' .handle_event methods are called
99+
_event_priority = 3
100+
88101
# BBOT helpers
89102
helpers = bbot_server_misc
90103
bbot_helpers = bbot_misc
@@ -113,14 +126,13 @@ def __init__(self, parent=None):
113126

114127
self._add_custom_routes()
115128

116-
for app in self.include_apps:
129+
applets_to_include = API_MODULES.get(self.name_lowercase, {})
130+
for included_app_name in sorted(applets_to_include):
117131
try:
118-
self.include_app(app)
132+
self.include_app(applets_to_include[included_app_name])
119133
except Exception as e:
120-
self.log.error(f"Error including app {app}: {e}")
121-
import traceback
122-
123-
traceback.print_exc()
134+
self.log.error(f"Error including app {included_app_name}: {e}")
135+
self.log.error(traceback.format_exc())
124136

125137
self._setup_finished = False
126138

@@ -346,7 +358,7 @@ async def _cleanup(self):
346358
async def cleanup(self):
347359
pass
348360

349-
async def handle_activity(self, activity: Activity):
361+
async def handle_activity(self, activity: Activity, asset: Asset = None):
350362
pass
351363

352364
async def handle_event(self, event: Event, asset=None):
@@ -367,7 +379,8 @@ async def _emit_activity(self, activity: Activity):
367379
await self.root.message_queue.publish_asset(activity)
368380

369381
def include_app(self, app_class):
370-
self.log.debug(f"{self.__class__.__name__} including {app_class.__name__}")
382+
self.log.debug(f"{self.name_lowercase} including applet {app_class.name_lowercase}")
383+
371384
# instantiate it
372385
applet = app_class(parent=self)
373386
# set it as an attribute on self
@@ -401,10 +414,17 @@ async def _put_obj(self, obj):
401414
{"host": obj.host, "type": self.model.__name__}, {"$set": obj.model_dump()}, upsert=True
402415
)
403416

404-
@cached_property
405-
def name_lowercase(self):
406-
# Replace non-alphanumeric characters with an underscore
407-
return word_regex.sub("_", self.name.lower())
417+
class NameLowercaseDescriptor:
418+
def __init__(self):
419+
self._cache = {}
420+
421+
def __get__(self, obj, owner):
422+
cache_key = owner if obj is None else obj
423+
if cache_key not in self._cache:
424+
self._cache[cache_key] = word_regex.sub("_", cache_key.name.lower())
425+
return self._cache[cache_key]
426+
427+
name_lowercase = NameLowercaseDescriptor()
408428

409429
def all_child_applets(self, include_self=False):
410430
applets = []

bbot_server/applets/buckets.py

Lines changed: 0 additions & 6 deletions
This file was deleted.

bbot_server/applets/export.py

Lines changed: 0 additions & 28 deletions
This file was deleted.

bbot_server/applets/redirects.py

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)