ConfigManBearPig

ConfigManBearPig is a "Python collector for adding SCCM attack paths to BloodHound with OpenGraph."

Prerequisites & Gotchas

Read this first — these are the things that will trip you up if you don't know them going in.

  • BloodHound MUST use the PostgreSQL graph backend, not Neo4j. OpenGraph SCCM_*/MSSQL_* kinds will not show up in Search/Pathfinding on Neo4j. Switch with bloodhound-cli:

    ./bloodhound-cli config set graph_driver pg

    Switching backends starts an empty graph, so you must re-ingest SharpHound/AzureHound/CMBP data afterward.

  • Register the schemas BEFORE trusting query results. If schema_SCCM.json / schema_MSSQL.json aren't uploaded, queries for SCCM/MSSQL edge kinds can return "no results" even when the data exists — a false negative. Register schemas first, then query.

  • Python version: openhound needs Python 3.13–3.15. If uv complains "No interpreter found" or "only system", install and force a managed one:

    uv python install 3.13
    UV_PYTHON_PREFERENCE=managed uv run --python 3.13 openhound ...
  • Some saved queries need other collectors' data (the names say so, e.g. "Requires SharpHound Collection", "Requires MSSQLHound Collection"). An empty result on those may just mean you didn't ingest that data — not that there's no attack path.

Install

uv tool install openhound --with configmanbearpig --prerelease=allow

Collect data

uv run openhound collect sccm .\out --run-all -d mayyhem.com --dc dc01.mayyhem.com -u "MAYYHEM\lowpriv" -p "Passw0rd!" -v

On Linux, use ./out and quote/escape the domain-qualified username (e.g. 'MAYYHEM/lowpriv').

Import the schemas

Go into the BloodHound admin web UI and hit Administration > OpenGraph Management. Upload schema_MSSQL.json and schema_SCCM.json.

The schema files ship inside the installed Python package. Find them with:

PKG=$(uv tool run --from configmanbearpig python -c "import openhound_sccm, os; print(os.path.dirname(openhound_sccm.__file__))")
cp "$PKG"/schema_SCCM.json "$PKG"/schema_MSSQL.json ~/

They'll be in ~/ for easy browsing in the upload dialog.

Import the collected data

Upload your collection zip (and your SharpHound/AzureHound data) via Administration > Data Collection > File Ingest > Upload File(s).

If queries later error with failed to translate kinds: unable to map kinds:, upload seed_data.json (in the repo) via File Ingest to populate one instance of each kind.

Import the saved queries

The repo ships ~20 prebuilt Cypher queries (TAKEOVER / CRED / ELEVATE chains, SCCM/MSSQL inventories) in cypher_queries/. These are not bundled with the uv tool install, so grab them from the repo:

git clone https://github.com/SpecterOps/ConfigManBearPig
cd ConfigManBearPig

Uploading them uses openhound searches upload, which talks to the BloodHound API and needs two things in a dlt secrets file: the BloodHound URL and a JWT.

The #1 gotcha: it wants a JWT, NOT a BloodHound API token. Do not create an "API Token" under Administration (that gives you an ID + HMAC key, which this tool does not use — it will fail with 401 Token Authorization failed). Instead, pull the session JWT from your logged-in browser.

1. Get the JWT from your browser

  1. Log into the BloodHound web UI.
  2. Open DevTools (F12) → Network tab.
  3. Run any query / click around so API calls appear, then click a request to /api/v2/....
  4. Under Request Headers, find Authorization: Bearer eyJ....
  5. Copy only the eyJ... part — everything after Bearer (no Bearer, no leading space).

Browser JWTs are short-lived. If the upload later 401s, your JWT probably expired — grab a fresh one.

2. Create the dlt secrets file

Create ~/.dlt/secrets.toml with exactly this (the JWT goes in the token field):

[destination.bloodhound]
url = "http://localhost:8080"
token = "eyJ...paste-your-JWT-here-no-Bearer..."

Adjust url/port to match your BloodHound instance.

3. Upload

uv run openhound searches upload ./cypher_queries

The queries now appear in BloodHound under Cypher > Saved Queries.

If an upload fails partway through, clear the stuck dlt package before retrying:

uv run --python 3.13 dlt pipeline bloodhound_searches drop-pending-packages

Run the queries

With the schemas registered, data ingested, and the PostgreSQL backend in use, run the saved queries from Cypher > Saved Queries. Suggested order:

  1. SCCM Infrastructure / SCCM Sites — confirm the graph populated (your site should render with proper SCCM node icons).
  2. SCCM Shortest TAKEOVER Path and the SCCM Hierarchy TAKEOVER-1 … -9 set — the takeover / coerce-and-relay paths. These surface relay-to-SMB / relay-to-MSSQL / relay-to-AdminService edges (drawn when SMB signing is off, EPA isn't required, etc.).
  3. SCCM CRED-* and the NAA / stored-account queries — credential-access paths and any Network Access Account identities.

Trust empty results only after the schemas are registered. Before registration, an unregistered edge kind can return "no results" even when the path exists.

ai