mirror of
https://github.com/ssteelfactor-oss/Kestrel
synced 2026-08-09 13:10:08 +00:00
update 25.07.2026 20:53:09,45
This commit is contained in:
@@ -7,11 +7,11 @@
|
||||
|
||||
> ### BloodHound shows you the path. Kestrel shows you what's already inside.
|
||||
|
||||
Everyone maps the same thing: the attack path — *who can reach Domain Admin.* It's the right question, and the tools that answer it are excellent. But a graph of "who can reach whom" is blind to an entire class of problem, because some of the worst things in an Active Directory aren't a path at all.
|
||||
Everyone maps the same thing: the attack path - *who can reach Domain Admin.* It's the right question, and the tools that answer it are excellent. But a graph of "who can reach whom" is blind to an entire class of problem, because some of the worst things in an Active Directory aren't a path at all.
|
||||
|
||||
They're a backdoor welded into an attribute. A certificate that keeps authenticating long after the password is reset. A permission stamped into the schema itself, so every object created from now on inherits it silently. A deleted account someone quietly kept the right to bring back. An object hidden from enumeration by a single deny-read ACE.
|
||||
|
||||
**None of that is an edge in a graph. All of it is sitting in your directory right now.** Kestrel reads it — with native Windows calls, ordinary domain-user rights, no server, no Python, no agent, and a footprint on the domain controller so restrained it's [documented event-by-event](FOOTPRINT.md).
|
||||
**None of that is an edge in a graph. All of it is sitting in your directory right now.** Kestrel reads it - with native Windows calls, ordinary domain-user rights, no server, no Python, no agent, and a footprint on the domain controller so restrained it's [documented event-by-event](FOOTPRINT.md).
|
||||
|
||||
One `.exe`. One command. Everything below.
|
||||
|
||||
@@ -19,11 +19,11 @@ One `.exe`. One command. Everything below.
|
||||
|
||||
## You've been looking the wrong way
|
||||
|
||||
The offensive AD ecosystem — SharpHound, impacket, Certipy, and the graph behind them — is superb, and it all looks at the same surface: reachability. Kestrel looks at the three dimensions that surface can't express.
|
||||
The offensive AD ecosystem - SharpHound, impacket, Certipy, and the graph behind them - is superb, and it all looks at the same surface: reachability. Kestrel looks at the three dimensions that surface can't express.
|
||||
|
||||
- **Time.** A graph is a snapshot. Kestrel reads replication metadata — *when* a Tier-0 attribute changed and *which DC* originated it. A DCSync right granted last night is not the same finding as one that's been there for years, and only one of them means you're being attacked right now.
|
||||
- **Time.** A graph is a snapshot. Kestrel reads replication metadata - *when* a Tier-0 attribute changed and *which DC* originated it. A DCSync right granted last night is not the same finding as one that's been there for years, and only one of them means you're being attacked right now.
|
||||
- **Persistence in an attribute, not an edge.** Shadow credentials, SID history, reanimate-tombstones, schema `defaultSecurityDescriptor` backdoors, hidden objects, `OWNER RIGHTS` deny-ACEs, AD FS DKM keys. The graph tools don't collect these because there's no edge to draw.
|
||||
- **Defensive posture, inverted.** Not "who can attack," but "what isn't protected" — the Tier-0 account outside its silo, the sync account with a random RID that nobody tagged, the lockout policy that never throttles a spray.
|
||||
- **Defensive posture, inverted.** Not "who can attack," but "what isn't protected" - the Tier-0 account outside its silo, the sync account with a random RID that nobody tagged, the lockout policy that never throttles a spray.
|
||||
|
||||
It's not that Kestrel is faster than a graph. It answers questions the graph can't ask.
|
||||
|
||||
@@ -33,14 +33,14 @@ It's not that Kestrel is faster than a graph. It answers questions the graph can
|
||||
|
||||
| Sin | What Kestrel finds | Flag(s) |
|
||||
|-----|-------------------|---------|
|
||||
| **Replication & delegation** | DCSync rights (who *can* replicate — without ever replicating), unconstrained / constrained / RBCD / S4U delegation | `--acl` · `--delegation` |
|
||||
| **Certificate abuse** | AD CS ESC1–5/9, rogue CA in the NTAuth store, long-lived cert persistence, **AD FS DKM key ACL — the Golden SAML precondition** | `--adcs` · `--adfs` |
|
||||
| **Replication & delegation** | DCSync rights (who *can* replicate - without ever replicating), unconstrained / constrained / RBCD / S4U delegation | `--acl` · `--delegation` |
|
||||
| **Certificate abuse** | AD CS ESC1–5/9, rogue CA in the NTAuth store, long-lived cert persistence, **AD FS DKM key ACL - the Golden SAML precondition** | `--adcs` · `--adfs` |
|
||||
| **Persistence in attributes** | Shadow credentials, SID history injection, **tombstone-reanimation rights**, **hidden objects**, **schema `defaultSecurityDescriptor` backdoors**, orphaned `adminCount` | `--shadowcreds` · `--sidhistory` · `--acl` · `--schema` · `--adminsdholder` |
|
||||
| **Cleartext & crackable creds** | GPP `cpassword`, `unattend`/`sysprep` secrets and script passwords across SYSVOL, Kerberoastable and AS-REP-roastable accounts, LAPS coverage gaps | `--gpp` · `--roast` · `--laps` |
|
||||
| **Cross-domain & hybrid** | Foreign principals in privileged groups, **Entra Connect sync accounts tagged Tier-0**, trust posture, **machine accounts created via MachineAccountQuota** (`mS-DS-CreatorSID`) | `--groups` · `--trust` · `--machines` |
|
||||
| **Posture & recon** | Password / PSO policy, `krbtgt` age, LLMNR / NBT-NS / WDigest / NTLMv1 GPO settings, gMSA readers, stale computers, delegation topology | `--pwdpolicy` · `--policy` · `--gmsa` · `--stale` |
|
||||
|
||||
Twenty-plus checks that are usually spread across a dozen scripts and two languages. Here they're one binary — and they end in a single, severity-sorted verdict.
|
||||
Twenty-plus checks that are usually spread across a dozen scripts and two languages. Here they're one binary - and they end in a single, severity-sorted verdict.
|
||||
|
||||
---
|
||||
|
||||
@@ -53,13 +53,13 @@ Kestrel.exe --all --report audit.html
|
||||
Run everything. Get the full HTML report. And, at the very end of the console, the part that matters:
|
||||
|
||||
```
|
||||
═══ Kestrel — Prioritized Findings ═══
|
||||
═══ Kestrel - Prioritized Findings ═══
|
||||
|
||||
CRITICAL DCSync CORP\svc_sql — non-default principal can replicate directory changes (DCSync)
|
||||
CRITICAL DCSync CORP\svc_sql - non-default principal can replicate directory changes (DCSync)
|
||||
→ fix: remove GetChanges/GetChangesAll from the principal on the domain head (dsacls) unless it is a DC
|
||||
CRITICAL AD FS CN=... — read access to the DKM key (Golden SAML precondition)
|
||||
CRITICAL AD FS CN=... - read access to the DKM key (Golden SAML precondition)
|
||||
→ fix: remove non-default read ACEs on the DKM object (dsacls) and rotate the token-signing certificate
|
||||
HIGH Persistence CN=... — object hidden from enumeration via a broad deny-read ACE
|
||||
HIGH Persistence CN=... - object hidden from enumeration via a broad deny-read ACE
|
||||
→ fix: inspect the hidden object and remove the broad deny-read ACE (dsacls)
|
||||
|
||||
[=] 2 critical · 1 high · 0 medium · 0 low
|
||||
@@ -71,19 +71,19 @@ Not a wall of output. The findings that matter, ranked, each with the command to
|
||||
|
||||
## One exe. Red, blue, purple.
|
||||
|
||||
- **Red / grey** — enumerate persistence and delegation the graph misses, export straight to BloodHound CE OpenGraph (`--opengraph`) to fuse with your existing collection, or pivot from any principal (`--from`).
|
||||
- **Blue** — a prioritized, remediated findings list; a `--diff` against last week's snapshot to catch what *changed*; and a tool whose exact detection footprint is published so you can whitelist it and tune your own alerting around it.
|
||||
- **Purple** — one artifact both sides read the same way. Red finds it, blue fixes it, everyone points at the same line number.
|
||||
- **Red / grey** - enumerate persistence and delegation the graph misses, export straight to BloodHound CE OpenGraph (`--opengraph`) to fuse with your existing collection, or pivot from any principal (`--from`).
|
||||
- **Blue** - a prioritized, remediated findings list; a `--diff` against last week's snapshot to catch what *changed*; and a tool whose exact detection footprint is published so you can whitelist it and tune your own alerting around it.
|
||||
- **Purple** - one artifact both sides read the same way. Red finds it, blue fixes it, everyone points at the same line number.
|
||||
|
||||
## Detectable by design
|
||||
|
||||
Kestrel is read-only. It never writes to the directory, never replicates, never needs `SeSecurityPrivilege`, never touches the cloud. Reading *who can* DCSync looks nothing, on the wire, like *doing* DCSync — no DRSUAPI, no replication-signature `4662`. Every query it runs and every event it can (and cannot) generate is catalogued in **[FOOTPRINT.md](FOOTPRINT.md)**. An auditor that tells the defender exactly how to catch it isn't a contradiction — it's the whole point.
|
||||
Kestrel is read-only. It never writes to the directory, never replicates, never needs `SeSecurityPrivilege`, never touches the cloud. Reading *who can* DCSync looks nothing, on the wire, like *doing* DCSync - no DRSUAPI, no replication-signature `4662`. Every query it runs and every event it can (and cannot) generate is catalogued in **[FOOTPRINT.md](FOOTPRINT.md)**. An auditor that tells the defender exactly how to catch it isn't a contradiction - it's the whole point.
|
||||
|
||||
---
|
||||
|
||||
## Quick start
|
||||
|
||||
**Grab a build.** Every green CI run publishes a `Kestrel.exe` artifact — download it from the [Actions tab](https://github.com/ssteelfactor-oss/Kestrel/actions), no toolchain required.
|
||||
**Grab a build.** Every green CI run publishes a `Kestrel.exe` artifact - download it from the [Actions tab](https://github.com/ssteelfactor-oss/Kestrel/actions), no toolchain required.
|
||||
|
||||
**Or build it yourself.** Visual Studio (v143+) or MSBuild:
|
||||
|
||||
@@ -93,7 +93,7 @@ cd Kestrel
|
||||
msbuild Kestrel.vcxproj /p:Configuration=Release /p:Platform=x64
|
||||
```
|
||||
|
||||
Pure C, zero third-party dependencies. Build `/MT` and it's a single self-contained executable — drop it on a domain-joined host, run as any ordinary user.
|
||||
Pure C, zero third-party dependencies. Build `/MT` and it's a single self-contained executable - drop it on a domain-joined host, run as any ordinary user.
|
||||
|
||||
**Run it.**
|
||||
|
||||
@@ -126,7 +126,7 @@ Run `--all`, or select any subset. Full help: `Kestrel.exe --help`.
|
||||
| `--shadowcreds` | Shadow credentials (`msDS-KeyCredentialLink`) |
|
||||
| `--sidhistory` | `sIDHistory` injection (privileged / foreign) |
|
||||
| `--adminsdholder` | Orphaned `adminCount=1` objects |
|
||||
| `--gpp` | SYSVOL secret sweep — GPP `cpassword`, `unattend`, script creds |
|
||||
| `--gpp` | SYSVOL secret sweep - GPP `cpassword`, `unattend`, script creds |
|
||||
| `--gpolateral` | GPO local-group → lateral edges (AdminTo / CanRDP / CanPSRemote / ExecuteDCOM) |
|
||||
| `--policy` | GPO security policy (LLMNR / NBT-NS / WDigest / NTLMv1) |
|
||||
| `--pwdpolicy` | Password / PSO policy · `krbtgt` age · MachineAccountQuota |
|
||||
@@ -143,15 +143,15 @@ Run `--all`, or select any subset. Full help: `Kestrel.exe --help`.
|
||||
|
||||
## Design invariants
|
||||
|
||||
These are promises, not preferences — the reasons it's safe to run in production. Breaking any of them is a security bug (see [SECURITY.md](SECURITY.md)).
|
||||
These are promises, not preferences - the reasons it's safe to run in production. Breaking any of them is a security bug (see [SECURITY.md](SECURITY.md)).
|
||||
|
||||
- **Read-only** — never creates, modifies, or deletes a directory object. Only read/access events, never modification events.
|
||||
- **Ordinary domain user** — no privilege escalation, no `SeSecurityPrivilege`, DACL-only security masks.
|
||||
- **No replication** — detects who *can* DCSync; never calls DRSUAPI itself.
|
||||
- **Directory & SYSVOL only** — no RPC/SMB against member hosts.
|
||||
- **No evasion** — no query fragmentation, no timing games, no log tampering. See [FOOTPRINT.md](FOOTPRINT.md).
|
||||
- **On-prem only** — no Entra / Graph / cloud calls; it audits the footprint hybrid leaves *in AD*.
|
||||
- **Native & self-contained** — pure C, zero third-party dependencies, single `.exe`.
|
||||
- **Read-only** - never creates, modifies, or deletes a directory object. Only read/access events, never modification events.
|
||||
- **Ordinary domain user** - no privilege escalation, no `SeSecurityPrivilege`, DACL-only security masks.
|
||||
- **No replication** - detects who *can* DCSync; never calls DRSUAPI itself.
|
||||
- **Directory & SYSVOL only** - no RPC/SMB against member hosts.
|
||||
- **No evasion** - no query fragmentation, no timing games, no log tampering. See [FOOTPRINT.md](FOOTPRINT.md).
|
||||
- **On-prem only** - no Entra / Graph / cloud calls; it audits the footprint hybrid leaves *in AD*.
|
||||
- **Native & self-contained** - pure C, zero third-party dependencies, single `.exe`.
|
||||
|
||||
---
|
||||
|
||||
@@ -172,18 +172,18 @@ These are promises, not preferences — the reasons it's safe to run in producti
|
||||
|
||||
## Documentation
|
||||
|
||||
- **[FOOTPRINT.md](FOOTPRINT.md)** — the exact LDAP / SYSVOL trace each scan leaves, and the DC events it does (and can't) generate.
|
||||
- **[SECURITY.md](SECURITY.md)** — reporting, scope, and the design invariants as verifiable guarantees.
|
||||
- **[LICENSE](LICENSE)** — Apache 2.0.
|
||||
- **[FOOTPRINT.md](FOOTPRINT.md)** - the exact LDAP / SYSVOL trace each scan leaves, and the DC events it does (and can't) generate.
|
||||
- **[SECURITY.md](SECURITY.md)** - reporting, scope, and the design invariants as verifiable guarantees.
|
||||
- **[LICENSE](LICENSE)** - Apache 2.0.
|
||||
|
||||
## Related
|
||||
|
||||
Parent project: [NetEnum](https://github.com/ssteelfactor-oss/NetEnum) — AD enumeration via ADSI / COM / LDAP.
|
||||
Parent project: [NetEnum](https://github.com/ssteelfactor-oss/NetEnum) - AD enumeration via ADSI / COM / LDAP.
|
||||
|
||||
## Author
|
||||
|
||||
[@ssteelfactor-oss](https://github.com/ssteelfactor-oss) — security research and COM / Windows internals.
|
||||
[@ssteelfactor-oss](https://github.com/ssteelfactor-oss) - security research and COM / Windows internals.
|
||||
|
||||
## License
|
||||
|
||||
Licensed under the **Apache License 2.0** — see [LICENSE](LICENSE). Provided "as is", without warranty; run it only against directories you're authorised to audit.
|
||||
Licensed under the **Apache License 2.0** - see [LICENSE](LICENSE). Provided "as is", without warranty; run it only against directories you're authorised to audit.
|
||||
|
||||
Reference in New Issue
Block a user