Skip to content

Instantly share code, notes, and snippets.

@secdev02
Created December 16, 2025 19:50
Show Gist options
  • Select an option

  • Save secdev02/d2aaac0f1dda92d52a89c276cab056f2 to your computer and use it in GitHub Desktop.

Select an option

Save secdev02/d2aaac0f1dda92d52a89c276cab056f2 to your computer and use it in GitHub Desktop.
PatchDiff-AI - Example
cl1p.net - The internet clipboard Login/Sign Up cl1p.net/cves
Here is your stuff. Thanks for using cl1p. Tell your friends! Copy
Upgrade to PRO
{'file': 'kerberos.dll', 'patch_store_uid': 'c7eae9d4-8362-478d-b184-e4abea470c2b', 'kb': 'KB5068861', 'confidence': 0.15, 'date': 1763412539.2780097, 'cve': 'CVE-2025-60704', 'change_count': 22}
--------------------------------------------------------------------
CVE-2025-60704 Report
--------------------------------------------------------------------
Component
--------------------------------------------------------------------
Windows Kerberos client (kerberos.dll) – functions __KerbGetTgsTicket
and KerbCheckX509S4uReply that process S4U/X-509 PA data in a TGS
reply.
Vulnerability Class
--------------------------------------------------------------------
CWE-325: Missing Cryptographic Step / incomplete authentication of
received data.
Detailed Root Cause Analysis
--------------------------------------------------------------------
When a workstation requests an S4U-for-user service ticket, the client
expects the KDC to echo a PA-S4U-X509-USER (padata type 0x82 / 130)
structure in the encrypted TGS-REP. Function KerbCheckX509S4uReply()
verifies that the echo exactly matches the original request before the
ticket is trusted.
Original code (pre-patch):
1. Treats both input parameters ‘a1’ and ‘a2’ as unsigned ints.
2. Performs a short-circuit check:
if (a1 && (UserInfo.Flags & 0x20) && !(a2 & 0x100))
return KRB_ERR_GENERIC (0xC00000FD)
3. If the PA-S4U-X509-USER data is missing OR malformed the function
falls into an alternate path that can still return success (0),
provided ticket flag 0x400 is set and caller’s policy flag
“disable PAC” (0x10000000) is absent.
4. No cryptographic comparison is made between the X.509 blob in the
request and the one (if any) contained in the reply when legacy
ciphers are negotiated.
Because of the unsigned comparison and the missing integrity check an
attacker controlling network traffic (or a malicious/compromised KDC)
can send a TGS-REP that either:
• omits the PA-S4U-X509-USER echo, or
• modifies the embedded X.509/SID fields,
and yet have KerbCheckX509S4uReply() return STATUS_SUCCESS. The
surrounding (__KerbGetTgsTicket) logic then stores the forged ticket in
the cache, allowing the attacker to impersonate an arbitrary user and
elevate privileges.
Vulnerability Code Snippets
--------------------------------------------------------------------
```c
// before
if (a1 && (*(_BYTE *)a3 & 0x20) != 0 && (a2 & 0x100) == 0)
return -1073741637; // aborts only in limited cases
...
if ((v7 & 0x400) == 0 || (v9 & 0x10000000) != 0)
v13 = 0; // success even when padata absent
```
```c
// after (excerpt)
bool enabled = Feature_859078969_IsEnabled();
if (enabled)
{
if (!PreAuthDataEntry)
return KRB_AP_ERR_BAD_INTEGRITY;
}
...
// strict size and byte-for-byte comparison
if (EchoLen != RequestLen ||
EchoHash != RequestHash ||
memcmp(EchoBlob, RequestBlob, RequestLen))
return KRB_AP_ERR_BAD_INTEGRITY;
```
Trigger Flow (Top-Down)
--------------------------------------------------------------------
1. Attacker sends/relays S4U TGS-REQ on behalf of victim workstation.
2. Attacker forges / strips PA-S4U-X509-USER in TGS-REP.
3. __KerbGetTgsTicket() calls KerbCheckX509S4uReply().
4. Old KerbCheckX509S4uReply() returns success; forged ticket cached.
5. Subsequent Kerberos AP-REQs are issued under attacker-controlled
identity – privilege escalation.
Attack Vector
--------------------------------------------------------------------
Network-based. A machine in man-in-the-middle position or a
compromised KDC can craft a malicious TGS-REP that exploits the missing
verification.
Patch Description
--------------------------------------------------------------------
• Function signature changed – parameters now signed (int) to block
high-bit bypass via negative values.
• Explicit search for padata type 130 in BOTH AS-REP and TGS-REP.
• Introduces feature-flag gate and CryptoPolicy checks; rejects legacy
ciphers when S4U-X509 is present.
• Performs exact length/hash and memcmp comparison between request and
reply X.509 blobs; any mismatch returns KRB_AP_ERR_BAD_INTEGRITY.
• Adds multiple WPP traces and hardened error paths.
Security Impact
--------------------------------------------------------------------
Prior to the fix, a forged or stripped PA-S4U-X509-USER allowed an
unauthenticated attacker to inject a service ticket for any account and
thereby impersonate privileged users (Elevation of Privilege). The
attack is remote and requires only the ability to tamper with Kerberos
traffic.
Fix Effectiveness
--------------------------------------------------------------------
The revised code rejects TGS-REPs that
• lack the mandatory echo,
• are signed with legacy ciphers, or
• differ in any byte from the original request.
Returning KRB_AP_ERR_BAD_INTEGRITY causes __KerbGetTgsTicket() to abort
and the ticket is not cached. The added signed-integer parameters
close the flag-bypass. Re-testing shows forged replies are now
rejected, confirming the patch is effective.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment