Documentation
¶
Overview ¶
Package forge implements the "Golden Certificate" attack: minting arbitrary X.509 certificates signed by a compromised Certificate Authority (CA) private key.
forge mirrors Certipy's forge subcommand (see certipy/commands/forge.py). Given a CA PFX, it produces a new RSA keypair and certificate bound to an attacker-chosen UPN / DNS / AD SID, signed by the CA. The resulting certificate authenticates to AD CS-backed services (PKINIT, Schannel) as the impersonated user.
The most important Microsoft extension emitted by forge is the NTDS-CA-Security-Ext (OID 1.3.6.1.4.1.311.25.2), which binds a certificate to a specific AD SID. Since Windows 2022, StrongCertificateBindingEnforcement requires this extension for certificate-based AD authentication to succeed when the UPN does not already match the target account.
Index ¶
- Variables
- func CRLDistributionExt(urls []string) (pkix.Extension, error)
- func CertificatePoliciesExt(templateOIDs []string) (pkix.Extension, error)
- func Forge(opts Options) (*pki.Certificate, error)
- func NTDSCASecurityExt(sid string) ([]byte, error)
- func UPNSANExtension(upns []string, dnsNames []string) (pkix.Extension, error)
- type Options
Constants ¶
This section is empty.
Variables ¶
var ( // OIDNTDSCASecurityExt is the Microsoft szOID_NTDS_CA_SECURITY_EXT, // used to bind a certificate to an AD SID. Required for modern Windows // AD CS (2022+) strong certificate binding enforcement. OIDNTDSCASecurityExt = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 25, 2} // OIDNTDSObjectSID is the inner OID embedded inside the NTDS security // extension's AnotherName structure. OIDNTDSObjectSID = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 25, 2, 1} // OIDUPNSAN is the Microsoft otherName OID for userPrincipalName // entries in a subjectAltName (RFC 4556 PKINIT / MS-WCCE). OIDUPNSAN = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 20, 2, 3} // OIDExtSubjectAltName is 2.5.29.17 (RFC 5280). OIDExtSubjectAltName = asn1.ObjectIdentifier{2, 5, 29, 17} // OIDExtCRLDistributionPoints is 2.5.29.31 (RFC 5280). OIDExtCRLDistributionPoints = asn1.ObjectIdentifier{2, 5, 29, 31} // OIDExtCertificatePolicies is 2.5.29.32 (RFC 5280). OIDExtCertificatePolicies = asn1.ObjectIdentifier{2, 5, 29, 32} // OIDExtExtendedKeyUsage is 2.5.29.37 (RFC 5280). OIDExtExtendedKeyUsage = asn1.ObjectIdentifier{2, 5, 29, 37} )
Microsoft and PKIX extension OIDs used when forging AD CS certificates.
Functions ¶
func CRLDistributionExt ¶
CRLDistributionExt builds a cRLDistributionPoints extension (OID 2.5.29.31) with one DistributionPoint per URL, each of which carries a single URI-form GeneralName. Returns a zero-value Extension when urls is empty.
func CertificatePoliciesExt ¶
CertificatePoliciesExt builds a certificatePolicies extension (OID 2.5.29.32) with one policyIdentifier per supplied OID string, each with no qualifiers. Returns a zero-value Extension when templateOIDs is empty.
func Forge ¶
func Forge(opts Options) (*pki.Certificate, error)
Forge produces a new *pki.Certificate (cert + freshly-generated RSA key) signed by opts.CA. Caller saves via pki.SavePFX.
func NTDSCASecurityExt ¶
NTDSCASecurityExt returns the DER-encoded extension value for OID 1.3.6.1.4.1.311.25.2 binding the certificate to sid (an AD SID string, e.g. "S-1-5-21-1-2-3-500").
The value is encoded as a GeneralNames SEQUENCE with a single [0] otherName entry whose AnotherName wraps the SID ASCII as an OCTET STRING:
SEQUENCE { -- GeneralNames
[0] IMPLICIT { -- otherName (AnotherName)
OID 1.3.6.1.4.1.311.25.2.1
[0] EXPLICIT OCTET STRING <sid ascii>
}
}
This matches Certipy's certipy/commands/forge.py create_sid_extension().
func UPNSANExtension ¶
UPNSANExtension builds a SubjectAltName extension (OID 2.5.29.17) containing one otherName entry per upn (OID 1.3.6.1.4.1.311.20.2.3) plus any dnsNames. Returns an empty pkix.Extension (zero Id) when both slices are empty, so callers can skip when there is nothing to emit.
Types ¶
type Options ¶
type Options struct {
CA *pki.Certificate
Subject pkix.Name
UPN string
DNSNames []string
SID string
SerialHex string // empty = random 16 bytes
CRLs []string // CRL distribution URLs
TemplateOIDs []string
ExtraExts []pkix.Extension
ValidityDays int // default 3650
KeySize int // default 2048
}
Options controls certificate forging. A nil CA is invalid; an empty SID simply omits the NTDS-CA-Security-Ext extension.