Patch Now: Two Microsoft Active Directory Bugs Chained to Takeover Windows Domain

Microsoft released a statement to its customers to patch two Active Directory domain controller bugs following the release of the proof-of-concept on December 11.

The vulnerabilities, tracked as CVE-2021-42287 and CVE-2021-42278, can be chained to gain privileges that lead to an easy Windows domain takeover.

The two vulnerabilities allow an adversary with low-privileged domain user credentials to obtain a Kerberos Service Ticket for a Domain Controller computer account, thereby allowing a normal user to control a domain controller. The flaw, according to Microsoft, stems from a KDC misconfiguration that allows any computer account to impersonate AD domains.

Historically, it has been previously observed that Active Directory is extremely difficult to secure. Windows Active Directory servers played a part in the SolarWinds attacks where the servers were hit by the FoggyWeb backdoor.

Get CSW script to detect Windows Active Directory bugs here

How dangerous are these two vulnerabilities?

  • CVE-2021-42287, an elevation of privilege vulnerability, affecting Windows Active Directory servers, has been assigned a CVSS v3 score of 8.8 (high) and the weakness enumeration, CWE-269, which leads to Improper Privilege Management.

  • CVE-2021-42278, on the other hand, is a security bypass escalation of privilege vulnerability with the potential to let attackers impersonate domain controllers using sAMAccountName spoofing techniques. CVE-2021-42278 has a CVSS v3 score of 8.8 (high) and is also pegged as an Improper Privilege Management software weakness (CWE-269).

  • Attackers can use a vulnerability-chaining method to create a direct path to a domain admin user in any unpatched Active Directory environment, thereafter, allowing the full takeover of the machine.

  • A proof-of-concept (PoC) tool that can be used to exploit the bug was released publicly on GitHub, a few weeks after Microsoft released the Patch Tuesday Update for November 2021.

  • Google Trends for most searches for CVE-2021-42287 between December 16-23 reveals it is trending in China, Switzerland, Israel, Austria, and Germany.

  • Similar search trends between December 16-23 for CVE-2021-42278 show a high number of searches in China with a lesser number of counts for Germany, Switzerland, Taiwan, and Denmark.

How does the exploit work?

Our security analysts took a deeper look at how the vulnerabilities affect the Active Directory server. Here is their analysis:

  • All computer accounts usually have a trailing $ in their sAMAccountName attribute. However, since no validation processes exist to make sure of it, CVE-2021-42278 can be leveraged to allow attackers to impersonate domain controller accounts.

  • CVE-2021-42287 comes in when requesting a Kerberos Service Ticket. Before one can request a Service Ticket, a Ticket Granting Ticket (TGT) is required by the Key Distribution Center (KDC). When the KDC is unable to find the requested service ticket, it automatically searches for a machine name with the trailing $. If a user is removed after obtaining the TGT, the user can request a service ticket meant for another user for himself by leveraging the obtained TGT, resulting in the KDC looking for user$ in Active Directory. If the domain controller account user$ exists, then the user basically obtained a service ticket for the domain controller account thereby completing the impersonation loop.

Successful exploitation of the Windows Active Directory domain server would require the following steps:

  1. Add a new machine account to the domain.

  2. Rename the new machine account to match the sAMAccountName of an existing domain controller (without the ‘$’ that all computer names usually have)

  1. Request a Kerberos TGT using the updated machine account name.

  2. Rename the new machine account once again to its original value or any other name.

  3. Use the S4U2self extension to request a Kerberos Service Ticket.

The complete exploitation process can be found here.

Exploit of CVE-2021-42287 and CVE-2021-42278 in process


CSW pentesters have provided a script below to help detect any potential compromise of an unpatched Windows AD Domain server.

#!/usr/bin/env python
from __future__ import division
from __future__ import print_function
import argparse
import logging
import sys
from binascii import unhexlify

from impacket import version
from impacket.examples import logger
from impacket.examples.utils import parse_credentials
from impacket.krb5 import constants
from impacket.krb5.kerberosv5 import getKerberosTGT
from impacket.krb5.types import Principal
import ldapdomaindump
import ldap3
from getpass import getpass

def TGT_size(options):
domain, username, password = parse_credentials(options.credentials)
userName = Principal(username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
lmhash = ”
nthash = ”
tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, password, domain, unhexlify(lmhash), unhexlify(nthash),requestPAC=True)
tgt_2, cipher_2, oldSessionKey_2, sessionKey_2 = getKerberosTGT(userName, password, domain, unhexlify(lmhash), unhexlify(nthash),requestPAC=False)

# # Print TGT
# print (tgt)
# print(“_”*50)
# print(tgt_2)

TGT_size, TGT_size_2 = len(tgt),len(tgt_2)

print(“<“*2+”-“*22+” TGT Size”+”-“*22+’>’*2)
print(f”[+] Length of TGT size with PAC: {TGT_size} \n”)

print(f”[+] Length of TGT size without PAC: {TGT_size_2} \n”)

if TGT_size == TGT_size_2:
print( “[-] Not Vulnerable, PAC validated\n”)
print(“[!] Possbily vulnerable to CVE-2021-42287. \n\n[+] Apply Patches”)

# helper functions ldap connection
def init_ldap_connection(target, tls_version, args, domain, username, password):
user = ‘%s\\%s’ % (domain, username)
if tls_version is not None:
use_ssl = True
port = 636
tls = ldap3.Tls(validate=ssl.CERT_NONE, version=tls_version)
use_ssl = False
port = 389
tls = None
ldap_server = ldap3.Server(target, get_info=ldap3.ALL, port=port, use_ssl=use_ssl, tls=tls)
ldap_session = ldap3.Connection(ldap_server, user=user, password=password, authentication=ldap3.NTLM, auto_bind=True)

return ldap_server, ldap_session

def init_ldap_session(args, domain, username, password):

# if args.k:
#     target = get_machine_name(args, domain)
if args.dc_ip is not None:
target = args.dc_ip
target = domain
return init_ldap_connection(target, None, args, domain, username, password)

## checking MachineAccountQuota
def Check_quota(options):
domain, username, password = parse_credentials(options.credentials)
dc_ip = options.dc_ip
ldap_server, ldap_session = init_ldap_session(options, domain, username, password )
cnf = ldapdomaindump.domainDumpConfig()
cnf.basepath = None
domain_dumper = ldapdomaindump.domainDumper(ldap_server, ldap_session, cnf)
MachineAccountQuota = None

# Get domain policy
dd = domain_dumper.getDomainPolicy()
for i in dd:
MachineAccountQuota = int(str(i[‘ms-DS-MachineAccountQuota’]))

# print(“<“*3+”-“*13+”Machine Account Quota “+”-“*13+’>’*3)
print(“<“+”-“*16+” Machine Account Quota “+”-“*16+”>”)
# print(f'[-] Machine Account Quota  ‘)
print(f'[+] MachineAccountQuota = {MachineAccountQuota} \n’)

#Conditional check
if MachineAccountQuota < 0:
print(“[#] Not vulnerable  cannot proceed with Machine creation. \n”)
print(“[!] Possible Attack Vector, can be exploited further. \n”)

# Process command-line arguments.
if __name__ == ‘__main__’:

parser = argparse.ArgumentParser()

parser.add_argument(‘-debug’, action=’store_true’, help=’Turn DEBUG output ON’)

group = parser.add_argument_group(‘mandatory’)
## hashes are currently not supported
# group.add_argument(‘-hashes’, action=”store”, metavar = “LMHASH:NTHASH”, help=’NTLM hashes, format is LMHASH:NTHASH’)

group.add_argument(‘-dc-ip’, action=’store’,required=True, metavar=”<IP address>”,
help=’IP of the domain controller to use. Useful if you can\’t translate the FQDN.’
‘specified in the account parameter will be used’)
group.add_argument(‘-targetUser’, action=’store’, required=True,metavar=”<Target Username>”, help=’The target user to retrieve the PAC of’)
group.add_argument(‘credentials’, action=’store’, help=’domain/username[:password]. Valid domain credentials to use ‘
‘for grabbing targetUser\’s PAC \n ‘)

if len(sys.argv)==1:

options = parser.parse_args()

domain, username, password = parse_credentials(options.credentials)
target_user = options.targetUser
dc_IP = options.dc_ip
# print(“<“*3+”-“*20+” Input Values “+”-“*20+’>’*3)
print(f”[#] Input Values”)
print(f”domain : {domain} \nusername : {username} \npassword: {password} \ntarget_user: {target_user} \ndc_ip : {dc_IP}”)

if domain is None:
domain = ”

if password == ” and username != ” and options.hashes is None:
password = getpass(“Password:”)

if options.debug is True:
# Print the Library’s installation path

print(f”\n[#] Initiating validations… \n”)

except Exception as e:
if logging.getLogger().level == logging.DEBUG:
import traceback

We also looked into the scanner details to see if the vulnerabilities had been missed by any major scanners. Here are the findings:

Name of Scanner

Plugin details





CVE-2021-42287: 154996, 1544995, 154994, 154993, 154990, 154986, 154984, 154983; CVE-2021-42278: 154996, 1544995, 154994, 154993, 154990, 154986, 154984, 154983

Qualys QID

91835 for CVE-2021-42278, CVE-2021-42287


Vulnerable Product Versions

The product versions affected by the two vulnerabilities are listed in the table below with patch links.


Product Versions Affected

Patch Links


cpe:2.3:o:microsoft:windows_server_2008:-:sp2 (All Versions)  cpe:2.3:o:microsoft:windows_server_2008:r2:sp1:*:*:*:*:x64:*

cpe:2.3:o:microsoft:windows_server_2012 (All Versions)  cpe:2.3:o:microsoft:windows_server_2012:r2 (All Versions)

cpe:2.3:o:microsoft:windows_server_2016:-: (All Versions)

cpe:2.3:o:microsoft:windows_server_2016:20h2 (All Versions)

cpe:2.3:o:microsoft:windows_server_2016:2004 (All Versions)

cpe:2.3:o:microsoft:windows_server_2019:-: (All Versions)

cpe:2.3:o:microsoft:windows_server_2022:-: (All Versions)


cpe:2.3:o:microsoft:windows_server:2004 (All Versions)




cpe:2.3:o:microsoft:windows_server_2012 (All Versions)

cpe:2.3:o:microsoft:windows_server_2012:r2 (All Versions)

cpe:2.3:o:microsoft:windows_server_2016 (All Versions)

cpe:2.3:o:microsoft:windows_server_2019 (All Versions)

cpe:2.3:o:microsoft:windows_server_2022 (All Versions)

Microsoft urged Windows admins to update all domain controllers using the information available in these knowledge-base articles:

There were no exposure counts available for the two CVEs on Shodan at the time this blog was written.

Patching these vulnerabilities should be a top priority for organizations.


With organizations scampering to fix the Apache Log4j vulnerabilities, there is a chance that the Windows Active Directory security flaws may get overlooked.

Since Windows domain administrators can usually modify configurations of Active Directory servers and any content stored there, including creation or deletion of users and/or permissions, as well as control of authorization and authentication to Windows services, CVE-2021-42287 and CVE-2021-42278 are crucial vulnerabilities that require the immediate attention of organizational cybersecurity teams.

We urge all organizations to patch the vulnerabilities before the end of the year because CSW’s experts predict that ransomware operators may use the publicly available proof-of-concept to install ransomware on every Windows machine in a target organization and carry out a fast-paced attack that could take down an entire organization at once.

CSW’s team of expert pentesters and security analysts can help you drive this remediation and gain cyber resilience through our Vulnerability Management services.


CSW’s Vulnerability Management as a Service (VMaaS) offers full coverage encompassing your entire IT landscape and detects, prioritizes,

and fixes vulnerabilities on your organizational infrastructure. 


To know more about CSW’s Vulnerability Management as a Service (VMaaS),

please click here.

Share This Post On