shadow

package
v1.0.30 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 22, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package shadow implements Certipy's "shadow" attack: manipulating the msDS-KeyCredentialLink attribute on a target user or computer account in Active Directory (Shadow Credentials, per Michael Grafnetter / @_dirkjan).

The package provides:

  • A codec for the KEYCREDENTIALLINK_BLOB binary format (MS-KPP §2.2.2) with the LDAP DNBinary wrapper used by msDS-KeyCredentialLink values.
  • A BCRYPT_RSAKEY_BLOB encoder/decoder used as the KeyMaterial payload for RSA public keys.
  • LDAP action helpers (Add / List / Info / Clear / Remove) that build or mutate KeyCredential entries and push them to the directory.

The command-line wrapper in cmd/certigo/shadow.go dispatches the various actions; the "auth" subcommand (separate) consumes the PFX produced by Add to perform PKINIT against the target principal.

Index

Constants

View Source
const (
	KeySourceAD byte = 0x00
)

KeySource values. 0x00 = created on/for AD.

View Source
const (
	KeyUsageNGC byte = 0x01
)

KeyUsage values per MS-KPP. 0x01 = NGC sign-in is what ShadowCredentials requires; Windows recognizes it for PKINIT pre-auth.

Variables

This section is empty.

Functions

func Add

func Add(opts Options) (string, error)

Add generates a new RSA 2048 key, builds a KeyCredential referencing the matching public key, appends the DNBinary-encoded blob to the target's msDS-KeyCredentialLink, and writes a self-signed cert + key PFX to OutPFX so the caller can follow up with PKINIT via `certigo auth -pfx`. It returns the DeviceID (lowercase hex without dashes) of the new entry.

func Clear

func Clear(opts Options) error

Clear removes ALL msDS-KeyCredentialLink values with a single LDAP REPLACE carrying an empty list - the canonical way to empty a multi-valued attribute.

func DecodeRSABcryptBlob

func DecodeRSABcryptBlob(blob []byte) (exponent int, modulus []byte, err error)

DecodeRSABcryptBlob parses a BCRYPT_RSAKEY_BLOB and returns the decoded public exponent (as an int) and the raw modulus bytes. Private-key material (Prime1 / Prime2 / etc.) is ignored - shadow credentials only carry the public key portion.

func EncodeRSABcryptBlob

func EncodeRSABcryptBlob(pub *rsa.PublicKey) []byte

EncodeRSABcryptBlob serializes a BCRYPT_RSAKEY_BLOB describing the public half of the supplied RSA key. The output is what Windows' msDS-Key- CredentialLink KeyMaterial entry carries (Identifier 3) for an RSA ShadowCredentials registration.

Layout:

Magic              (4 LE) = 0x31415352 "RSA1"
BitLength          (4 LE)
PublicExponentSize (4 LE)
ModulusSize        (4 LE)
Prime1Size         (4 LE) = 0 (public key)
Prime2Size         (4 LE) = 0
PublicExponent     (PublicExponentSize bytes, big-endian)
Modulus            (ModulusSize bytes, big-endian)

func Remove

func Remove(opts Options, deviceID string) error

Remove deletes the single msDS-KeyCredentialLink entry whose DeviceID matches the hex string deviceID. Dashes in the input are tolerated. Because AD does not let us delete individual values of a DNBinary multi-valued attribute by identifier, we read every value, parse it, and rewrite the attribute with REPLACE omitting the target.

Types

type KeyCredential

type KeyCredential struct {
	Version       uint32
	KeyID         []byte // 32 bytes - SHA-256 of the KeyMaterial (public-key blob).
	KeyHash       []byte // 32 bytes - SHA-256 over the serialized entries that follow.
	KeyMaterial   []byte // BCRYPT_RSAKEY_BLOB for RSA keys.
	KeyUsage      byte
	KeySource     byte
	DeviceID      [16]byte
	CustomKeyInfo []byte
	LastLogonTime time.Time // zero = unset
	CreationTime  time.Time
}

KeyCredential represents one decoded msDS-KeyCredentialLink entry.

func Info

func Info(opts Options) ([]*KeyCredential, error)

Info is List today - callers distinguish "info" by choosing a more verbose formatter. The signature matches the spec and leaves room for pulling decoded-KeyMaterial extras in the future.

func List

func List(opts Options) ([]*KeyCredential, error)

List fetches msDS-KeyCredentialLink for the target and decodes each value into a *KeyCredential.

func NewRSAKeyCredential

func NewRSAKeyCredential(pub *rsa.PublicKey) (*KeyCredential, error)

NewRSAKeyCredential builds a KeyCredential linking an RSA public key to a freshly-generated DeviceID, with CreationTime = time.Now().UTC(). The caller is expected to Marshal the result and append it to the target's msDS-KeyCredentialLink.

func ParseDNBinary

func ParseDNBinary(s string) (*KeyCredential, string, error)

ParseDNBinary decodes one msDS-KeyCredentialLink DNBinary value. It returns the parsed KeyCredential plus the owner DN suffix.

func UnmarshalBlob

func UnmarshalBlob(raw []byte) (*KeyCredential, error)

UnmarshalBlob decodes a KEYCREDENTIALLINK_BLOB. Unknown entry identifiers are skipped (forward-compatible).

func (*KeyCredential) MarshalBlob

func (k *KeyCredential) MarshalBlob() ([]byte, error)

MarshalBlob encodes the KeyCredential to the binary wire format (KEYCREDENTIALLINK_BLOB). The KeyHash is recomputed on each call so the caller need not populate it ahead of time.

func (*KeyCredential) MarshalDNBinary

func (k *KeyCredential) MarshalDNBinary(ownerDN string) string

MarshalDNBinary returns the LDAP DNBinary value for msDS-KeyCredentialLink. Format: "B:<hexlen>:<hex>:<owner-DN>" where hexlen is the number of hex characters (i.e. 2 * len(blob)).

type Options

type Options struct {
	Conn     *goldap.Conn
	TargetDN string
	OutPFX   string
	PFXPass  string
}

Options bundles the inputs shared by every shadow action.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL