Mostrando entradas con la etiqueta Seguridad. Mostrar todas las entradas
Mostrando entradas con la etiqueta Seguridad. Mostrar todas las entradas

miércoles, 25 de diciembre de 2013

Separación de privilegios en OpenSSH

Muchos servicios del sistema operativo requieren privilegios especiales para poder ejecutar sus respectivas tareas. Un error de programación en un servicio que posea tales privilegios abre la puerta para comprometer al sistema mediante la adquisición no autorizada de permisos. En el peor de los casos, un atacante remoto podría alcanzar privilegios de superusuario.
[Mediante la separación de privilegios], aun cuando existan errores en partes no privilegiadas, los mismos no pueden utilizarse para escalar privilegios. [Este procedimiento] es especialmente útil para servicios del sistema que autentican usuarios.
El principio básico de la separación de privilegios consiste en reducir la cantidad de código que se ejecuta con permisos especiales sin afectar o limitar la funcionalidad del servicio. Esto se logra al dividir una aplicación en dos o más partes: una de ellas (denominada monitor) es ejecutada con privilegios y la/s otra/s (esclavo/s) sin ellos. Esto disminuye la exposición a bugs en el código que es ejecutado con privilegios. Idealmente, la única consecuencia que resulta de un error en un servicio que esté corriendo con separación de privilegios es la denegación del servicio al atacante mismo.
La línea del archivo de configuración de sshd que habilita la separación de privilegios es la siguiente:
Con esta configuración, estos son los procesos relacionados con ssh:
La salida del comando ps -ef muestra los siguientes datos:
  1. UID (User ID)
  2. PID (Process ID)
  3. PPID (Parent Process ID)
  4. C (Tiempo de CPU utilizado recientemente por el proceso, en términos de ciclos de reloj, más información aquí)
  5. STIME (Start TIME)
  6. TTY (terminal en la que está corriendo el proceso, una ? indica que el proceso es un daemon que está ejecutándose en segundo plano)
  7. TIME (tiempo de CPU utilizado por el proceso desde que fue iniciado, en términos de minutos y segundos)
  8. CMD (argumentos de la línea de comandos que iniciaron el proceso)
En la imagen anterior vemos que el demonio ssh (PID 3287) fue iniciado por init (PID 1). A su vez, sshd inició el monitor (parte de la aplicación que posee privilegios, PID 3354), el cual luego de la autenticación hizo lo propio con la sesión de usuario remota (PID 3430) creando una pseudo-terminal para la misma.
Este ejemplo muestra dos operaciones que requieren privilegios de superusuarios en la máquina remota:
  • Antes de la autenticación, el monitor es la parte de la aplicación que chequea la contraseña provista por el usuario (o la clave pública) contra el archivo de contraseñas (/etc/shadow) o contra la clave pública del cliente previamente guardada en el servidor, según corresponda. Si la autenticación es exitosa, se crea la sesión de usuario; caso contrario, se niega el acceso.
  • Después de la autenticación, se crea una pseudo-terminal para la sesión de usuario.
De esta manera, el monitor y el esclavo corren separadamente y se reduce considerablemente la posibilidad de un ataque por escalación de privilegios.
Ahora voy a deshabilitar la separación de privilegios y reiniciar el servidor ssh, para luego verificar los procesos nuevamente:
En este caso podemos ver que tanto sshd como el monitor fueron iniciados directamente por init, y aunque se lanzó la sesión remota de usuario correctamente, no se dispone de la "interfaz" de protección entre las peticiones efectuadas y la aplicación con privilegios. De esta manera, si un atacante lograra encontrar un bug en el código, podría fácilmente explotarla para escalar privilegios sobre el sistema.
Sin embargo, se puede ver en este caso que el monitor retuvo su PID y solamente cambiaron los correspondientes al esclavo y a sshd. Al inspeccionar el estado de los procesos luego de finalizar la conexión anterior e iniciar una nueva, podemos ver lo siguiente:
Por último, vuelvo a editar el archivo /etc/ssh/sshd_config para volver a utilizar separación de privilegios (recordar que más allá de reiniciar el servidor ssh, los cambios recién serán aplicados a la próxima conexión):

Nota: La teoría de este post está basado en el paper "Preventing Privilege Escalation" por Niels Provos, Markus Friedl, y Peter Honeyman, el cual puede descargarse desde este link.

viernes, 22 de marzo de 2013

Configurando NIS (Network Information Service) - Parte 2: El cliente

Continuando con la implementación de NIS, ahora pasamos a configurar un cliente que podrá utilizar la información contenida en /etc/passwd (situado en el servidor). Los detalles de cada operación se pueden ver en la primera parte (Configurando el servidor):

1) Instalar portmap.

2) Actualizar portmap.

3) Instalar y configurar NIS con el nombre de dominio elegido anteriormente.

4) Editar el archivo /etc/hosts agregando el nombre del servidor de NIS y su FQDN (Fully Qualified Domain Name) para resolver nombres en caso de no utilizar DNS o de una falla en dicho servicio:
192.168.0.10    debian  debian.gorditolinuxero.com.ar
5) Editar el archivo /etc/yp.conf
# ypserver ypserver.network.comdomain gorditolinuxero.com.ar server debian.gorditolinuxero.com.ar
(salvo la línea que está comentada, el resto debe ir en la misma línea)
6) Editar el archivo /etc/nsswitch.conf
passwd:         nis compatgroup:          nis compatshadow:         nis compat
7) Modificar los permisos por defecto del directorio /home (esto se puede retocar luego!) para que Nautilus (o el explorador de archivos que corresponda) y XWindows permitan a los usuarios loguearse mediante una interfaz gráfica: chmod 777 /home

LISTO :).

Configurando NIS (Network Information Service) - Parte 1: El servidor

Nota: La práctica desarrollada en este post está basada en Setting up NIS (Part 1 of 2): Configuring a NIS SERVER
NIS (Network Information Service = Servicio de Información de Red) permite distribuir la información contenida en los archivos /etc/passwd y /etc/groups de un servidor a todos los demás equipos de la red, haciendo que la misma parezca transparente para los usuarios; es decir, que toda la red se comporte como si fuera un solo equipo. También permite distribuir los datos de resolución de nombres contenidos en el archivo /etc/hosts del servidor cuando por la simplicidad de la red no se considere necesario la puesta en marcha de un servicio de DNS dedicado.
Originalmente, NIS fue desarrollado por Sun Microsystems bajo el nombre de Yellow Pages, pero debido a que Yellow Pages es una marca registrada de British Telecom, luego se le cambió el nombre; sin embargo, las siglas "yp" todavía se encuentran en varios de los comandos relacionados con NIS.
Funcionalmente, NIS utiliza demonios (servicios, o procesos no interactivos) y una base de datos para proveer autenticación centralizada en una arquitectura cliente-servidor en sistemas basados en Unix, como GNU/Linux, de manera similar que Active Directory en Microsoft Windows.
Una vez puesto en marcha NIS, es importante asegurarlo mediante cifrado y la configuración apropiada utilizando los archivos hosts.allow y hosts.deny.

PASOS PARA CONFIGURAR EL SERVIDOR (ejecutar los comandos como root o con privilegios de superusuario)

1) Instalar portmap: aptitude install portmap

2) Actualizar la configuración por defecto de portmap: update-rc.d portmap defaults 10
El comando update-rc.d nos permite automatizar el proceso de creación y borrado de enlaces a los scripts de inicio, con en fin de iniciar/parar servicios. El argumento "10" se utiliza para hacer que arranque antes que NIS, que según el listado del directorio /etc/rc2.d (correspondiente al nivel de ejecución o runlevel 2 que es con el que inicia Debian por defecto):
S15nis -> ../init.d/nis
Según el man page the update-rc.d:
Si  se  usa la opción defaults entonces update-rc.d creará enlaces para arrancar los servicios en los niveles de ejecución  2345  y  parar  los servicios  en  los  niveles  de  ejecución  016.  Por omisión todos los enlaces tendrán el código de secuencia 20, pero  esto  puede  cambiarse especificando  uno  o  dos argumentos NN.  Un argumento cambia el valor por omisión del código de secuencia tanto para los enlaces de  arranque como para los de parada, y si se proporcionan dos argumentos el primero cambia el código de los enlaces de arranque y  el  segundo  el  de  los enlaces de parada.
Si el comando anterior arroja el siguiente error:
insserv: warning: current start runlevel(s) (2 3 4 5 S) of script `portmap' overwrites defaults (2 3 4 5).
hay que ejecutar antes
update-rc.d -f portmap remove
para quitar el enlace simbólico de portmap al script de inicio (/etc/init.d/portmap), y luego recrearlo utilizando:
update-rc.d portmap defaults 10
3) Instalar NIS: aptitude install nis
Al realizar la instalación, se pedirá ingresar el nombre del dominio que se utilizará:


4) Editar el archivo /etc/defaults/nis: modificar las líneas indicadas con los cambios que sean necesarios

# Are we a NIS server and if so what kind (values: false, slave, master)?
NISSERVER=master

# Are we a NIS client?
NISCLIENT=false

5) Editar el archivo /etc/ypserv.securenets: modificar la línea indicada con los cambios que sean necesarios
# This line gives access to everybody. PLEASE ADJUST!
255.255.255.0   192.168.0.0

6) Editar el archivo /var/yp/Makefile: modificar la línea indicada con los cambios que sean necesarios
ALL =   passwd shadow group hosts rpc services netid protocols netgrp

7) Reiniciar portmap: service portmap restart

8) Reiniciar NIS: service nis restart

9) Invocar /usr/lib/yp/ypinit -m para construir la lista de los hosts que van a ser los servidores NIS en la red:

At this point, we have to construct a list of the hosts which will run NIS
servers.  debian.gorditolinuxero.com.ar is in the list of NIS server hosts.  Please continue to add
the names for the other hosts, one per line.  When you are done with the
list, type a <control D>.
next host to add:  debian.gorditolinuxero.com.ar
next host to add:

10) Agregar en el servidor los usuarios y los grupos que los clientes van a usar en toda la red. Esto se lleva a cabo mediante la creación común de usuarios, incluida la asignación de contraseñas.

11) Compilar los usuarios, los grupos, y las contraseñas en la base de datos de NIS: cd /var/yp; make

LISTO :). Ahora a configurar los clientes.

miércoles, 5 de diciembre de 2012

Firmas y certificados digitales

Una firma digital es un esquema matemático que se utiliza para demostrar la autenticidad de un mensaje o documento digital. Una firma digital válida le da al receptor la garantía que el mensaje ha sido creado por un emisor conocido, y que no ha sido alterado en el camino. Las firmas digitales se emplean por lo general en la distribución de software, en transacciones financieras, y en otros casos en los que sea importante detectar falsificaciones o manipulación indebida. (Resumen traducido de Digital Signature, Wikipedia).

Un certificado digital (también conocido como certificado de identidad) es un documento electrónico que utiliza una firma digital para vincular una clave pública con una identidad determinada - tal como el nombre de una persona o de una organización, sus direcciones, etc. Este certificado también puede usarse para verificar que una clave pública le pertenece a un individuo específico. (Resumen traducido de Public key certificate, Wikipedia)

Generando una firma digital mediante DSA (Digital Signature Algorithm):

Primera fase: Elección de los parámetros del algoritmo, los cuales pueden ser compartidos por varios usuarios del sistema.
(Nota: /dev/random es un archivo especial que se encuentra presente en sistemas operativos basados en Unix y se emplea como un generador de números aleatorios mediante el acceso a "ruido ambiental" recogido de drivers de dispositivos y otras fuentes).


Segunda fase: Cálculo de clave pública y privada para un usuario determinado.


Creo el archivo "archivo.sha1" con el hash sha1 de "archivo" (por eso filtro con awk la primer columna a fin de utilizar el hash propiamente dicho, ver las diferencias en las imágenes siguientes. Con print $0 muestro todo el contenido del archivo sin filtrar, pero a mí me interesa únicamente el hash, por ese motivo empleo print $1). Para esto se puede utilizar tanto el comando sha1sum como openssl dgst -sha -sha1.



Creo la firma digital del hash (archivo.sha1) correspondiente al archivo "archivo", con mi clave privada. Luego verifico con mi clave pública que la firma "firma" es la que corresponde al hash que contiene archivo.sha1:


De esta manera, si se pudo verificar la firma con la clave pública del emisor, significa que éste último es el único que puede haberla creado a partir de su clave pública.

Por último, en este link hay un excelente recurso para comprender los conceptos de clave pública y privada, y firmas / certificados digitales.

lunes, 3 de diciembre de 2012

Funciones hash

Una función hash genera una cadena de caracteres a partir de un mensaje o de un archivo para determinar si el mismo ha sido modificado en la cadena de transmisión (de ser así, el resultado de la función cambia) y de esa manera asegurar su integridad y autenticidad.

Para evitar la posibilidad de que tanto el mensaje (archivo) como su hash correspondiente sean modificados en el camino, el emisor puede utilizar un cifrador asimétrico para encriptar el hash con una clave pública. El problema con esto es que cualquiera que tenga la clave pública puede interceptar el mensaje con su hash, modificarlos, y enviarlos nuevamente.

La manera de evitar este último incoveniente es combinar un algoritmo simétrico con uno asimétrico, generando un secreto compartido (clave simétrica) entre emisor y receptor, el cual si bien no va a ser usado para encriptar, el emisor va a concatenar esta clave al contenido del mensaje original, y a eso le va a calcular el hash, para luego encriptar este último con la clave pública. Sin embargo, lo que se envía es el mensaje original sin la clave concatenada, y el hash encriptado. Cuando se recibe, se descifra el hash enviado, se concatena el mensaje con el secreto compartido, se le calcula el hash en destino y se calcula con el que se recibió - la igualdad de ambos asegura la autenticidad y la integridad de la transmisión.

En resumen:
  1. Se genera un secreto compartido entre emisor y receptor.
  2. El emisor concatena el mensaje original junto con el secreto compartido, y calcula el hash del resultado.
  3. Se envía el mensaje original y el hash obtenido en el punto 2 de forma separada.
  4. En el destino, se concatena el mensaje recibido y el secreto compartido.
  5. Se calcula el hash del resultado obtenido en el punto 4.
  6. Se compara el hash del punto 2 con el del punto 5.
MD5 utiliza hashes de 128 bits. Se considera que, dadas las capacidades de cálculo actuales, puede llegar a ser vulnerable o que existan dos archivos cuyos hashes sean idénticos.
SHA-1 emplea hashes de 160 bits, y el SHA-512 de 512 bits.

Ejemplos:
  • Creo el archivo llamado "archivo" y le agrego la cadena "Yo uso CentOS :)".
  • Calculo el hash MD5 de archivo.
  • Le agrego un espacio (" ") a "archivo".
  • Vuelvo a calcular el hash MD5 y comparo los hashes obtenidos.
  • Creo el archivo "archivo" con el texto original ("Yo uso CentOS :)") y calculo los hashes SHA-1 (160 bits) y SHA-2 512 de 512 bits.


jueves, 29 de noviembre de 2012

Conceptos de criptografía (2da parte)

Cifradores asimétricos: Permiten encriptar un mensaje utilizando una clave y descifrarlo utilizando otra (claves pública y privada, respectivamente). En otras palabras, si alguien quiere enviarme un mensaje cifrado con mi clave pública (la cual puede distribuirse libremente), solamente yo voy a poder desencriptarlo utilizando mi clave privada (que es estrictamente personal y no debe compartirse bajo ningún punto de vista).
La generación de estas claves se basa en cálculos de números primos y logaritmos.

El algoritmo RSA es el más utilizado en el cifrado asimétrico (ver este link para una descripción completa de su funcionamiento con ejemplos).

Genero mi clave privada, obtengo la clave pública a partir de la misma, y la muestro:

Fig. 1: Generación de claves


Ahora voy a probar en encriptar un mensaje con esta clave pública (pruebo desde una máquina virtual simulando un emisor, que también podía ser otro usuario del mismo equipo)...

Fig. 2: Cifrado de mensajes

  para luego descifrarlo utilizando mi clave privada: 

Fig. 3: Desencriptar mensajes ("Yo uso Debian :)" es el contenido de "archivo", que me acabo de dar cuenta que no salió en la captura de pantalla correspondiente a la Figura 2)

Para tener en cuenta: al compartir la clave pública lo conveniente es distribuir el archivo pub.pem directamente en vez de "copiar y pegar" sus contenidos en un archivo vacío y darle el mismo nombre (al principio probé de esta última manera, pero al parecer por una cuestión de formato me daba el error "Unable to load Public Key").

martes, 27 de noviembre de 2012

Conceptos de criptografía (1era parte)

La criptografía actualmente se encarga del estudio de los algoritmos, protocolos y sistemas que se utilizan para dotar de seguridad a las comunicaciones, a la información y a las entidades que se comunican (José Pastor Franco, Miguel Ángel Sarasa López, José Luis Salazar Riaño,"Criptografía digital: fundamentos y aplicaciones",Ed. Prensas Universitarias de Zaragoza, 1998), permitiendo que los mensajes puedan ser leídos (descifrados) únicamente por el emisor de los mismos y el (o los) destinatario(s) deseado(s), pudiendo estos últimos tener la seguridad de que dichos mensajes proceden de quienes dicen ser los emisores, y que no han sido alterados en el camino. De esta manera, las palabras claves para la criptografía son privacidad, integridad, y autenticidad.




Cifradores simétricos: encriptan y desencriptan la información utilizando la misma clave.

Por ejemplo, digamos que se quiere enviar el texto "gabriel" como mensaje cifrado, utilizando la cadena "0123" como clave.



Caracteres ASCII
Hex
gabriel (código ASCII tomado de aquí) 67  61  62  72  69  65  6C
0123012 (la clave se repite secuencialmente hasta abarcar todos
los caracteres que se desean encriptar)
30  31  32  33  30  31  32
Algoritmo de cifrado: OR Exclusivo (Mensaje cifrado) 57  50  50  41  59  54  5E 
Tabla 1: Encriptación del mensaje


Caracteres ASCII
Hex
Mensaje cifrado 57  50  50  41  59  54  5E
0123012 (la clave se repite secuencialmente hasta abarcar todos
los caracteres que se desean encriptar)
30  31  32  33  30  31  32
Algoritmo de descifrado: OR Exclusivo (Mensaje original) 67  61  62  72  69  65  6C
Tabla 2: Desencriptación del mensaje

Ejemplo 1: Encriptando con RC4 (algoritmo de cifrado simétrico por stream) mediante la API de OpenSSL

a) Envío la cadena de caracteres "HolaMundo" al archivo y lo leo con "cat":


b) Encripto el archivo "mensaje" tomándolo como entrada, y obteniendo "mensaje.enc" como salida (cuando pide la contraseña de encriptación se puede poner cualquier cadena de texto, yo puse "0123"):


c) Compruebo la encriptación del archivo:


d) Desencripto y comparo:


Ejemplo 2: Encriptando con 3DES (algoritmo de cifrado simétrico por bloques, que cifra un cierto mensaje 3 veces utilizando claves aleatorias de 64 bits, razón por la cual es un tanto "lento").


Ejemplo 3: Lo mismo con el algoritmo -más moderno y rápido- AES (cifrado simétrico por bloques) de 256 bits en modo CBC:


Ejemplo 4: Finalmente, el mismo procedimiento pero esta vez utilizando el algoritmo de cifrado simétrico por bloques Blowfish (que por defecto utiliza claves de 448 bits):