Skip to content

adcs: add --altSid flag to embed szOID_NTDS_CA_SECURITY_EXT in CSR#2222

Open
JosuPalacios99 wants to merge 1 commit into
fortra:masterfrom
JosuPalacios99:feature/adcs-sid-extension
Open

adcs: add --altSid flag to embed szOID_NTDS_CA_SECURITY_EXT in CSR#2222
JosuPalacios99 wants to merge 1 commit into
fortra:masterfrom
JosuPalacios99:feature/adcs-sid-extension

Conversation

@JosuPalacios99

Copy link
Copy Markdown

Problem

ntlmrelayx ADCS relay (ESC8 and ESC11) generates CSRs without the
szOID_NTDS_CA_SECURITY_EXT extension (OID 1.3.6.1.4.1.311.25.2).
Since KB5014754, DCs with StrongCertificateBindingEnforcement >= 1
(default 2 since February 2025) reject certificates that lack this
extension during PKINIT. certipy v5 also validates this client-side and
aborts with Object SID mismatch before reaching the DC.

This breaks the ESC1 relay attack chain: even when the CA issues a
certificate with the target account's UPN in the SAN, authentication
fails because the certificate lacks the SID binding that modern DCs
require. The attack was functional before KB5014754 enforcement but is
blocked on any updated environment without this fix.

The root cause is pyOpenSSL: it delegates extension encoding to OpenSSL,
which has no knowledge of Microsoft-proprietary OIDs and cannot encode
this extension via the high-level API.

Fix

Add --altSid <SID> parameter. When provided, generate_csr() switches
from pyOpenSSL to cryptography.x509.CertificateSigningRequestBuilder
with UnrecognizedExtension, using pure-Python DER/TLV encoding to
construct the extension value.

The extension encodes the SID string (e.g. S-1-5-21-...-500) as
UTF-8 inside an OtherName GeneralName with OID
1.3.6.1.4.1.311.25.2.1 (szOID_NTDS_OBJECTSID). The CA propagates
this extension to the issued certificate, satisfying the DC's strong
mapping requirement and restoring ESC1 relay on fully enforced environments.

Backward compatible: omitting --altSid keeps the original
pyOpenSSL code path unchanged.

Files changed

  • impacket/examples/ntlmrelayx/attacks/httpattacks/adcsattack.py — DER helpers + generate_csr altSid path
  • impacket/examples/ntlmrelayx/attacks/rpcattack.py — pass altSid to generate_csr (ESC11)
  • impacket/examples/ntlmrelayx/utils/config.pyaltSid field + setAltSid()
  • examples/ntlmrelayx.py--altSid argument

Usage

sudo ntlmrelayx.py -6 \
  -t rpc://CA.corp.local \
  -rpc-mode ICPR \
  -icpr-ca-name 'CORP-CA' \
  --adcs \
  --template VulnTemplate \
  --altname 'Administrator@corp.local' \
  --altSid 'S-1-5-21-XXXXXXXXX-XXXXXXXXX-XXXXXXXXX-500' \
  --no-multirelay \
  -smb2support

ntlmrelayx ADCS relay generates CSRs without the SID extension required
by KB5014754 (StrongCertificateBindingEnforcement >= 1, enforced by
default since Feb 2025). Certs issued without the extension fail PKINIT
on modern DCs and are rejected client-side by certipy v5 with
"Object SID mismatch".

Add --altSid <SID> parameter (ESC8 and ESC11 paths) that embeds the
target account SID inside szOID_NTDS_CA_SECURITY_EXT (OID
1.3.6.1.4.1.311.25.2) using cryptography.x509.UnrecognizedExtension
with manual DER/TLV encoding. pyOpenSSL cannot encode this OID since
OpenSSL has no knowledge of Microsoft-proprietary extensions.

Backward compatible: omitting --altSid keeps the original pyOpenSSL
code path unchanged.
@anadrianmanrique anadrianmanrique added the in review This issue or pull request is being analyzed label Jul 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

in review This issue or pull request is being analyzed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants