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 ¶
const (
KeySourceAD byte = 0x00
)
KeySource values. 0x00 = created on/for AD.
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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)).