Detecting MS14-068 Kerberos Exploit Packets on the Wire aka How the PyKEK Exploit Works

MS14-068 References:

This post shows the packet captures I performed using WireShark on the Domain Controllers during stage 1 and stage 2 of the attack.
Microsoft KB3011780 patches this issue.

Here are the full packet captures:

Stage 1 – Using PyKEK to inject a forged PAC into a valid TGT: ADSecurityOrg-MS14068-Exploit-KRBPackets

Stage 2 – Using Mimikatz to leverage the forged TGT into the user session & connect to the unpatched Domain Controller’s admin$ share: ADSecurityOrg-MS14068-Exploit-KRBPackets-TGTInjection-And-DC-AdminShare-Access

Note: Using the information posted here, it may be possible to create a Snort signature that can identify active MS14-068 exploitation on a network by looking at the TGS-REQ Kerberos packet that states “include-pac: False” (additionally, the AS-REQ packet earlier in the conversation also states “include-pac: False”)

Stage 1 Attack Packets: PyKEK requests and modifies a TGT

.The Python script performs a TGT request (Kerberos Authentication Service Request aka AS-REQ) and instead of requesting a TGT with a PAC (default AS-REQ), PyKEK requests a TGT with no PAC from the Domain Controller.

Once the script receives the valid TGT without a PAC from the DC, the script generates a PAC (with the group membership listed above) packages it in encrypted authorization data as part of a TGS request to the DC (Kerberos Ticket Granting Service Request aka TGS-REQ) to obtain another TGT (a new one with the PyKEK generated PAC).
“The vulnerable KDC will verify it with MD5 and give you another TGT with a PAC in it”.
This is the TGT that PyKEK saves to the ccache file used for stage 2.

Since PyKEK communicates with the Domain Controller for valid TGTs, the TGT is a valid ticket (other than the forged PAC it includes). To summarize, there are two TGTs involved in the process: the original one without a PAC as a result of the first AS-REQ and a second one the DC delivers in the TGS-REP with the PyKEK generated PAC.

NOTE: The TGT is technically not modified by PyKEK since it is encrypted by the KDC account (KRBTGT). The process the script uses results in a valid TGT with the PAC PyKEK created that is accepted by an unpatched DC. The genius part of this is that PyKEK uses the Kerberos AS & TGS exchanges to forge a PAC and have the DC place it into a new user TGT. Then when the TGT is presented later on in Stage 2 for a valid TGS, the PAC is accepted and its values carried on into the new TGS for a Kerberos service in AD.

From the post entitled “Exploiting MS14-068 Vulnerable Domain Controllers Successfully with the Python Kerberos Exploitation Kit (PyKEK)

c:\Temp\pykek> -u -p TheEmperor99! -s S-1-5-21-1473643419-774954089-2222329127-1110 -d

[+] Building AS-REQ for… Done!
[+] Sending AS-REQ to… Done!

Stage 1 Packet #1: TGT request (AS-REQ) with no PAC.


NOTE: The AS-REQ for the TGT requests a TGT with no PAC. This may be useful for creating a Snort signature to detect attempted MS14-068 exploitation on the network.
Compare this with a TGT request (AS-REQ) from a Windows client (Windows 7) which requests a PAC by default (click thumbnail to embiggen):

[+] Receiving AS-REP from… Done!

Stage 1 Packet #2: TGT Response (AS-REP) which returns the KDC encrypted TGT to the client.


[+] Parsing AS-REP from… Done!
[+] Building TGS-REQ for… Done!
[+] Sending TGS-REQ to… Done!

Stage 1 Packet #3: The TGS request notes no PAC should be included and there is an authenticator provided (the generated PAC).


NOTE: The TGS-REQ provides the PAC as part of the request (though no PAC is requested). This can be used to create an IDS signature to detect attempted MS14-068 exploitation on the network.
Compare this with a TGS request (TGS-REQ) from a Windows client (Windows 7) which doesn’t have “include-pac:False”
(click thumbnail to embiggen):

[+] Receiving TGS-REP from… Done!

Stage 1 Packet #4: The TGS response includes the new TGT which uses MD5 (unkeyed).

Compare this with a TGS response (TGS-REP) from a Windows client (Windows 7) in which the ticket component contains an “enc-part” with the etype: “eTYPE-AES256-CTS-HMAC-SHA1-96 (18)” which is a keyed SHA1 hash.
(click thumbnail to embiggen):

[+] Parsing TGS-REP from… Done!
[+] Creating ccache file ‘’… Done!

Stage 1 is now complete with a forged TGT.


Stage 2 Attack Packets: Using Mimikatz to leverage the forged TGT & connect to DC Admin$ Share:

This stage leverages Mimikatz to clear the existing Kerberos tickets in memory for the current user and places the TGT created in Stage 1 into memory for use.
At this point, the user can connect to the unpatched DC with full admin credentials. The act of attempting to connect to the Admin$ share on the DC generates a TGS-REQ and resulting TGS-REP (with a KRB-ERR mixed in for spice).

 c:\Temp\pykek> c:\temp\mimikatz\mimikatz.exe “kerberos::ptc c:\temp\” exit

.#####.   mimikatz 2.0 alpha (x64) release “Kiwi en C” (Nov 20 2014 01:35:45)
.## ^ ##.
## / \ ##  /* * *
## \ / ##   Benjamin DELPY `gentilkiwi` ( )
‘## v ##’             (oe.eo)
‘#####’                                     with 15 modules * * */

mimikatz(commandline) # kerberos::ptc c:\temp\
Principal : (01) : darthsidious ; @ LAB.ADSECURITY.ORG
Data 0
Start/End/MaxRenew: 12/7/2014 3:10:30 PM ; 12/8/2014 1:10:30 AM ; 12/14/2014 3:10:30 PM
Service Name (01) : krbtgt ; LAB.ADSECURITY.ORG ; @ LAB.ADSECURITY.ORG
Target Name  (01) : krbtgt ; LAB.ADSECURITY.ORG ; @ LAB.ADSECURITY.ORG
Client Name  (01) : darthsidious ; @ LAB.ADSECURITY.ORG
Flags 50a00000    : pre_authent ; renewable ; proxiable ; forwardable ;
Session Key       : 0x00000017 – rc4_hmac_nt
Ticket            : 0x00000000 – null              ; kvno = 2        […]
* Injecting ticket : OK

mimikatz(commandline) # exit

c:\Temp\pykek> net use \\\admin$

Stage 2 Packet #1: The first TGS-REQ for the Admin$ share on the DC using the forged TGT.


Stage 2 Packet #2: Kerberos Error response due to “eRR-ETYPE-NOSUPP (14)” error due to the request including encryption type (etype) eTYPE-AES256-CTS-HMAC-SHA1-96 (18). This is interesting since the TGS-REP shows this etype is indeed supported.


Stage 2 Packet #3: The second TGS-REQ for the Admin$ share on the DC.


Stage 2 Packet #4: The TGS-REP to the second  TGS-REQ for the Admin$ share on the DC.


From here, the user has a valid TGS for the CIFS service on the DC and can use it to access the admin$ share via SMB.



(Visited 11,478 times, 1 visits today)