This data set is intended to illustrate hybrid attack paths involving GitLab, on-premise Active Directory and Entra ID.
Ingest in this order:
- Active Directory data
- AzureHound collection
- GitLab base collection
- GitLab hybrid edges
Using Sysinternals AD Explorer a snapshot of the lab environment was taken and converted to LDIF:
$ ADExplorerSnapshot.py -m BOFHound -o logs ad-explorer-snapshot.dat
[08:00:40] INFO Server: dc.ludus.domain
INFO Time of snapshot: 2026-03-02T07:57:29
INFO Metadata offset: 0x27de4d
INFO Object count: 3624
INFO Parsed 1499 properties
[08:00:41] INFO Parsed 749 classes
INFO Parsed 3624 object offsets
Dumping objects ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:04
✓ Output written to dc.ludus.domain_1772434649_bofhound.log
Collect further ADIDNS data:
$ pyldapsearch -base-dn 'CN=MicrosoftDNS,DC=DomainDnsZones,DC=ludus,DC=domain' 'ludus.domain/domainadmin:password' '(objectclass=dnsnode)' -output logs/adidns.log
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
[*] pyldapsearch v0.1.7 - Tw1sm
[*] Binding to 10.10.10.11
[*] Distinguished name: CN=MICROSOFTDNS,DC=DOMAINDNSZONES,DC=LUDUS,DC=DOMAIN
[*] Filter: (objectclass=dnsnode)
--------------------
...
[*] Retrieved 34 results total
Convert the logs to BloodHound input data:
$ bofhound -i logs -o ad
_____________________________ __ __ ______ __ __ __ __ _______
| _ / / __ / | ____/| | | | / __ \ | | | | | \ | | | \
| |_) | | | | | | |__ | |__| | | | | | | | | | | \| | | .--. |
| _ < | | | | | __| | __ | | | | | | | | | | . ` | | | | |
| |_) | | `--' | | | | | | | | `--' | | `--' | | |\ | | '--' |
|______/ \______/ |__| |__| |___\_\________\_\________\|__| \___\|_________\
<< @coffeegist | @Tw1sm >>
[08:18:32] INFO Parsed 3657 LDAP objects
[08:18:32] INFO Parsed 0 local group/session objects
[08:18:32] INFO Sorting parsed objects by type...
[08:18:32] INFO Parsed 9 Users
[08:18:32] INFO Parsed 51 Groups
[08:18:32] INFO Parsed 3 Computers
[08:18:32] INFO Parsed 1 Domains
[08:18:32] INFO Parsed 0 Trust Accounts
[08:18:32] INFO Parsed 4 OUs
[08:18:32] INFO Parsed 205 Containers
[08:18:32] INFO Parsed 4 GPOs
[08:18:32] INFO Parsed 0 Enterprise CAs
[08:18:32] INFO Parsed 0 AIA CAs
[08:18:32] INFO Parsed 0 Root CAs
[08:18:32] INFO Parsed 0 NTAuth Stores
[08:18:32] INFO Parsed 0 Issuance Policies
[08:18:32] INFO Parsed 0 Cert Templates
[08:18:32] INFO Parsed 1768 Schemas
[08:18:32] INFO Parsed 1 Referrals
[08:18:32] INFO Parsed 3 DNS nodes
[08:18:32] INFO Parsed 1461 Unknown Objects
[08:18:32] INFO Parsed 0 Sessions
[08:18:32] INFO Parsed 0 Privileged Sessions
[08:18:32] INFO Parsed 0 Registry Sessions
[08:18:32] INFO Parsed 0 Local Group Memberships
[08:18:32] INFO Parsed 1825 ACL relationships
[08:18:32] INFO Created default users
[08:18:32] INFO Created default groups
[08:18:32] INFO Resolved group memberships
[08:18:32] INFO Resolved delegation relationships
[08:18:32] INFO Resolved OU memberships
[08:18:32] INFO Linked GPOs to OUs
[08:18:32] INFO Assigned IP addresses to computers
[08:18:33] INFO JSON files written to ad
Authenticate:
$ roadtx interactiveauth -u ... -p ... -t 925c2cd8-a177-41a5-93f3-1257ffd75334 -c 1950a258-227b-4e31-a9cf-717495945fc2 -r https://graph.microsoft.com
To get a refresh token:
$ jq .refreshToken < .roadtools_auth
Run AzureHound:
$ azurehound -r ... -t 925c2cd8-a177-41a5-93f3-1257ffd75334 list -o azurehound.json
Set credentials:
export BLOODHOUND_USERNAME=api
export BLOODHOUND_PASSWORD=...
export GITLAB_URL=https://git.pwn.gift
export GITLAB_TOKEN=glpat-...
Collect GitLab data:
gitlabhound collect > gitlab.json
Ingest the data into BloodHound and enrich the data by creating hybrid edges:
gitlabhound enrich > gitlab-enrichment.json
Search repositories and their history for credentials using trufflehog:
trufflehog gitlab --token=$GITLAB_TOKEN --no-verification --json --repo=https://git.pwn.gift/alice/config.git > trufflehog.json
Search job logs and build artifacts for credentials using pipeleek:
pipeleek gl scan -g https://git.pwn.gift -t $GITLAB_TOKEN --artifacts --repo alice/config --json --logfile pipeleek.json
Map the detected secrets to GitLab resources present in the graph:
gitlabhound enrich secrets trufflehog.json pipeleek.json > gitlab-enrichment-secrets.json