

GitHound è un collector OpenGraph di BloodHound per GitHub, progettato per mappare la struttura e le autorizzazioni della tua organizzazione in un grafico di percorsi di attacco navigabile. Esso:
Modella le Entità Chiave di GitHub
Visualizza e Analizza in BloodHound
Con GitHound ottieni un grafico chiaro e interattivo del panorama delle autorizzazioni GitHub—perfetto per revisioni di sicurezza, audit di conformità e rapide indagini sugli incidenti.
Per la documentazione dettagliata, consulta BloodHound Docs - GitHound.
# 1. Load the collector
. ./githound.ps1
# 2. Create a session with your Personal Access Token
$session = New-GitHubSession -OrganizationName "YourOrgName" -Token (Get-Clipboard)
# 3. Run the collection
Invoke-GitHound -Session $session
# 4. Upload the resulting githound_<orgId>.json file to BloodHound
Se la raccolta viene interrotta, riprendi da dove eri rimasto:
Invoke-GitHound -Session $session -Resume
GitHound supporta sia le sessioni con Personal Access Token sia le sessioni di installazione GitHub App. Il flusso di lavoro esistente per GitHub App con ambito organizzazione è invariato:
. ./githound.ps1
$session = New-GitHubJwtSession `
-OrganizationName "YourOrgName" `
-ClientId $clientId `
-PrivateKeyPath $privateKeyPath `
-InstallationId $installationId
Invoke-GitHound -Session $session -CollectAll
La stessa funzione può anche creare sessioni abilitate per l'enterprise:
. ./githound.ps1
$session = New-GitHubJwtSession `
-EnterpriseName "YourEnterpriseSlug" `
-ClientId $clientId `
-PrivateKeyPath $privateKeyPath `
-InstallationId $installationId `
-PersonalAccessToken $pat
Le sessioni abilitate per l'enterprise mantengono più contesti di autenticazione sulla GitHound.Session restituita:
Headers: gli header del token di installazione della GitHub App usati per la raccolta normaleJwtHeaders: gli header JWT della GitHub App usati per gli endpoint a livello di app, come l'enumerazione delle installazioniPatHeaders: header opzionali del Personal Access Token per i percorsi di raccolta che richiedono l'autenticazione con token utentePer enumerare le installazioni che appartengono alla GitHub App autenticata:
Get-GitHubAppInstallation -Session $session |
Select-Object TargetType, InstallationId, Login, Name, SuspendedAt
Il parsing dei workflow è ora integrato in Invoke-GitHound quando usi -CollectAll. Il collector:
GH_Workflow grezzi e i contenuti dei workflowGH_WorkflowJob e GH_WorkflowStepGH_CanPwnRequest e GH_CanDispatchTogithound_<orgId>.jsonPer scopi di ripresa/debug, il checkpoint intermedio dell'analisi dei workflow viene scritto come githound_WorkflowAnalysis_<orgId>.json.
GitHound ora include una base minima di raccolta enterprise tramite Git-HoundEnterprise. Questo collector attualmente crea:
GH_EnterpriseGH_Organization per le organizzazioni membroGH_Contains dall'enterprise alle sue organizzazioniLa raccolta degli utenti enterprise tramite Git-HoundEnterpriseUser aggiunge:
GH_UserGH_HasMember dall'enterprise a quegli utentiLa raccolta SAML enterprise tramite Git-HoundEnterpriseSamlProvider aggiunge:
GH_SamlIdentityProviderGH_ExternalIdentityGH_HasSamlIdentityProvider dall'enterprise al providerQuesto percorso richiede una sessione basata su PAT perché GitHub espone il SAML enterprise tramite enterprise.ownerInfo.
La raccolta dei team enterprise tramite Git-HoundEnterpriseTeam aggiunge:
GH_EnterpriseTeamGH_AssignedTo dai team enterprise alle organizzazioni assegnateGH_MemberOf dai team enterprise ai nodi GH_Team ent: visibili all'org usando il matching delle proprietàmembers dei team enterprise e archi GH_HasRole dagli utenti a questi ruoliLa raccolta dei ruoli enterprise tramite Git-HoundEnterpriseRole aggiunge:
GH_EnterpriseRoleGH_Contains dall'enterprise a questi ruoliGH_HasRole dagli utenti assegnati direttamente e dai team enterpriseowners predefinito popolato da enterprise.ownerInfo.admins quando i dati admin enterprise basati su PAT sono disponibiliPer ora, le stringhe grezze delle autorizzazioni enterprise sono conservate sul nodo GH_EnterpriseRole nella sua proprietà permissions invece di essere espanse in archi di autorizzazione dedicati.
La raccolta SCIM enterprise attualmente aggiunge:
SCIM_UserSCIM_GroupSCIM_Provisioned da SCIM_User a GH_ExternalIdentitySCIM_Provisioned da SCIM_Group a GH_EnterpriseTeam quando GitHub espone il group_id del team enterpriseSCIM_MemberOf da SCIM_User a SCIM_GroupQuesto offre a GitHound un ponte indipendente dal provider dallo schema SCIM condiviso al modello nativo di identità e team enterprise di GitHub.
Quando un GH_SamlIdentityProvider raccolto identifica l'IdP a monte, GitHound può anche aggiungere archi di correlazione SCIM consapevoli del provider nell'output sidecar SCIM:
Okta_User -> SCIM_User
Okta_User.id = SCIM_User.externalIdOkta_Group -> SCIM_Group
Okta_Group.name = SCIM_Group.externalIdOkta_Group.oktaDomain = GH_SamlIdentityProvider.foreign_environmentidGitHound mantiene il layer SCIM nel proprio output sidecar, così queste mappature restano visibili senza mescolare i nodi nativi SCIM nel grafico enterprise principale nativo di GitHub:
githound_<entId>.json contiene i dati enterprise nativi di GitHubgithound_scim_<entId>.json contiene i nodi nativi SCIM e gli archi ponte SCIMgithound_saml_<entId>.json contiene i dati SAML e delle identità esternegithound_hybrid_<entId>.json contiene gli archi tra modelli come SAML_Implements, SAML_HasAccount e GH_SyncedTogithound_saml_<entId>.json contiene anche la topologia SAML normalizzata per il service provider GitHub, inclusi SAML_TrustsIssuer e SAML_HasAssertionConsumerServiceIl modello nativo del provider di identità GitHub rimane intatto negli output nativi GitHub/SAML:
GH_ExternalIdentityGH_HasExternalIdentityGH_MapsToUserIl layer SAML normalizzato in githound_hybrid_<entId>.json ora colloca SAML_HasAccount direttamente su GH_User, derivando match_values dalle proprietà SAML della GH_ExternalIdentity collegata, come saml_identity_name_id e saml_identity_username.
Gli stub GH_Organization emessi dalla raccolta enterprise sono intenzionalmente marcati collected = false. Rappresentano la scoperta strutturale dal contesto enterprise e sono destinati a essere arricchiti in seguito dalla normale raccolta delle organizzazioni.
Per un'orchestrazione enterprise-first, Invoke-GitHoundEnterprise raccoglie i dati supportati con ambito enterprise, enumera le installazioni delle organizzazioni correlate e poi esegue il flusso di lavoro esistente Invoke-GitHound per ogni organizzazione nella propria sottodirectory sotto il percorso di checkpoint scelto.
Esempio:
$session = New-GitHubJwtSession `
-EnterpriseName "your-enterprise-slug" `
-ClientId $clientId `
-PrivateKeyPath $privateKeyPath `
-InstallationId $enterpriseInstallationId `
-PersonalAccessToken $pat
Invoke-GitHoundEnterprise -Session $session -CheckpointPath "./output/your-enterprise" -CollectAll
Per testare solo l'enterprise senza enumerare le organizzazioni correlate:
Invoke-GitHoundEnterprise -Session $session -CheckpointPath "./output/your-enterprise" -EnterpriseOnly

Per la documentazione dettagliata, consulta BloodHound Docs - GitHound Schema.
Principali categorie di archi:
Principale pattern di percorso di attacco:
(:GH_User)-[:GH_HasRole|GH_MemberOf|GH_AddMember*1..]->(:GH_RepoRole)-[:GH_AdminTo|GH_CanPush]->(:GH_Repository)
Trova l'identificatore dell'oggetto per il tuo utente target:
MATCH (n:GH_User)
RETURN n
SUGGERIMENTO: Seleziona Table Layout
https://github.com/user-attachments/assets/1ddfd075-2a15-4aa9-bad7-74c43e6c82d6
Sostituisci il valore <object_id> nella query successiva con l'identificatore dell'oggetto dell'utente:
MATCH p = (:GH_User {objectid:"<object_id>"})-[:GH_MemberOf|GH_AddMember|GH_HasRole|GH_HasBaseRole|GH_Owns*1..]->(:GH_RepoRole)-[:GH_WriteRepoContents]->(:GH_Repository)
RETURN p

Ottieni l'identificatore dell'oggetto per il tuo repository target:
MATCH (n:GH_Repository)
RETURN n
Prendi l'identificatore dell'oggetto per il tuo repository target e sostituiscilo al valore <object_id> nella query successiva:
MATCH p = (:GH_User)-[:GH_MemberOf|GH_HasRole|GH_HasBaseRole|GH_Owns|GH_AddMember*1..]->(:GH_RepoRole)-[:GH_WriteRepoContents]->(:GH_Repository {objectid:"<object_id>"})
RETURN p

MATCH p = (:GH_User)-[:GH_HasRole|GH_HasBaseRole]->(:GH_OrgRole {short_name: "owners"})
RETURN p

MATCH p = (:AZUser)-[:GH_SyncedTo]->(:GH_User)
RETURN p

Trova le entità GitHub che possono assumere identità federate Azure (relazioni di trust OIDC):
// All GitHub → Azure OIDC attack paths
MATCH p = (:GH_Repository|GH_Branch|GH_Environment)-[:GH_CanAssumeIdentity]->(:AZFederatedIdentityCredential)
RETURN p
// Users with paths to Azure via GitHub Actions
MATCH p = (:GH_User)-[:GH_HasRole|GH_MemberOf|GH_AddMember*1..]->(:GH_RepoRole)-[:GH_CanPush]->(:GH_Repository)-[:GH_CanAssumeIdentity]->(:AZFederatedIdentityCredential)
RETURN p
MATCH p = (:GH_Repository)-[:GH_HasSecret]->(:GH_OrgSecret)
RETURN p
MATCH p = (:GH_Repository)-[:GH_Contains]->(:GH_SecretScanningAlert)
RETURN p
Apprezziamo e accogliamo con piacere i tuoi contributi! Per rendere il processo fluido ed efficiente, segui questi passaggi:
Discuti la Tua Idea
Fork & Crea un Branch
Fai il fork di questo repository nel tuo account.
Crea un branch tematico per il tuo lavoro:
git checkout -b feat/my-new-feature
Implementa & Testa
Segui lo stile e i pattern esistenti nel repo.
Aggiungi o aggiorna test/esempi per coprire le tue modifiche.
Verifica che il tuo codice funzioni come previsto:
# e.g. dot-source the collector and run it, or load the model.json in BloodHound
Invia una Pull Request
Fai push del tuo branch sul tuo fork:
git push origin feat/my-new-feature
Apri una Pull Request verso il branch main di questo repository.
Nella descrizione della PR, includi:
Revisione & Merge
Grazie per aver contribuito a migliorare questa estensione! 🎉
Copyright 2025 Jared Atkinson
Licensed under the Apache License, Version 2.0
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Salvo diversa indicazione da un file LICENSE di livello inferiore o da un'intestazione di licenza, tutti i file in questo repository sono rilasciati sotto la licenza Apache-2.0. Una copia completa della licenza è disponibile nel file LICENSE nella directory principale.
| Categoria | Archi Chiave | Descrizione |
|---|
| Contenimento | GH_Contains, GH_Owns | Gerarchia organizzativa |
| Assegnazione dei Ruoli | GH_HasRole, GH_MemberOf, GH_HasBaseRole | Chi ha quali ruoli |
| Autorizzazioni dei Repository | GH_AdminTo, GH_CanPush, GH_CanPull | Cosa possono fare i ruoli |
| Protezioni dei Branch | GH_BypassPullRequestAllowances, GH_RestrictionsCanPush | Accesso a livello di branch |
| Segreti | GH_HasSecret | Mappatura degli accessi ai segreti |
| Cross-Cloud | GH_CanAssumeIdentity, GH_SyncedTo | Percorsi di attacco verso Azure/AWS |