In late September, Charlie Clark (@exploitph) published research titled New Attack Paths? AS Requested Service Tickets. In this research, he describes an attack he dubs Roast-in-the-Middle, in which an unauthenticated attacker able to obtain a man-in-the-middle position can sniff AS-REQs and replay them in order to Kerberoast known accounts. He released a proof-of-concept along with the research, which you can find here. Using his research and proof-of-concept code, I was able to create a Python implementation of the attack, RITM. This post will simply serve to describe how RITM works under the hood.
ARP Spoofing
Similar to the proof-of-concept code, RITM performs ARP spoofing to obtain the man-in-the-middle position required for the attack. The only difference between how the tools operate is RITM supports spoofing to a gateway, allowing for the attack to function even when the target clients and DCs are on different network segments. In my home lab, all the machines are on the same segment, like below, so ARP spoofing between then doesn’t involve a gateway.
However, in practice you’ll likely need to spoof between your target and the local gateway (which can be done by adjusting one CLI flag).
Before we start the attack, if we check the ARP cache on the Windows 10 client, everything will appear normal.
Let’s kick off RITM and start the attack.
Couple of notes on the screenshot:
I’m providing the domain controller’s IP to the
-g/--gateway
flag where you’ll specify the gateway normallyRegardless of if everything’s on the same segment or not, I would specify a domain controller’s IP with
--dc-ip
. You really don’t want to wait around sniffing for an AS-REQ, only for the attack to fail if your machine can’t directly resolve the domain nameThe
-u/--users-file
flag needs a list of usernames. If you’re performing this attack truly unauthenticated, use RID cycling or brute forcing Kerberos pre-auth to obtain a list
Once RITM is up and running, we can take another look at the target’s ARP cache and see that it’s been poisoned.
Since RITM supports spoofing to a gateway, the ARP spoofing is performed both ways. Meaning, if you were also to check the ARP cache on whatever was provided to the -g/--gateway
flag, the attacker’s MAC would be listed as the physical address for the target client(s).
This is where things can get risky - if you target networking devices with -t instead of Windows workstations/servers, things are going to break. Targeting too many machines at once could also have negative effects.
AS-REQ Sniffing
Now that a man-in-the-middle position has been obtained, it’s really just a waiting game to sniff an AS-REQ. You should be able to sniff them naturally when users’ TGTs on your target(s) expire and a new one is requested, or when they log into their machine from a locked screen. Tt’s probably more fruitful to target Windows workstations than servers for this reason, if you have a choice on your network segment.
In my lab, a new AS-REQ can be forced by purging existing tickets and then requesting access to a service.
RITM confirms this caused the client to send out an AS-REQ.
Let’s examine this a bit in Wireshark. We can see that we’ve actually man-in-the-middled two AS-REQs from the target. The first does not contain pA-ENC-TIMESTAMP
data and is met with a ERR_PREAUTH_REQUIRED
from the KDC. The second AS-REQ from the target does contain the encrypted timestamp, used by the KDC to verify the client’s identify
This second AS-REQ is what RITM is sniffing for. If the account the sniffed AS-REQ belongs to does not require pre-auth, no AS-REQ containing pA-ENC-TIMESTAMP
data will be sent and this will actually be missed by RITM. In my experience, this would be an edge case that won’t be encountered often. But be aware this could technically be missed.
Roasting
This is where Charlie’s research comes into play. AS-REQs are normally used to request ticket-granting-tickets (TGTs) , but Charlie discovered that by specifying a SPN within the sname of a valid AS-REQ, the KDC will respond with a service ticket for that SPN. By replaying the AS-REQ and inserting known usernames into the sname field, we can Kerberoast.
In regards to the roast-in-the-middle attack, he also states:
This type of attack generally is not possible with TGS-REQs because the optional cksum field within the authenticator inside the AP-REQ protects the req-body of the request and is frequently included by genuine Windows Kerberos clients. Therefore, modifying the sname of a TGS-REQ without updating the checksum within the authenticator invalidates the authenticator checksum and returns a KRB_AP_ERR_MODIFIED error. But this is not a problem for AS-REQs because the req-body, and consequently the sname field, are not protected.
This may be another minor difference between his proof-of-concept and RITM. Instead of modifying the sniffed AS-REQ and replaying it, RITM uses Impacket to create new AS-REQs from scratch and then stuff the sniffed pA-ENC-TIMESTAMP
data into those packets.
Going back to Wireshark, you’ll notice there are 5 AS-REQs following the legitimate Kerberos traffic. The user list I provided only included 4 names - RITM first sends an AS-REQ with krbtgt as the sname value to determine the validity of the timestamp. In the 4 trailing AS-REQs you’ll see the legitimate timestamp data, pulled right from the sniffed packet, with the user list rotated in as the sname value.
Three of those four AS-REQs received an ERR_S_PRINCIPAL_UNKNOWN
from the KDC, indicating those sname values were valid, but were unassociated with an SPN. The other account does have an SPN and RITM successfully roasts this account.
Cleanup
After the user list is exhausted, RITM will automatically shutdown and attempt to restore the ARP caches of any systems involved in the spoofing attack. It will also attempt to perform this cleanup upon receiving a Ctrl-C
from the operator, although multiple Ctrl-C
hits will likely interrupt restoration.