# ConfigManBearPig
[ConfigManBearPig](https://github.com/SpecterOps/ConfigManBearPig) is a "Python collector for adding SCCM attack paths to BloodHound with OpenGraph."

!!!warning
This was put together by AI using a bunch of troubleshooting I was doing on a live assessment
!!!

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