forge

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: 10 Imported by: 0

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

Constants

This section is empty.

Variables

View Source
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

func CRLDistributionExt(urls []string) (pkix.Extension, error)

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

func CertificatePoliciesExt(templateOIDs []string) (pkix.Extension, error)

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

func NTDSCASecurityExt(sid string) ([]byte, error)

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

func UPNSANExtension(upns []string, dnsNames []string) (pkix.Extension, error)

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.

Jump to

Keyboard shortcuts

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