
Ihr vorlagenbasiertes BloodHound-Terminal-Begleitwerkzeug

Eine Python3-Terminalanwendung, die Neo4j-Cypher für BloodHound-Datensätze enthält, mit einem Skript zum automatischen Importieren in BloodHound CE.
Terminal

HTML-Bericht

HTML-Bericht (Fortsetzung)

BloodHound ist ein Standardwerkzeug für jeden Penetrationstester. Allerdings gibt es einige negative Nebeneffekte aufgrund seines Designs. Ich werde die größten Problemstellen behandeln, die ich erlebt habe und was dieses Tool zu adressieren versucht:
JSON-Graphen parsen, benötige ich Graph-Ergebnisse in einem zeilenweisen .txt-Format, um tatsächlich Angriffe aus anderen Tools durchzuführenDieses Tool kann sowohl für Red- als auch Blue-Teams einen erheblichen Mehrwert bieten.
Übernimm die Kontrolle über deine BloodHound-Daten mit CypherHound!
grep/cut/awk-freundlichen Format bereitgestelltcustomqueries.json-Importskript für BloodHound CE enthaltenStelle sicher, dass python3 installiert ist, und führe aus:
python3 -m pip install -r requirements.txt
Starte das Programm mit: python3 cypherhound.py -c config.json -y queries.yaml
Das Programm liest eine Konfigurationsdatei im json-Format. Ein Beispiel dieser Datei ist unten dargestellt:
{
"user": "neo4j",
"pwd": "password",
"database": "neo4j"
}
wobei:
user dein Neo4j-Benutzername istpwd dein Neo4j-Passwort istdatabase deine Neo4j-Datenbank istDas Programm liest Abfragen aus einer YAML-Datei im folgenden Format. ad-queries.yaml wurde als Beispiel mit Abfragen zu Active Directory bereitgestellt. msg_template ist für Kürzeste-Pfade-Abfragen nicht erforderlich, aber sie müssen die Variable zurückgeben, die den Pfad enthält
queries:
- group: general
desc: List all AddKeyCredentialLink privileges for owned principals
cypher: |-
MATCH (n {owned: true})-[r:AddKeyCredentialLink]->(m)
RETURN n.name AS n_name, m.name AS m_name, labels(m) AS labels_m, labels(n) AS labels_n
ORDER BY n.name
msg_template: |-
{{ n_name }} ({{ labels_n[0] }}/{{ labels_n[1] }}) has AddKeyCredentialLink over {{ m_name }} ({{
labels_m[0] }}/{{ labels_m[1] }})
Eine Aufschlüsselung der Schlüssel/Wert-Paare ist unten zu sehen:
params.*)Das Programm verwendet Jinja2, um Cypher zu rendern. Definiere Laufzeitparameter mit dem Befehl set und referenziere sie in YAML als {{ params.<key> }}.
CLI
set <key> <value...> # e.g., set user [email protected]
unset <key> # optional
show # optional
YAML-Beispiel
- group: user
desc: List all privileges for this user
cypher: |-
MATCH (n:User)-[r]->(m)
WHERE n.name =~ '((?i){{ params.user }})'
RETURN n.name AS n_name, TYPE(r) AS rel_type, labels(m) AS labels_m, m.name AS m_name
ORDER BY TYPE(r)
msg_template: |-
User {{ n_name }} has {{ rel_type }} over {{ m_name }} ({{ labels_m[0] }}/{{ labels_m[1] }})
Häufige Parametermuster
Dieses Repository stellt ein Skript query-importer.py bereit, um Abfragen automatisch aus einer JSON-Datei in die BloodHound CE UI zu importieren. bh_query_converter.py wurde ebenfalls bereitgestellt, um eine für die Terminalanwendung vorgesehene YAML-Datei in das von query-importer.py & BloodHound CE erwartete JSON-Format zu konvertieren. Ein Beispiel des erforderlichen JSON-Formats ist unten zu sehen:
{
"queries": [
{
"name": "List all AddKeyCredentialLink privileges for owned principals",
"description": "List all AddKeyCredentialLink privileges for owned principals - General",
"query": "MATCH p=(n {owned: true})-[r:AddKeyCredentialLink]->(m)\nRETURN p\nORDER BY n.name"
},
{
"name": "List all AddKeyCredentialLink privileges for Users, Domain Users, Authenticated Users, and Everyone groups",
"description": "List all AddKeyCredentialLink privileges for Users, Domain Users, Authenticated Users, and Everyone groups - General",
"query": "MATCH p=(n:Group)-[r:AddKeyCredentialLink]->(m)\nWHERE (n.objectid =~ \"(?i)S-1-5-21-.*-513\" OR n.objectid =~ \"(?i).*-S-1-5-11\" OR n.objectid =~ \"(?i).*-S-1-1-0\" OR n.objectid =~ \"(?i).*-S-1-5-32-545\")\nRETURN p\nORDER BY n.name"
}
]
}
Das vollständige Befehlsmenü ist unten dargestellt:
Documented commands (use 'help -v' for verbose/'help <topic>' for details):
======================================================================================================
alias Manage aliases
clear Clear the terminal.
cls Clear the terminal.
edit Run a text editor and optionally open a file with it
export Run a query and save its results
help List available commands or provide detailed help for a specific command
history View, run, edit, save, or clear previously entered commands
list List queries by group.
macro Manage macros
report Run multiple queries and generate a HTML report
run Execute a query
run_pyscript Run a Python script file inside the console
run_script Run commands in script file that is encoded as either ASCII or UTF-8 text
search Full-text search through stored queries.
set Set a dynamic search parameter (set <TARGET> <VALUE...>)
shell Execute a command as if at the OS prompt
shortcuts List available shortcuts
show Show dynamic search parameters
unset Unset a dynamic search parameter (unset <TARGET>)
Undocumented commands:
======================
exit q quit stop

Das Skript query-importer.py automatisiert den Import von Abfragen aus einer JSON-Datei in die BloodHound CE UI. bh_query_converter.py wurde ebenfalls bereitgestellt, um eine für die Terminalanwendung vorgesehene YAML-Datei in das von query-importer.py & BloodHound CE erwartete JSON-Format zu konvertieren.
Dieses Skript konvertiert eine für die Terminalanwendung vorgesehene YAML-Datei in eine JSON-Datei zum einfachen Import in BloodHound CE über das Skript query-importer.py. ad-queries.json wurde als Beispiel dafür bereitgestellt, wie eine Ausgabedatei aussieht, und ist bereit für query-importer.py sowie den Import der Abfragen in BloodHound CE.
Dieses Skript liest eine customqueries.json-Datei von BloodHound Legacy und importiert alle mit Ihren API-Anmeldedaten in die neue Version von BloodHound Community Edition. Es wird bereitgestellt, damit Abfragen, die Sie für BloodHound Legacy erstellt haben, weiterhin mit Community Edition verwendet werden können.
Dieses Skript löscht alle gespeicherten Abfragen aus BloodHound, um für zukünftige Importe zurückzusetzen. Es ist für BloodHound CE.
Dieses Skript liest eine Liste von Knotennamen aus einer .txt-Datei und markiert sie in der Datenbank entweder als owned (besessen) oder high-value (hochwertig).
Verwendung
Um das Skript zu verwenden, sollten Sie zwei Dateien bereithalten:
.txt-Datei mit Knotennamen im BloodHound-Format
[email protected][email protected]COMPUTER.DOMAIN.LOCALjson-Format mit Ihrem Neo4j-Benutzernamen, Passwort und Datenbank (Beispiel oben gezeigt)Das Skript hat die folgenden Optionen:
-h, --help show this help message and exit
-c CONFIG, --config CONFIG
Config file
-l LIST, --list LIST List of node names
-o, --owned Set target nodes as owned
-v, --high-value Set target nodes as high-value
Sie müssen mindestens -o oder -v angeben.
Dieses Skript importiert die gespeicherten Abfragen der SpecterOps BloodHoundQueryLibrary in BloodHound Community Edition unter Verwendung der BloodHound CE API.
Queries.json / Queries.zipQueries.json / Queries.zipplatforms (Groß-/Kleinschreibung wird ignoriert)/api/v2/saved-queries)429) unter Verwendung von Retry-After, falls vorhandenSpecterOps veröffentlicht
Queries.jsonundQueries.zipals Release-Artefakte (nicht im Repository gespeichert). Die Download-URLs für das neueste Release sind:
https://github.com/SpecterOps/BloodHoundQueryLibrary/releases/latest/download/Queries.jsonhttps://github.com/SpecterOps/BloodHoundQueryLibrary/releases/latest/download/Queries.zip
Verwendung (lokale Datei)
python3 scripts/bhql/query-importer.py \
--token-id "<TOKEN_ID>" \
--token-key "<TOKEN_KEY>" \
--queries-file "/path/to/Queries.json" \
--base-url "http://127.0.0.1:8080"
Verwendung (direkte URL)
python3 scripts/bhql/query-importer.py \
--token-id "<TOKEN_ID>" \
--token-key "<TOKEN_KEY>" \
--queries-url "https://github.com/SpecterOps/BloodHoundQueryLibrary/releases/latest/download/Queries.json" \
--base-url "http://127.0.0.1:8080"
Verwendung (automatisch: neuestes Release)
python3 scripts/bhql/query-importer.py \
--token-id "<TOKEN_ID>" \
--token-key "<TOKEN_KEY>" \
--bhql-latest \
--base-url "http://127.0.0.1:8080"
Plattformgefilterter Import (Beispiele)
# Nur Abfragen importieren, die Active Directory unterstützen
python3 scripts/bhql/query-importer.py \
--token-id "<TOKEN_ID>" \
--token-key "<TOKEN_KEY>" \
--bhql-latest \
--platforms "Active Directory" \
--base-url "http://127.0.0.1:8080"
# Abfragen für mehrere Plattformen importieren (jeder Treffer)
python3 scripts/bhql/query-importer.py \
--token-id "<TOKEN_ID>" \
--token-key "<TOKEN_KEY>" \
--bhql-latest \
--platforms "Active Directory" "Azure" \
--base-url "http://127.0.0.1:8080"
Tipp: Sie können in BloodHound CE einen Token erstellen und hier dessen Token-ID/Key verwenden. Wenn Sie vor dem Import „neu starten“ möchten, verwenden Sie das enthaltene Bereinigungsskript (siehe
scripts/bloodhound-ce/purge-queries.py).
Formatiere eine vorhandene BloodHound-Abfragen-YAML neu, so dass:
Falls Sie die CypherHound-Funktionalität nicht in das ursprüngliche DPAT-Repository integriert sehen, greifen Sie bitte auf meinen DPAT-Fork zu, der diese enthalten wird.
Dieses Skript parst einen Roh-Export aus der Terminalanwendung, insbesondere den Cypher zum Auflisten aller Benutzergruppenmitgliedschaften als Beispiel dafür, wie die Ausgabe dieses Tools geparst werden kann. Sie übergeben diesen Export als Parameter an das Skript, eine NTDS.dit-Datei und ein Ausgabeverzeichnis. Es erzeugt dann .txt-Dateien im Ausgabeverzeichnis für jeden Gruppennamen mit Einträgen im Format DOMAIN\USER, kompatibel mit DPAT. Sie übergeben dann dieses Verzeichnis mit dem Befehlszeilenargument -g an DPAT, sodass der Bediener gruppenspezifische Statistiken für jede Gruppe in einer Domäne erstellen kann.
Um das Skript zu verwenden, sollten Sie zwei Dateien bereithalten:
NTDS.dit-Datei mit Zeilen im folgenden Format: domain\user:RID:LMhash:NTLMhash:::Verwendung
usage: parse-memberships.py [-m MEMBERSHIPS_FILE] [-d DOMAIN] [-n NTDS_FILE] [-o OUTPUT_DIR] [--netbios NETBIOS] [--encoding ENCODING]
[--debug] [--no-index] [-h]
Map users to groups from memberships file and match against NTDS dump.
options:
-m, --memberships-file MEMBERSHIPS_FILE
Path to memberships file (BloodHound-style lines) (default: None)
-d, --domain DOMAIN FQDN domain (e.g., EXAMPLE.COM) used in the membership regex (default: None)
-n, --ntds-file NTDS_FILE
Path to NTDS dump (DOMAIN\user:hash or pwdump-style) (default: None)
-o, --output-dir OUTPUT_DIR
Directory to write per-group output files (default: None)
--netbios NETBIOS NETBIOS/short domain to prefix when NTDS lines lack a domain (pwdump) (default: None)
--encoding ENCODING Encoding for input files (default: cp1252)
--debug Enable verbose debug output (default: False)
--no-index Name group files after the group instead of numbered files (unsafe chars replaced) (default: False)
-h, --help Show this help message and exit
Dieses Skript parst den Roh-Export zum Auflisten aller kerberoastable Benutzer, gleicht die Benutzer mit Einträgen in einer NTDS.dit ab und erzeugt eine Ausgabedatei mit allen kerberoastable Benutzer-Hash-Einträgen aus dem Dump. Sie übergeben diese Ausgabedatei dann mit dem Flag -kz an DPAT, um Statistiken zu geknackten kerberoastable Konten bereitzustellen.
Verwendung
usage: parse-kerberoastable.py [-k KERB_FILE] [-n NTDS_FILE] [-d DOMAIN] [-o OUTPUT] [--encoding ENCODING] [--debug] [-h]
Match kerberoastable usernames against an NTDS.dit dump file
options:
-k, --kerb-file KERB_FILE
Path to Kerberoast output file (default: None)
-n, --ntds-file NTDS_FILE
Path to NTDS dump file (default: None)
-d, --domain DOMAIN Domain (e.g., EXAMPLE.COM) for regex matching (default: None)
-o, --output OUTPUT Path to write matches (default: None)
--encoding ENCODING File encoding to use when reading input files (default: cp1252)
--debug Enable verbose debug output (default: False)
-h, --help Show this help message and exit
Neo4j-Datenbank und URI verwendetBloodHound 4.3.1, bestimmte Kanten funktionieren nicht mit früheren VersionenAm 15. Juli 2023 habe ich beschlossen, einige Änderungen am Projekt vorzunehmen. Nach diesem Datum wird dieses Projekt immer eine Version hinter der privaten Version für Sponsoren zurückbleiben. Unterstützen Sie mich unbedingt, um Zugang zu den neuesten Cyphern, Funktionen und Fehlerbehebungen zu erhalten. Wenn Sie mich in dieser Stufe sponsern, erhalten Sie auch Zugang zu zusätzlichen privaten Repositorys, die ich nicht veröffentlicht habe!
Azure-Kanten hinzufügenBitte beschreiben Sie alle Probleme, die Sie öffnen, ausführlich und geben Sie nach Möglichkeit eine Ausgabe an (falls zutreffend).
| Key |
|---|
| Beschreibung |
|---|
group | Die Gruppe, zu der diese Abfrage gehört, Gruppen sind benutzerdefiniert, z.B. "general" |
desc | Die Beschreibung der Abfrage |
cypher | Die Abfrage selbst im Neo4j-Format |
msg_template | Jinja2-Vorlage für die Terminalausgabe basierend auf Cypher-Variablen, Aliase für Neo4j-Variablen verwenden, um zu vermeiden, dass Jinja versucht, sie als verschachtelte Variablen zu rendern |
| Param-Schlüssel | Beispielwert | Verwendung in Cypher |
|---|
params.user | [email protected] | = {{ params.user }} |
params.user_regex | (?i)john\.doe(@example\.com)? | =~ '{{ params.user_regex }}' |
params.group | Domain [email protected] | = {{ params.group }} |
params.prefix | ACME- | STARTS WITH {{ params.prefix }} |