🛡️
Hello root
  • Sobre mi
  • Día 1 : Hardware y Software
  • Kali Linux y Virtualizacion
    • Virtualización
    • Cómo instalar Kali-Linux
    • Instalar Kali-linux en pendrive
  • Básicos de Linux
    • Usuarios y permisos en Linux. Primeros comandos
    • Challenge (reto_comandos)
    • Chuleta de comandos Linux
  • Programación (python)
    • Introducción a la programación
    • Python 1 | Variables, print() y funciones básicas
    • Python 2 | Listas y operadores
    • Python 3 | Bucles y funciones
    • Challenge (reto_python_server)
    • Python: Subnet and Host Capacity Calculator
  • Programación C#
    • Variables y condicionales
  • Bucles y colecciones
    • Ejercicio Bucles y colecciones
  • Métodos y funciones
    • Ejercicio math
  • C# Clases
  • Redes
    • Redes y topologías
    • Protocolos y tools
    • Comandos y servicios
  • Criptografía
    • Criptografia. Cifrado e Historia
  • Informes
    • T1043 - Exfiltración de Credenciales Mediante Protocolos de Red Inseguros
Powered by GitBook
On this page
  • Conectarse con ssh
  • User1
  • User2
  • User3
  • User4
  • User5
  • User6
  • User7
  • User8
  • "El trilero"
  • Función decode()
  • Funciones de tiempo y lógica del juego
  • Loop principal del juego
  • Victoria
  • Dónde está la clave?
  • User9
  • User10
  1. Programación (python)

Challenge (reto_python_server)

PreviousPython 3 | Bucles y funcionesNextPython: Subnet and Host Capacity Calculator

Last updated 3 days ago

Conectarse con ssh

Primero verificamos que en la opción de red, ambas máquinas estén en red nat o nat network en inglés.

Iniciamos la máquina víctima con la flecha del start y le damos a "Headless Start" lo que nos permitirá ejecutar la máquina sin GUI.

Luego aparecerá corriendo:

Corremos ip a

Vemos en este caso la ip 10.0.2.15

Escaneamos la red con nmap -sn 10.0.2.15/24

Vamos a tener un output como este:

Hay dos máquinas que son claramente de virtual box

MAC Address: 08:00:27:E2:AE:C5 (PCS Systemtechnik/Oracle VirtualBox virtual NIC)
Nmap scan report for 10.0.2.4
Host is up (0.0014s latency).
MAC Address: 08:00:27:63:B4:E1 (PCS Systemtechnik/Oracle VirtualBox virtual NIC)
Nmap scan report for 10.0.2.15

Como vimos antes al hacer ip a nuestra ip es 10.0.2.15 por lo tanto la máquina víctima del ejercicio es 10.0.2.4

Corremos ssh user1@10.0.2.4 y cuando le demos a enter nos pedirá es password. Que en este caso es St@rt1ng Si lo hicimos correctamente estaremos dentro de la máquina.

User1

Hacemos un ls y luego un cd Documentos para ver el ejercicio de este usuario.

Por defecto asumiremos que en cada usuaario hacemos estos pasos ya que todos tienen la misma estructura. Una vez hecho el su userX vamos a asumir que nos movemos a la carperta de ese usaurio. Que podriamos hacerlo con cd /home/userX/Documentos donde X es el usuario con el que estamos trabajando en ese momento.

Este nivel es facilito. Ejecutamos python3 nivel1.py y ya nos da el password como output

Se asume que luego de ver Challenge (reto_comandos) ya investigamos las máquinas con ls y nos sabemos mover y demas. Si no lo sabes hacer, volve a esa maquina.

Password de user2

S0Easy&Gu1d3d

Ahora hacemos su user2 ponemos el password, y vamos a su home con los comandos que vimos antes


User2

Verificamos que somos el usuario correcto y estamos en el lugar correcto con pwd y whoami

Asumimos que estos comandos se corren antes de cada user. Solo se mostrarán esta vez

Si corremos el comando python3 nivel2.py para ver que hay dentro. No nos aparece nada útil. Solo una carga y un fallo.

Qué podríamos hacer para avanzar?

Respuesta

Abrir el archivo para ver su contenido. Cómo podemos ver su contenido?

Respuesta siguiente

Podemos correr cualquier lector de texto. Como cat nivel2.py o mejor aun con less nivel2.py o cualquier otro comando de lectura.

Luego de leer el archivo de python deberiamos haber visto el password

Password de user3

N0C0mm3nts!


User3

Asumimos que sabemos leer los archivos .py como vimos arriba. Vez que pasa en el archivo?

Respuesta

Si al ejecturar el comando, le pasamos devadmin como user, y de password le pasamos H4rdC0ding&F4il Nos dará el password del user4


User4

Si analizamos este archivo de .py como podemos sacar el password?

Hay que pasarle al programa una determinada cantidad y tipo de parametros para que nos de el password. Esto tiene dos condiciones.

if (len(args)%2 == 0) Si el resultado de la división de los argumentos en 2 es de resto (Osea si la cantidad de argumentos es par)

and (args[4] == 'debug' Y si el argumento de indice 4 es 'debug'

Entonces nos da el password del user5.

Recordemos que en programación se empieza a contar por el 0.

El argumento [4] es el quinto argumento

[0] [1] [2] [3] [4]

Y sepamos también que para python, el archivo en si es el argumento [0]

Respuesta

python3 nivel4.py [1] [2] [3] debug [5]

Siendo el argumento [0] el archivo nivel4.py

Siendo debug el argumento [4]

Siendo [5] el argumento número 6 para que sean pares los argumentos que le pasamos


User5

Si ejecutamos el python con python3 nivel5.py nos dirá que no puede ayudarnos.

Si analizamos el código del python qué vemos?

Respuesta

El if user_response == key nos dice que si ingresamos lo que el programa quiere, nos dará el password del siguiente usuario. Qué es key?

Qué es key?

key es una variable a la cual se le asigna un valor particular.

  1. response = requests.get(...) Se realiza una solicitud HTTP GET usando la librería requests. El resultado es un objeto requests.Response.

  2. response.text Es una propiedad del objeto response que contiene el cuerpo de la respuesta como un string de texto plano.

  3. str(response.text) Convierte el contenido a string. En este caso es redundante porque response.text ya es un string.

  4. .split('\n') Divide el string en una lista de líneas, usando el carácter de salto de línea () como separador. Ejemplo: 'a\nb\nc' → ['a', 'b', 'c']

  5. [-2] Toma el segundo elemento de la lista resultante contando de atras hacia adelante. Osea invertido.

  6. .strip() Elimina espacios en blanco, tabulaciones o saltos de línea al principio y al final del string.

Resultado final: key contiene la penultima línea del texto descargado desde la web, sin espacios ni caracteres invisibles adicionales.

Para ver que hay dentro del Response. Podemos descargarlo nosotros y guardarlo en un file con el siguiente comando:

wget URL

Y luego vemos las últimas lineas con tail (es como cat pero para ver las últimas lineas.) Y pasarselo a head para ver la primera linea de ese output de tail

(Esto es opcional, también puedes abrir el archivo con cat y leer la penúltima línea.

User6

Este usuario está bastante complicado si no nos llevamos von python. Pero son unas pocas líneas que tendremos que escribir. O también las podemos escribir en bash.

Si la función verify_win() devuelve True nos da el password del user7

Verify win() lo que se fija es si el file .registered_users.db tiene un millón de líneas.

Si somos el usario 1.000.000 nos da el password. Para ser el usuario un millon, tenemos que tener un archivo que tenga 999.999 lineas. Y con este programa, agregar el mail 1.000.000

Para ello podemos resolverlo escribiendo un script en python, o en cualquier otro lenguaje, que nos genere un archivo de 999.999 lineas.

Este podría ser un ejemplo en python:

mail = "shanick@muyu.es\n"
with open(".registered_users.db", "w") as file:
    for _ in range(999999):
        file.write(mail)
  1. mail = "shanick@muyu.es\n" Se define una variable de tipo string que contiene un correo electrónico seguido de un salto de línea (), para que cada vez que se escriba en el archivo, quede en una nueva línea.

  2. with open(".registered_users.db", "w") as file: Se abre (o crea) un archivo llamado .registered_users.db en modo escritura ("w").

    • Si el archivo ya existe, su contenido será sobrescrito.

    • El with garantiza que el archivo se cierre correctamente al finalizar el bloque.

  3. for _ in range(999999): Se inicia un bucle que se ejecuta 999.999 veces.

    • La variable _ es una convención para indicar que el valor del índice no importa.

  4. file.write(mail) En cada iteración del bucle, se escribe el contenido de mail en el archivo. Como mail termina en , cada entrada quedará en una línea separada.

Resultado final: El archivo .registered_users.db contendrá 999.999 líneas, todas con el texto shanick@muyu.es.

Verificamos que nuestro archivo haya quedado bien

Hacerlo con yes en vez de con python

Hay una manera eficiente y mejor de hacerlo. Es usando yes con el siguiente comando:

yes "shanick@muyu.es" | head -n 999999 > .registered_users.db

  1. yes "shanick@muyu.es" Este comando imprime infinitamente la cadena "shanick@muyu.es" seguida de un salto de línea.

  2. | Es un pipe. Toma la salida del comando anterior (yes) y la pasa como entrada al siguiente comando (head).

  3. head -n 999999 Este comando toma solo las primeras 999999 líneas de la entrada que recibe. En este caso, las 999999 primeras líneas generadas por yes.

  4. > Es un operador de redirección. Toma la salida final del head y la escribe en un archivo.

  5. .registered_users.db Es el archivo de destino. Si no existe, se crea. Si ya existe, se sobrescribe con el nuevo contenido.

Resultado: Se crean exactamente 999.999 líneas en el archivo .registered_users.db, cada una con shanick@muyu.es.

Hacerlo con bash en vez de con python o yes

  1. for i in {1..999998}; do Inicia un bucle for en Bash.

    • {1..999998} usa la sintaxis de expansión de secuencia de números desde 1 hasta 999998.

    • i es la variable que va tomando esos valores en cada iteración.

    • El do abre el bloque de instrucciones que se ejecutan en cada vuelta del bucle.

  2. echo "$i" >> .registered_users.db En cada iteración, imprime el valor actual de i (del 1 al 999998).

    • echo "$i" genera una línea con ese número.

    • >> agrega esa línea al final del archivo .registered_users.db (sin sobrescribir lo anterior). El archivo se va construyendo línea por línea.

  3. done Marca el final del bloque del bucle. Cuando se llega a este punto, Bash vuelve al inicio del bucle y toma el siguiente número.

Resultado: El archivo .registered_users.db contendrá 999.998 líneas, cada una con un número del 1 al 999998.

Password del user7

0neM1llion


User7

Para esta máquina va a ser más fácil si tenemos dos consolas. Por lo que vamos a apretar cntrl + shift + R para dividir la consola, y vamos a hacer login de nuevo pero esta vez en el usuario 7.

ssh user7@10.0.2.4 password: =0neM1llion

Nos debería quedar algo asi:

Si abrimos con less u otro lector el archivo nivel7_srv.py veremos el siguiente detalle:

Si nos conectamos con el otro file, podremos establecer una conexión entre un falso server y un "cliente"

Ejecutamos el server en una pestaña de la terminal con python3 nivel7_srv.py y ejecutamos en la otra terminal el cliente con python3 nivel7_cli.py

Esto nos dará el password del usuario 8.

Password del User8

TCP!S0ck3t


User8

Si analizamos lo que tiene el script de python, esta vez nos encontramos con un juego.

"El trilero"

En este juego, si lo ejecutamos, la consola nos ira pidiendo que ingresemos numeros para adivinar donde esta el "vaso indicado". Si bien parece random donde pone los vasos, no lo es. Está basado en un algorítmo que toma como semilla la hora actual del dispositivo.

Función decode()

  • Decodifica un mensaje en base64 que contiene una clave secreta.

  • Solo se ejecuta si el jugador gana el juego.


Funciones de tiempo y lógica del juego

def timeNow():
    ...
def getNewPosition(timeexec, round):
    ...
  • timeNow(): devuelve la hora actual en formato "HH:MM:SS".

  • getNewPosition(): calcula la posición de la bolita usando la hora actual y el número de ronda, generando un valor entre 1 y 3.


Loop principal del juego

for i in range(5):
    ...
  • El jugador debe adivinar 5 veces seguidas.

  • Si falla, pierde inmediatamente.

  • Si acierta, se muestra una frase motivacional.


Victoria

if win == 5:
    print("Aquí tienes la pass de user9")
    loading()
    print(decode())
  • Si el jugador gana 5 veces seguidas, se decodifica y muestra la clave secreta.


Dónde está la clave?

Cada vez que lo ejecutes tomará tu hora actual como base para el agorítmo. Y luego entre funciones que se van pasando se ejecuta el siguiente algorítmo:

La función getNewPosition() basicamente tome como variable base el índice de la hora actual, lo divide en 3 y toma el resto.

Imaginando que nuestra hora es 22:42:36

En el round 0, osea el primer round, la ecuación quedaría asi:

base = timeexec.split(':')[round%3]

El round es 0, por lo que el índice equivale a 22. Si a 22 le hacemos módulo 3 nos queda 1.

Reempazamos

base = timeexec.split(":")[22%3]

osea que base = 1

Luego resolvemos la variable position

position = (int(base)+round)%3

Como base = 1, resolvemos:

position = (1+0)%3

Osea que position es 1. Y por último la línea del final hace return str(position + 1) osea que el primer resultado es 2

Si hay algo que nos enseña la programación es que las tareas manuales se pueden automatizar.

Como no podemos modificar el archivo actual debido a las reglas, ni agregar ficheros. En nuestra máquina local, vamos a crear un script de python que resulve los vasitos por nosotros.

Hacemos un script ejecutando vim solve_time.py

Y escribimos lo siguiente:

import sys
if len(sys.argv) > 1:
    time = sys.argv[1]

print(f"La hora indicada es: {time}")
for i in range(5):
    base = time.split(":")[i%3]
    position = (int(base)+i)%3
    print(f"La solución del round {i+1} es {position+1}")

Guardamos nuestro script con :wq y ejecutamos. python3 "22:49:15" < O la hora que corresponda. Y esto nos dará la solución para cada ronda.

Constraseña user9

N0tS0Rand0m!


User9

Hacemos login del user9 con el password N0tS0Rand0m!

Si ejecutamos python3 nivel9.py entrará en una aplicación de consola falsa que nos da opciones y comandos.

Si apretamos 0 hay un output. Si apretamos 1 hay otro output. Y asi sucesivamente.

Al seleccionar la opcion 1 vemos que el output es Hex(Reverse(password)) Esto es una pista clave.

Si ponemos una letra en vez de un numero, nos quita del programa.

Vamos a ver como funciona por dentro el script de python

Corremos vim nivel9.py

Opcional: Podemos correr syntax on una ve dentro de vim para que tenga colores y entienda que es un archivo python

Hay una función bastante clave que se llama get_privs() y por lo que vemos en el interior, está abriendo un archivo .json y está cargando el valor "privs" de ese archivo.

Al final del script, también podemos ver que dependiendo el valor de privs. Ejeutará una cosa u otra.

Salimos de vim con :q! y enter.

Si hacemos un ls veremos un archivo .json al lado del script de python. Vamos a ver que tiene dentro.

Hay una key que se llama "privs" y su valor es "high" . Excelente! Sabemos que si modificamos estos privilegios el programa de python se comportara diferente.

Usamos vim o cualquier editor de texto para cambiar ese valor de high por medium y a ver que pasa.

Ahora si ejecutamos el programa y le damos a la opcion 0 nos dice lo siguiente:

User: user10 - Encoded pass: 6e6957267376697250796669646f4d

Aqui esta el password de nuestro user10 !

Pero claro. Esta en un formato raro...

Gracias a la pista del punto anterior

Hex(Reverse(password))

Pareciera que si le aplicamos una funcion que nos saque el valor desde un hexadecimal y luego lo revierta, tenemos el password!

Vamos a ello. Nos copiamos el valor del password 6e6957267376697250796669646f4d

Ejecutamos python con python3

Nos aparecerá el intérprete

>>>

Guardamos el password escribiendo password = "6e6957267376697250796669646f4d" y le damos a enter.

Ahora decodeamos el hexa de este password con la siguiebnte funcion y guardamos el valos en decoded_password.

decoded_password = bytes.fromhex(password)

Le damos a enter. Ahora si ejecutamos un print, veremos el password!

print(decoded_password)

Pero está al revés! Vamos a arreglarlo.

reversed_password = decoded_password[::-1]

Y ahora si. Hacemos un print(reversed_password) y nos aparecerá el password!

También podemos crear un script en python que automatice los comandos que corrimos recién:

Creamos nuestro script con vim solve.py y escribimos lo siguiente:

coded_password = "6e6957237376697250796669646f4d"
hex_password = bytes.fromhex(coded_password)
inverted_password = hex_password[::-1]
print(inverted_password)

Y esto nos decodificará el password.

Cuando ves un b'...' al imprimir en Python, significa que estás trabajando con un objeto de tipo bytes y no con una cadena de texto (str). Para mostrarlo como texto legible, simplemente usá .decode(). Por ejemplo:

print(reversed_password.decode())

Password user10

ModifyPrivs&Win

User10

Con esto podemos hacer sudo su e ingresar el password. Luego podemos ejecutar groups y veremos que pertenecemos a la elite ;)

Y si le pasamos 'user' como comando. Nos dará un

Que la terminal te acompañe

🏹
OTP
El paso a paso