CVE-2026-56155 Anatomy: Inside the Actively Exploited AD FS Zero-Day That Grants Admin Privileges and How Ransomware Groups Are Chaining It With RCE
622 CVEs landed on July 14, 2026, the biggest single Patch Tuesday Microsoft has ever shipped. Forty-eight of them were rated critical. Security teams spent the week triaging remote-code-execution scores in the 9-point range. And the one bug that actually mattered, the only one being exploited in the wild that month, carried a modest 7.8 and the word “local” in its attack vector. That bug is CVE-2026-56155, and if you run on-prem AD FS, it is a loaded gun pointed at every application you have ever federated.
The record that buried the real story
There is a rhythm to Patch Tuesday triage that works most months and fails badly on the ones that count. You sort by CVSS, you look at “Exploitation More Likely,” you patch the criticals first, and you move on. July 2026 broke that reflex. Buried under 48 critical RCEs was a single “important” elevation-of-privilege flaw that Microsoft flagged as actively exploited, and it was the only one in the entire batch with that designation.
The detail that should stop you cold: CVE-2026-56155 was credited to the Microsoft Detection and Response Team, DART. DART is not a research lab that fuzzes drivers for fun. It is the unit Microsoft flies in when a customer is already on fire. When DART finds a bug, the finding almost always comes out of a live intrusion. So this was not a theoretical write-up that happened to ship the same day as the patch. Someone was using it against a real organization, and Microsoft’s own responders reverse-engineered it out of the wreckage.
Microsoft never disclosed who was hit, how the attackers got their initial foothold, or what the indicators looked like. That silence is the whole problem. You cannot answer “were we already breached through this” because there are no published IOCs to check against. The patch closes the door. It says nothing about whether someone already walked through it.
Here is the thesis for the rest of this piece: CVE-2026-56155 is scored as a local privilege escalation, but it is functionally a full identity-infrastructure compromise, and treating it as “just patch KB5121391” leaves the actual damage untouched. Let me show you why.
AD FS architecture for defenders
To understand why a 7.8 detonates the way it does, you need to understand what AD FS actually is inside the trust chain.
Active Directory Federation Services is the on-prem service that turns “you authenticated to Active Directory” into “here is a signed token that a cloud app will trust.” It sits between your internal directory and everything you have federated: Microsoft 365, Salesforce, AWS via SAML, on-prem SharePoint, custom line-of-business apps. Every one of those relying parties (RPs) trusts AD FS because they have imported its federation metadata, and that metadata contains the public half of the AD FS token-signing certificate.
That is the pivot point of the entire design. The relying party does not phone home to your domain controller. It does not validate a Kerberos ticket. It receives an XML assertion, checks the digital signature against the public key it already trusts, and if the math holds, it logs the user in. Trust is delegated entirely to whoever holds the private signing key.
The token-signing pipeline, endpoint to assertion
Walk a passive (browser-based) WS-Federation sign-in through the box:
- A user hits an RP. The RP redirects the browser to the AD FS passive endpoint:
/adfs/ls/?wa=wsignin1.0&wtrealm=<RP_URI>&wctx=.... This is handled byMicrosoft.IdentityServer.Web.PassiveRequestHandler. - AD FS authenticates the user against Active Directory (integrated Windows auth, forms, whatever the policy is).
- The incoming AD identity flows into the claims pipeline:
ClaimsProviderTrustproduces raw claims, theClaimsTransformationEngineruns the issuance transform rules, and theRelyingPartyTrustshapes them into whatever the target app expects (a UPN, an email, a role, a NameID). - The Security Token Service (
Microsoft.IdentityServer.Service.SecurityTokenService) constructs a<saml:Assertion>, then signs it usingX509SigningCredentialsbuilt over the token-signing certificate. The signature is an<ds:Signature>block per XML-DSIG, typically RSA-SHA256. - The signed assertion is packaged in a
wresultand posted back to the RP.
The active (programmatic) path uses WS-Trust endpoints like /adfs/services/trust/13/usernamemixed, exchanging an RST for an RSTR, but the crypto ending is identical: a SAML assertion signed with the token-signing key. SAML-P and OAuth flows differ in envelope but converge on the same signing operation.
The takeaway for a defender: there is exactly one secret that makes AD FS trustworthy, and it is the token-signing private key. Steal it and you can manufacture identities for anyone, forever, without ever touching a domain controller again.
The DKM container: what it is and why it is the crown jewel
Microsoft knew the signing key was the crown jewel, so they did not leave it sitting in a plaintext PFX on disk. AD FS protects it through the Distributed Key Manager, DKM.
DKM stores a set of symmetric keys inside Active Directory itself, in a container that by default lives at a path like:
CN=ADFS,CN=Microsoft,CN=Program Data,DC=<domain>,DC=<tld>
Inside that container are contact objects, and the encrypted key material rides in an unusual attribute: thumbnailPhoto. That is not a mistake in the design; thumbnailPhoto is a large binary attribute that happens to be a convenient place to stash an opaque blob. The blob holds an AES key that has been wrapped using DPAPI-NG, Microsoft’s group-scoped data protection layer, through the CNG APIs NCryptProtectSecret and NCryptUnprotectSecret.
The chain of custody looks like this:
Token-signing private key (RSA)
└─ stored in a PFX blob
└─ encrypted with an AES key
└─ AES key wrapped by DPAPI-NG (NCryptProtectSecret)
└─ wrapped blob written to thumbnailPhoto in the DKM container
The intended security property: only the AD FS service account, running with the correct group protection descriptor, can call NCryptUnprotectSecret to peel this back. Everyone else sees an inert binary blob in a directory attribute.
That property depends entirely on the ACL of the DKM container. And that is exactly what broke.

Root cause analysis: CWE-1220 in the DKM ACL
CVE-2026-56155 is classified as CWE-1220, insufficient granularity of access control. Strip away the taxonomy and it means the ACL on the DKM container was more permissive than the design assumed. Principals that should never have been able to read the key material could read it.
Reading thumbnailPhoto is only the first step. Possessing an encrypted blob is not the same as possessing a usable key, and Microsoft’s own language is careful about this: an attacker still has to understand the AD FS storage format, retrieve the protected data, and perform the cryptographic operations to unwrap it. But once the ACL grants read access to a low-privilege principal, and once that principal can also reach the DPAPI-NG protection descriptor (also resolvable from AD when permissions are loose), every downstream step is just applied engineering. The prior art already exists.
Two things about the fix tell you how deep this cut. First, it is phased, not a simple binary patch. KB5121391 ships in audit mode, detecting insecure DKM ACLs and logging them without changing anything, because auto-tightening an AD object’s ACL in place can break AD FS if done blindly. Second, Microsoft set a hard enforcement date of October 13, 2026, at which point the update will forcibly remediate insecure ACLs unless an administrator has already opted in via the RemediateDkmAcl registry value. When Microsoft gives you a three-month runway before they touch your ACLs for you, it is because the blast radius of getting it wrong is enormous on both sides.
Affected surface: on-prem AD FS on supported Windows Server builds. If you have already moved federation to Entra ID, this specific object does not exist in your environment and you are out of scope.
The privilege escalation primitive, reconstructed
Microsoft has not published the exact exploitation procedure. What follows is a technically grounded reconstruction built from the confirmed root cause (permissive DKM ACL leads to key read leads to decryption) and well-documented prior art, primarily ADFSDump and the Golden SAML research lineage. Treat the mechanics as accurate at the level of class, not as a byte-exact Microsoft disclosure.
The primitive is a chain of four moves, all executable by a low-privilege, domain-authenticated attacker sitting locally.
Step 1: Confirm the ACL is permissive
# Low-priv context: can we even read the DKM container's key attribute?
$dkmPath = "LDAP://CN=ADFS,CN=Microsoft,CN=Program Data,DC=lab,DC=local"
$entry = New-Object DirectoryServices.DirectoryEntry($dkmPath)
$searcher = New-Object DirectoryServices.DirectorySearcher($entry)
$searcher.Filter = "(objectClass=contact)"
$searcher.PropertiesToLoad.Add("thumbnailPhoto") | Out-Null
# If thumbnailPhoto comes back populated for a non-privileged user,
# the ACL is misconfigured and the box is exploitable.
$searcher.FindAll() | ForEach-Object { $_.Properties["thumbnailPhoto"] }
If that attribute is readable from labuser, the game is over before it started.
Step 2 through 4: unwrap the blob and recover the RSA key
The canonical tooling is ADFSDump (from the fox-it adconnectdump project, in the lineage of Dirk-jan Mollema’s work). It automates exactly the chain of custody described earlier: read thumbnailPhoto over LDAP, call DPAPI-NG to unwrap the AES key, AES-decrypt the PFX, and load the RSA private key. In pseudocode so you can see every stage:
# Conceptual reconstruction - educational annotation only.
# Byte-level format should be verified against ADFSDump source.
# 1. Read the encrypted key blob from the DKM contact object
dkm_blob = ldap_read(
"CN=ADFS,CN=Microsoft,CN=Program Data,DC=lab,DC=local",
attr="thumbnailPhoto")
# 2. Unwrap the AES key via DPAPI-NG. The group protection descriptor
# is resolvable from AD when the ACL is loose - that is the crux.
aes_key = NCryptUnprotectSecret(dkm_blob.protection_descriptor,
dkm_blob.encrypted_aes_key)
# 3. AES-decrypt the PFX blob holding the signing cert + private key
pfx_bytes = AES_decrypt(key=aes_key, iv=dkm_blob.iv,
ciphertext=dkm_blob.encrypted_pfx)
# 4. Load the PFX and pull out the RSA private key
signing_cert, signing_private_key = load_pfx(pfx_bytes, password=None)
# signing_private_key is now the AD FS token-signing key.
# It can sign arbitrary SAML assertions for any user.
Notice what this primitive does not require: no admin token on the AD FS host at the start, no LSASS access, no memory corruption, no exotic syscall. It is a directory read followed by a CNG unwrap. That is why it scores “low complexity, low privileges, no user interaction.” The elevation to administrator is not the interesting part. The interesting part is that at the end of it you hold the key that makes the entire federation trust chain lie for you.
Golden SAML: from signing key to forged identity
Once you hold signing_private_key, you graduate from privilege escalation to Golden SAML, and the two are worlds apart in impact.
Golden SAML is the SAML analogue of a Golden Ticket, except it is arguably worse. With a Golden Ticket you forge Kerberos TGTs and you are still bounded by what the DC will honor. With Golden SAML you forge the assertion itself and sign it with the stolen token-signing key, so any relying party that trusts your AD FS metadata will accept it. You pick the NameID, you pick the claims, you pick the roles. Domain admin, CFO, service account, whoever.
# AADInternals (Nestori Syynimaa) - lab only
Import-Module AADInternals
$saml = New-AADIntSAMLToken `
-ImmutableID "base64EncodedObjectGUID" `
-Issuer "http://adfs01.lab.local/adfs/services/trust" `
-PfxFileName "C:\lab\stolen_signing.pfx" `
-PfxPassword ""
# Replay to the relying party. It validates the signature against the
# public key in the trusted metadata, sees valid math, logs the user in.
The detection nightmare is structural. The forged token is minted entirely offline. It never hits your domain controller, so there is no 4769 Kerberos service-ticket event. It never hits AD FS to be issued, so there is no AD FS token-issuance event. The RP just sees a perfectly valid login. From the DC’s and AD FS’s perspective, nothing happened at all. This is the single most important fact for the detection section below: the crime is invisible on the systems you are most likely monitoring, and visible only as an absence.

The ransomware chain: RCE, then CVE-2026-56155, then everything
ZDI called out the pairing explicitly, and it is the reason this bug belongs at the top of your queue rather than the middle. On its own, CVE-2026-56155 needs local access. Ransomware operators solve “local access” for a living. Here is the composed playbook:
| Stage | Technique | What the operator does |
|---|---|---|
| 1. Initial access | RCE on a networked host | Exploit a separate remote bug (email, edge appliance, web app) to land code on a domain-joined machine |
| 2. Recon | BloodHound CE / SharpHound | Map the AD FS farm and, critically, enumerate the DKM container ACL path |
| 3. Pivot | WMI / PsExec as labuser | Move from the beachhead to the AD FS host, or simply run the LDAP read remotely |
| 4. EoP | CVE-2026-56155 | Read thumbnailPhoto, unwrap DKM, escalate to admin, extract the signing key |
| 5. Identity forge | Golden SAML | Mint tokens for M365, AWS, SaaS as any user, no further AD interaction |
| 6. Impact | Exfil + encrypt | Exfiltrate under forged executive identities, then deploy ransomware across the federated estate |
The blast radius is not “the AD FS box.” It is every cloud tenant, every SaaS app, and every on-prem RP that trusts your federation, accessed under identities that pass every signature check. That is why “important, 7.8, local” is a wild understatement.
Mapped to MITRE ATT&CK: initial access via T1190/T1566, discovery via T1069/T1482, credential access on the DKM read via T1552.004 (private keys), the signing-key theft as T1606.002 (forge web credentials: SAML tokens), lateral movement to cloud as T1550.001 (application access token), and impact via T1486.

Detection engineering: Event IDs, ETW, and the blindspot
Start with an uncomfortable prerequisite: AD FS auditing is not on by default. If you have never touched it, none of the events below exist in your logs. Turn it on first:
Set-AdfsProperties -AuditLevel Verbose
# Plus GPO: Audit Application Generated = Success, Failure
# on the AD FS servers.
The AD FS security log events that matter
| Event ID | Log | Meaning |
|---|---|---|
| 1200 | Security | Application token issued successfully |
| 1201 | Security | Token issuance failed (SSO artifact leg) |
| 1202 | Security | Fresh credential validation success (WS-Trust, WS-Fed, SAML-P first leg, OAuth Authorize) |
| 1203 | Security | Fresh credential validation error |
| 411 | AD FS Admin | Token validation failure on the receiving side (bad signature, malformed token) |
| 1132 | AD FS Admin | New post-KB5121391 event: DKM container permissions require attention |
Event ID 1132 is your first-line signal that the ACL is insecure. Audit mode exists precisely to generate it. If you see 1132, you are vulnerable right now, patched or not, until you fix the ACL.
The Golden SAML blindspot, expressed as a detection
Because the forged token never touches the DC or AD FS, you cannot detect the forgery directly. You detect the absence of expected authentication upstream of a successful downstream login. The rule, in plain English:
If a relying party (Azure sign-in, AWS
AssumeRoleWithSAML, an app login) records a successful federated login for user X at time T, and there is no corresponding AD FS Event 1200 (and no 1202, and no DC 4769) for user X in the window around T, treat that login as a likely forged SAML assertion.
This correlation is the only reliable Golden SAML tripwire, and it keeps working after the patch, which is exactly what you want against an attacker who may already hold your signing key.
Key-extraction and tooling signals
You can also catch the theft itself if you instrument the AD FS host:
- Event ID 1007 (
Microsoft-Windows-CertificateServicesClient-Lifecycle-System): signing certificate export from the AD FS server. - Sysmon Event ID 18, named pipe
\Microsoft##wid sql\query: this is the WID database pipe thatADFSDumptouches. High-fidelity tool signal. - PowerShell 4103/4104 and process creation containing
Export-PfxCertificateorcertutil.exe -exportPFX: key export by hand. - Sysmon 11: file creation under
%ProgramData%\Microsoft\ADFS\, potential export artifacts. - Windows Security 4662: object access on the DKM container. This requires a SACL on the DKM object, which is not present by default. You must add it before this event will ever fire.
Relevant ETW providers if you want to go deeper: Microsoft-Windows-ADFS (Admin and Operational channels) and Microsoft-Windows-CNG for NCryptUnprotectSecret call visibility via a custom session.
Sigma: DKM read and ADFSDump
title: AD FS DKM Container LDAP Read - CVE-2026-56155 Recon
status: experimental
logsource:
product: windows
service: security
detection:
selection:
EventID: 4662
ObjectName|contains: 'CN=ADFS,CN=Microsoft,CN=Program Data'
AccessMask: '0x10' # READ_PROPERTY
filter_legit:
SubjectUserName|endswith: '$' # exclude machine/service accounts
condition: selection and not filter_legit
falsepositives:
- AD replication or backup service accounts
level: high
tags:
- attack.credential_access
- attack.t1552.004
title: ADFSDump WID Named Pipe - Token-Signing Key Extraction
status: experimental
logsource:
product: windows
service: sysmon
detection:
selection:
EventID: 18
PipeName|contains: 'Microsoft##wid'
filter_legit:
Image|endswith:
- '\Microsoft.IdentityServer.ServiceHost.exe'
- '\sqlservr.exe'
condition: selection and not filter_legit
level: critical
tags:
- attack.t1606.002
Remember the DKM read rule is inert until you set that SACL. It is a two-part control: instrument the object, then alert on access.
Sentinel KQL: RP login with no matching AD FS issuance
let adfs_issued = SecurityEvent
| where EventID == 1200
| extend UPN = extract("UPN: ([^\\r\\n]+)", 1, EventData)
| project TimeGenerated, UPN;
SigninLogs
| where AuthenticationProtocol == "samlp"
| where TimeGenerated > ago(1h)
| join kind=leftanti (
adfs_issued
| where TimeGenerated between (ago(1h) .. now())
) on $left.UserPrincipalName == $right.UPN
| project TimeGenerated, UserPrincipalName, AppDisplayName, IPAddress
Splunk SPL: DKM container read
index=wineventlog source="WinEventLog:Security" EventCode=4662
Object_Name="*CN=ADFS,CN=Microsoft,CN=Program Data*"
Access_Mask="0x10"
NOT Account_Name="*$"
| table _time, Account_Name, Object_Name, Access_Mask, host
| eval alert="DKM Container Read - CVE-2026-56155 Recon"
Hardening blueprint: beyond patching KB5121391
The patch is necessary and nowhere near sufficient. Audit mode does not fix your ACL until October 13, 2026 unless you tell it to. And nothing about the patch answers the only question that matters after a DART-attributed zero-day: has my signing key already been stolen? Here is the layered posture that actually reduces risk.
| Layer | Control | Why it matters |
|---|---|---|
| 1 | Apply KB5121391 now | Enables audit mode and Event 1132; does not auto-fix the ACL yet |
| 2 | Set RemediateDkmAcl=1 immediately | Opt in to ACL remediation now instead of waiting for the October auto-fix |
| 3 | Add a SACL to the DKM container | Prerequisite for 4662 read detection; not present by default |
| 4 | Enable verbose AD FS auditing | Without it, 1200/1201/1202/411 simply do not exist |
| 5 | Rotate the token-signing certificate | Update-AdfsCertificate -CertificateType Token-Signing -Urgent invalidates any key an attacker may already hold |
| 6 | Baseline and verify the cert thumbprint | Compare (Get-AdfsCertificate -CertificateType Token-Signing).Thumbprint against a known-good value |
| 7 | Segment the AD FS host | Only allow LDAP/LDAPS from the AD FS service account to the DC; kill lateral paths |
| 8 | Manage AD FS from a PAW only | No browser, no email on the AD FS box; removes the RCE-to-pivot bridge |
| 9 | Deploy the Golden SAML correlation | The RP-login-without-1200 rule keeps catching forgeries after the patch |
| 10 | Migrate federation to Entra ID | The strategic answer: retire the DKM container and this entire attack surface |
If I could force one action beyond patching, it would be layer 5, rotate the signing certificate, and do it twice per AD FS guidance so the secondary key rolls too. Because DART found this in a live intrusion and Microsoft published zero IOCs, the honest default assumption for any exposed AD FS farm is that the key might already be gone. A forged token signed with an old key is worthless the moment you rotate. Rotation is the one control that retroactively neutralizes a theft you cannot even confirm happened.

Key takeaways
- CVSS 7.8 local EoP is a lie of omission here. The real impact is full federated-identity compromise via Golden SAML, reaching every cloud tenant and SaaS app you trust.
- DART credit means live exploitation. No published IOCs means you cannot rule out prior compromise, so assume the signing key may already be stolen and rotate it.
- The DKM container ACL is the whole ballgame. Loose permissions on
CN=ADFS,CN=Microsoft,CN=Program Dataturn a directory read into your token-signing private key. - Golden SAML is invisible on the DC and AD FS. Detect it as an absence: an RP login with no matching Event 1200/1202 and no DC 4769.
- Patching KB5121391 is step one, not the finish line. Set
RemediateDkmAcl=1today, add the SACL, enable verbose auditing, and rotate the signing certificate. - The permanent fix is architectural. Migrating federation to Entra ID deletes the DKM container and this bug class along with it.
Related Tutorials
References
- # Reference
- CVE-2026-56155 – Active Directory Federation Services Elevation of Privilege Vulnerability (Microsoft MSRC Official Advisory)
- CVE-2026-56155 Detail – National Vulnerability Database (NVD / NIST)
- The July 2026 Security Update Review – Zero Day Initiative (Trend Micro ZDI)
- MITRE ATT&CK: Exploitation for Privilege Escalation (T1068) – Enterprise Technique
- Microsoft Active Directory Services 0-Day Vulnerability Actively Exploited in the Wild – CyberSecurityNews
- CVE-2026-56155: The AD FS DKM ACL Privilege Escalation – PenLigent AI Hacking Labs