Post

Attacking the Attack Lab - Part 1

banner

Introduction

If you’ve been following, in the previous post I detailed how I manage and deploy my personal attack lab infrastructure (dubbed AttackLab-Lite) using Terraform and Ansible - go give it a read to get up to speed on where we’re heading to next.

In the retrospective section of the previous post, I noted how I would like to create supplemental posts on using different tools and techniques against the attack lab. If you recall (or went and took a look at the post) I leveraged a PowerShell script called VulnAD to populate the lab’s Active Directory with some user objects, groups, and also do a few other preparations, which I’ll get to next.

This is Part 1 of (hopefully) a 2 part series. In this particular post, I want to review what happened when we stood up the Active Directory lab server and performed some preparations by way of the VulnAD script.

So, what are we doing?

The VulnAD script I mentioned previously made some changes to some of the users in the AD lab environment at random (besides generating random user accounts with random passwords) After running the script, I received the following output which we’ll use as guidance.

output

So, what are we going to be doing eventually (Part 2)?

  • Active Directory/LDAP enumeration
  • Kerberoasting
  • Lateral Movement
  • DCSync Attacks

Before we dig into these methodologies and the tools that will accompany us, let’s analyze that screenshot above a little closer, in parallel with the actual script that was used to generate all of the random goodness.

The VulnAD Script… what’s it doing?

whatdoing

The README on the Vulnerable-AD GitHub page doesn’t have a terrible amount of information as to the exacts of what’s going on, only a high-level list. Let’s take this opportunity to inspect the script, in parallel with the screenshot, to see whats happening at some of the more interesting steps.

It’s important to note this script comes packed with randomly generated usernames, passwords, and common service account/SPN names.

Kerberoasting

1
"[+] Kerberoating Done"

Here’s the function from the PowerShell script that’s handling this activity.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function VulnAD-Kerberoasting {
    $selected_service = (VulnAD-GetRandom -InputList $Global:ServicesAccountsAndSPNs)
    $svc = $selected_service.split(',')[0];
    $spn = $selected_service.split(',')[1];
    $password = VulnAD-GetRandom -InputList $Global:BadPasswords;
    Write-Info "Kerberoasting $svc $spn"
    Try { New-ADServiceAccount -Name $svc -ServicePrincipalNames "$svc/$spn.$Global:Domain" -AccountPassword (ConvertTo-SecureString $password -AsPlainText -Force) -RestrictToSingleComputer -PassThru } Catch {}
    foreach ($sv in $Global:ServicesAccountsAndSPNs) {
        if ($selected_service -ne $sv) {
            $svc = $sv.split(',')[0];
            $spn = $sv.split(',')[1];
            Write-Info "Creating $svc services account"
            $password = ([System.Web.Security.Membership]::GeneratePassword(12,2))
            Try { New-ADServiceAccount -Name $svc -ServicePrincipalNames "$svc/$spn.$Global:Domain" -RestrictToSingleComputer -AccountPassword (ConvertTo-SecureString $password -AsPlainText -Force) -PassThru } Catch {}

        }
    }
}

1) The first line that is executing VulnAD-GetRandom -InputList $Global:ServiceAccountsAndSPNs is storing those results the in $selected_service variable. So, what is in $Global:ServiceAccountsAndSPNs?

1
$Global:ServicesAccountsAndSPNs = @('mssql_svc,mssqlserver','http_svc,httpserver','exchange_svc,exserver');

With that, the first line is reading from the global variable and using the Get-Random cmdlet to grab objects out of that array. Then it splits them at position 0 and 1 from the array with the , being the delimiter and assign the randomly selected value to the $svc and $spn variables respectively.

2) Similarly, it’s also grabbing ransom passwords from $Global.BadPasswords global variable to assign to them to the service accounts to be generated in the next step.

3) Once the values are in position, it’s leveraging the New-ADServiceAccount cmdlet recursively in the foreach() loop to register the given account from the global ServiceAccountsAndSPNs array with one of the randomly selected passwords.

Conclusion: this will generate a new service account and register an SPN for it as well. This can allow us to perform Kerberoasting attacks against these service accounts.

serviceaccount

AS-REP Roasting

Here’s the function from the script that’s handling this functionality.

1
2
3
4
5
6
7
8
9
function VulnAD-ASREPRoasting {
    for ($i=1; $i -le (Get-Random -Maximum 6); $i=$i+1 ) {
        $randomuser = (VulnAD-GetRandom -InputList $Global:CreatedUsers)
        $password = VulnAD-GetRandom -InputList $Global:BadPasswords;
        Set-AdAccountPassword -Identity $randomuser -Reset -NewPassword (ConvertTo-SecureString $password -AsPlainText -Force)
        Set-ADAccountControl -Identity $randomuser -DoesNotRequirePreAuth 1
        Write-Info "AS-REPRoasting $randomuser"
    }
}

1) Starting with a for() loop to grab random AD users (maximum of 6) to be stored into $randomuser variable via the VulnAD-GetRandom function, which is simply pulling 6 random users from the global list $Global:CreatedUsers - same goes for 6 random passwords via the global list $Global:BadPasswords

2) It is taking one of these passwords from $Global:BadPasswords and setting the AD account password as one of those passwords via Set-ADAccountPassword cmdlet

3) Next, it’s using the Set-ADAccountControl cmdlet to set the random users with the flag -DoesNotRequirePreAuth which means this will configure this account in a way that Kerberos pre-authentication is not required to logon using that particular account

Conclusion: by enforcing the -DoesNotRequirePreAuth flag, this will allow these accounts to be susceptible to brute forcing. By pre-authentication being required, this would require a user to logon/authenticate with the domain first and thereby obtain a Ticket-Granting-Ticket (TGT). This can allow us to use a tool such as Reubus to identify such accounts and obtain its (encrypted) TGT hashes to then crack offline, hopefully obtain a password, and then profit from there.

DCSync

1
"[+] DCSync Done"

Yet again, here’s the function that’s handling this preparation for DCSync attacks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function VulnAD-DCSync {
    for ($i=1; $i -le (Get-Random -Maximum 6); $i=$i+1 ) {
        $ADObject = [ADSI]("LDAP://" + (Get-ADDomain $Global:Domain).DistinguishedName)
        $randomuser = (VulnAD-GetRandom -InputList $Global:CreatedUsers)
        $sid = (Get-ADUser -Identity $randomuser).sid

        $objectGuidGetChanges = New-Object Guid 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2
        $ACEGetChanges = New-Object DirectoryServices.ActiveDirectoryAccessRule($sid,'ExtendedRight','Allow',$objectGuidGetChanges)
        $ADObject.psbase.Get_objectsecurity().AddAccessRule($ACEGetChanges)

        $objectGuidGetChanges = New-Object Guid 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2
        $ACEGetChanges = New-Object DirectoryServices.ActiveDirectoryAccessRule($sid,'ExtendedRight','Allow',$objectGuidGetChanges)
        $ADObject.psbase.Get_objectsecurity().AddAccessRule($ACEGetChanges)

        $objectGuidGetChanges = New-Object Guid 89e95b76-444d-4c62-991a-0facbeda640c
        $ACEGetChanges = New-Object DirectoryServices.ActiveDirectoryAccessRule($sid,'ExtendedRight','Allow',$objectGuidGetChanges)
        $ADObject.psbase.Get_objectsecurity().AddAccessRule($ACEGetChanges)
        $ADObject.psbase.CommitChanges()

        Set-ADUser $randomuser -Description "Replication Account"
        Write-Info "Giving DCSync to : $randomuser"
    }
}

Back at it again with a for() loop for a maximum of 6 iterations wherein:

1) Getting the Distinguished Name for the domain via LDAP (i.e. {DC=lab,DC=local}) and tossing that into $ADObject

2) Snagging a random users SID via Get-ADUser where $randomuser is coming from the, yet again, global array $Global:CreatedUsers

3) The next three chunks focus on applying three specific GUID’s to the randomly selected user:

  • 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 - DS-Replication-Get-Changes
  • 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2 - DS-Replication-Get-Changes-All
  • 89e95b76-444d-4c62-991a-0facbeda640c - DS-Replication-Get-Changes-In-Filtered-Set

It applies these Extended Rights during the loop, one at a time:

1
2
$ACEGetChanges = New-Object DirectoryServices.ActiveDirectoryAccessRule($sid,'ExtendedRight','Allow',$objectGuidGetChanges)
        $ADObject.psbase.Get_objectsecurity().AddAccessRule($ACEGetChanges)

With the ActiveDirectoryAccessRule() class, specifically the this constructor, the VulnAD-DCSync function will:

Initializes a new instance of the ActiveDirectoryAccessRule class with the specified identity reference, Active Directory Domain Services rights, access rule type, and object type.

It does this with the following parameters/values (as seen in the code snippet above):

  • identity - the randomly-selected users’ SID
  • adRights - ExtendedRight being the control access right
  • type - setting the permission for the Extended Property as “Allow” (see screenshot below)
  • objectType - the given GUID(s) from the list above

Until it finally commits the changes with $ADObject.psbase.CommitChanges()

lablocal

Conclusion: this function of the script is selecting a random user and providing the user with the ability to replicate directory changes; something not typical for a standard Domain User. This sets up an attack path for abuse with this particular user for a DCSync attack.

Blue Team/SOC Perspective

In the previous blog post, I detailed how I also use infrastructure as code to deploy an Ubuntu Server VM as an Elastic Stack to be used as a SIEM of sorts.

By installing and configuring things such as Winlogbeat, Packetbeat, and Filebeat on the Windows Server and Windows 10 endpoints (along with GPO’s for Sysmon, PowerShell, and enhanced audit logging) the goal is to be able to take a look at what artifacts, logs, and noise we’re generating at each step.

I think it’s incredibly useful to understand what the defensive side may see as you use different tools, execute payloads, and anything else in between. Hopefully to provide some insight and ideas as to ways you can blend in, minimize noise, and continue to hone and refine trade craft… or accept “it is what it is” if necessary.

Conclusion

In this first part of the “Attacking the Attack Lab” series, we dissected the Vulnerable-AD script and what it’s doing, besides generating users/groups, to set us up for the actual attack lab engagement.

In the second part (and hopefully the final part) we’ll go through exploiting and taking advantage of these attack paths and we’ll culminate by looking at our Elastic Stack (SIEM) each step of the way to see what noise we’ve been generating within the logs.

Additional Reading

Below is a list of references used to dissect and better understand how the script was making poor configuration changes to some of the DC’s settings and being generous with providing permissions to some users - again, all by design:

This post is licensed under CC BY 4.0 by the author.