#4sysadmins

Inicio » LPIC-1 Capítulo 10

LPIC-1 Capítulo 10

EN ESTE CAPÍTULO SE ABARCAN LOS SIGUIENTES OBJETIVOS DEL EXAMEN:

  • 110.1 : Realizar tareas administrativas de seguridad (3)
  • 110.2 : Configurar la seguridad del host (3)
  • 110.3 : Proteger los datos mediante técnicas de encriptación (3)

 

Proteger el sistema

Hoy en día la mayoría de los ordenadores se encuentran conectados a Internet. Estar conectado a Internet aporta innumerables ventajas a nuestra sociedad, es como salir al exterior pero sin realmente dar un paso de donde nos encontramos. Esto, sin pensarlo, nos parece incluso seguro, nos da la sensación de ser menos vulnerables pero realmente es todo lo contrario, estar conectado a Internet significa prácticamente exponer en cierta forma nuestro ‘yo‘ mas íntimo, a través de fotografías, vídeos, conversaciones, datos bancarios, etc… es por ello que cada día debemos de ser mas conscientes y dedicar mas tiempo, esfuerzo o economía a protegernos del exterior.

En las siguientes secciones veremos algunos puntos básicos a tener en cuenta cuando utilizamos un dispositivo tanto con acceso a red como si nos limitamos a un uso local. Tener un ‘agujero‘ de seguridad en nuestro dispositivo, en el mejor de los casos significaría que solo ese dispositivo se vería comprometido pero en la mayoría de las veces, solamente se trata de una puerta de acceso al interior de nuestra red, red en la que podemos tener servidores con importantes servicios ejecutándose o numerosa información personal que de ninguna de las maneras queremos que sea accedida por terceras personas. Existen muchos puntos a tener en cuenta para ser realmente eficaces con respecto a la posibilidad de parar a un atacante pero este curso abarcará solamente aquellos que se encuentran al nivel exigido para aprobar la certificación y que con serán los siguientes:

Administrar la seguridad local

  • Crear contraseñas fuertes contra ataques de fuerza bruta
  • Control de acceso al sistema
  • Límites y cuotas de usuarios
  • Permisos sobre archivos: nosuid, nodev, noexec
  • Habilitación de hosts
  • Módulos PAM

Administrar la seguridad de la red

  • Técnicas utilizadas en los ataques y contramedidas
  • Controlar los puertos de red que se están utilizando
  • Comprobar las conexiones de red existentes y los servicios que las provocan
  • Utilizar un súper servidor con el que poder limitar el acceso de una forma mas controlada
  • Protección mediante Firewalls
  • Sistemas de detección de intrusos (IDS)

 

 Administrar la seguridad local

 

El uso de contraseñas

Quizás el primer paso para acceder a un sistema, independientemente de la técnica utilizada para localizar el sistema en cuestión y sus vulnerabilidades (de ser un ataque en red) como el uso de la ingeniería social, un keylogger o cualquier otro método para tomar el control de un sistema de forma local, es acceder a la cuenta de un usuario de manera que se obtenga un punto de partida para continuar con un ataque, ya sea al propio sistema o equipos conectados a la red. Un equipo sin contraseña o con una contraseña lo suficientemente débil como para ser averiguada en poco tiempo mediante fuerza bruta allanaría el terreno aportado este punto necesario para tomar el control. Es por ello que debemos de seguir unas pautas para generar una contraseña de cuenta lo suficientemente robusta como para ser vencida rápidamente por un ataque de fuerza bruta, además no basta con generarla una vez si no que lo conveniente sería ir mortificándola cada cierto tiempo de manera que si un atacante obtuvo nuestra contraseña, se encuentre con que somos como mínimo una victima poco perezosa, en este caso deberá de volver a intentar tener acceso al sistema. Este será nuestro primer pequeño muro a construir. Algunas de las pautas a seguir para evitar riesgo con respecto a las contraseñas serían:

  • Utilizar contraseñas seguras: Podemos utilizar alguna técnica para generar nuestra contraseña por ejemplo, crear una combinación aleatoria de letras mayúsculas y minúsculas, dígitos y signos de puntuación. Una buena forma de empezar sería escribir una frase que tenga (o no) que ver con la cuenta o programa. Imaginemos que vamos a crear una contraseña para el correo electrónico, podríamos hacer algo así; “cuando abro mi correo solo tengo spam“. Vamos a trabajar sobre esta frase, de momento vamos a seleccionar las dos primeras letras de cada palabra quedando algo así “cuabmicosotesp“. Ahora vamos a cambiar una vocal si y otra no por un dígito tal que así “cu4bmic0sot3sp”. Con esto la contraseña tomaría suficiente fuerza pero si queremos podemos separar la contraseña en dos partes mediante un guión bajo o signo de exclamación “cu4bmic_0sot3sp” o “cu4bmic!0sot3sp”. Con esto hemos conseguido una contraseña lo suficientemente segura. Podríamos seguir implementando seguridad a nuestra contraseña como por ejemplo invertir el orden o ampliando el pajar. La expresión “ampliar el pajar” viene de buscar una aguja en un pajar, y no es mas que aumentar la longitud de la contraseña mediante la repetición de caracteres, en nuestro caso podría quedar definitivamente así (inversión + ampliación) “0sot3sp!!!!!!!!cu4bmic”. Parece paranoico pero nuestro nivel de paranoia será (o debería serlo) directamente proporcional a la criticidad de la información que queremos ocultar.

Información: Existen programas como John the Ripper que podemos aplicar sobre nuestra propia base de datos de contraseñas encriptadas para localizar contraseñas pobres.

  • Cambiar la contraseña con frecuencia: Sería interesante a la hora de crear una cuenta en el equipo hacerlo de manera que cada cierto tiempo el sistema nos obligue a modificar la contraseña. Podemos hacer esto directamente a la hora de crear la cuenta mediante useradd o una vez creada mediante la herramienta chage o usermod.
  • Utilizar contraseñas ocultas: En el Capítulo 7 ya se comentó la importancia de usar contraseñas shadow (/etc/shadow) en lugar del antiguo mecanismo que permitía que un atacante pudiese leer el archivo /etc/passwd y localizar la contraseña directamente. Hoy en día todas las distribuciones utilizan por defecto contraseñas shadow. No obstante podemos modificar esto con los comandos pwconv y pwunconv que implementan o no contraseñas shadow respectivamente.
  • Mantener las contraseñas en secreto: Aunque parezca arcaico no hay nada mas ‘seguro‘ que mantener la contraseña escrita en un papel al que acudir cuando la necesitamos, aunque realmente lo mejor es memorizarla, pero…
  • Utilizar protocolos seguros de acceso remoto: Mas adelante hablaremos sobre protocolos o métodos de conexión remota, pero adelantamos que lo mejor es conectar a través de ssh, ya sea a ftp, escritorio o consola remota, o bien copiar archivos (sftp, ssh -X, ssh, y scp respectivamente). Esto encriptará nuestra contraseña. Deberemos de desactivar Telnet, FTP y otros protocolos que emplean contraseñas en texto plano.
  • Tener cuidado con la ingeniería social: práctica que implica engañar a personas fingiendo ser por ejemplo un administrador de sistemas o cualquier otra persona de responsabilidad en la materia, para que estas le entreguen sus contraseñas. Este sería el método sencillo pues esto puede llevar a conversaciones suficientemente elaboradas por aquel que emplea la ingeniería social de modo que nos esté sacando información valiosa sin ni siquiera darnos cuenta. Es posible que no digamos en ningún momento nuestra contraseña pero quizás si le estemos ofreciendo el método de llegar a ella. Una práctica relacionada es el phishing (o pesca telemática) en la que un atacante crea un sitio web falso o envía un correo electrónico fingiendo ser otra persona, de manera que la víctima se lo crea y revele algún dato sensible, como su número de tarjeta de crédito.

 

Controlando el acceso al sistema

Como se ha comentado en la sección anterior, el acceso al sistema mediante una cuenta de usuario puede ser el primer paso para comenzar un ataque hacia el interior de la red o del propio sistema. Según se mire, puede que tener el control de una cuenta sea el primer o segundo muro, dependiendo si el atacante a tenido que saltar diferentes obstáculos para llegar a través de la red hacia el sistema o bien estamos ante un ataque directo físico, como por ejemplo un compañero hostil de nuestro entorno que conoce nuestra contraseña y accesa al sistema. En cualquiera de los casos es de suma importancia mantener un control sobre quien o que usuario está iniciando sesión en nuestro equipo o servidor que administramos. Para ello Linux pone a nuestro disposición varias herramientas y archivos que mantienen un control sobre la entrada y salida de usuarios, herramientas que ya hemos estudiado en su correspondiente capítulo y que son algunas como who, users, w, lastlog, last, lastb o finger, este último en desuso por sus vulnerabilidades. Repasemos el uso de estas herramientas y los archivos implicados:

  • last y lastb: Muestran un histórico de los usuarios que han conectado y desconectado al sistema así como intentos de sesión fallidos, respectivamente. Los archivos binarios que corresponden a estos comandos son (por defecto) /var/log/wtmp y /var/log/btmp
  • lastlog: Otro comando que nos permite ver un histórico de entradas al sistema, pero esta vez de todos los usuarios del sistema hayan o no iniciando sesión alguna vez. Este comando despliega el contenido del archivo de registro binario /var/log/lastlog
  • w, who y users: El comando ‘w‘ muestra los usuarios conectados actualmente en el sistema y el uso que hacen de este (procesos ejecutados) mientras que who solo muestra los usuarios conectados en ese momento en la máquina. Ambos por defecto despliegan el contenido del archivo binario /etc/utmp. Con who además podemos ver el usuario actual (como con whoami) si usamos su opción -m o desplegar el contenido de /var/log/wtmp (como hace last por defecto) si le pasamos el nombre de archivo (con ruta absoluta) como argumento. El comando users tiene un comportamiento similar a who pero ofrece menos información.

Como podemos comprobar, el uso de los archivos de registros de acceso al sistema son de vital importancia aunque no del todo fiables pues un atacante podría manipularlos de manera que oculte sus accesos. Estos archivos deberían de tener los permisos 644 sin afectar por ello al funcionamiento del sistema de registros. A continuación veremos como implementar una mínima seguridad sobre estos archivos.

Atributos de un archivo

Existen ciertos atributos para los archivos que pueden ayudar a incrementar la seguridad de un sistema. No vamos a estudiar todos los que existen pero si alguno de ellos que nos pueden ser de utilidad. La herramienta para implementar el uso de atributos de archivos es chattr y su sintaxis es la utilizada para la gran mayoría de los comandos Linux: ‘# Comando [opciones] archivo(s)‘, solo que en las opciones usaremos los signos +, o = para añadir, quitar o dar exactamente unos atributos a uno o varios archivos respectivamente.

Nota: Podemos ver los atributos de un archivo con lsattr.

Acabamos de ver la importancia de los archivos de registro de accesos al sistema y sabemos que pueden ser atacados por un intruso bien de forma manual o a través de rootkits. Para añadir un extra de seguridad a estos archivos podríamos hacer que tomaran el atributo ‘a‘ de manera que el archivo fuera abierto exclusivamente para añadir información, nunca para borrarlo. Solo root puede hacer uso de este atributo, de manera que si la seguridad del sistema se ha visto comprometida por un intruso a nivel de root, solo sería cuestión de tiempo que el atacante modificara el atributo con chattr -a archivo y modificase o eliminase el archivo. No obstante de no tener privilegios de root, estaríamos teniendo constancia de la entrada del intruso al sistema. Otro atributo interesante es ‘i‘ con el que haremos que un archivo sea inmutable, es decir, no se puede escribir en el, modificar permisos, enlazan con ln, eliminar, etc… Al igual que pasa con el anterior atributo solo root puede activar o desactivarlo. Podríamos usar este atributo para hacer inmutable ciertos archivos de interés que no suelen ser modificados con regularidad, como archivos de configuración de /etc/, el archivo de contraseñas de usuario, etc…

Nota: Cuando activamos el atributo i debemos de tener en cuenta que ni siquiera root podrá modificar el archivo, a menos que desactive el atributo.

Otros atributos a destacar, aunque menos importantes que los dos anteriores son s y S. Si eliminamos un archivo que tenía activado el atributo s, el sistema rellenará sus bloques con ceros en lugar de efectuar un simple unlink. De esta manera dificultamos la tarea de recuperación de un archivo por parte de un atacante, aunque una vez mas esto solo supondrá una pérdida de tiempo para un atacante experimentado. El atributo S lo que hace es escribir los datos directamente al disco sin esperar a sync de aquellos archivos que lo tengan activado. Esto no muy significante, pero de apagarse nuestro equipo en el momento en el que un atacante entra al sistema, mantendremos esa información en el archivo de registro.

Para terminar vamos a nombrar otros atributos quizás útiles en determinadas circunstancias:

  • El atributo A hace que la fecha de último acceso en un archivo no sea modificada
  • Cuando un directorio tiene activo el atributo D los datos serán escritos de forma síncrona en el disco. Idéntico a S solo que S trabaja sobre archivos.
  • Un archivo con el atributo u activado podrá ser recuperado con alguna herramienta destinada a tal fin.

Limitar el acceso a root

Acceder como root directamente al sistema suele ser desaconsejable, por varias razones, entre ellas, que no deja ningún rastro en los archivos de registro de acceso. En el capítulo 7 se trato el uso de herramientas como su y sudo, mejores opciones para acceder como root al sistema. Recordemos que con su – podemos cambiar a root bajo su entorno (gracias a ‘‘), mientras que con sudo podemos ejecutar un programa con privilegios de root siempre y cuando tengamos correctamente configurado el archivo /etc/sudoers. Hablaremos de como configurar este archivo al final de la sección.

También podemos usar su -c “programa” para ejecutar ‘programa‘ con privilegios de root, aunque esto también suele usarse en scripts que solo root puede ejecutar pero que posteriormente queremos que sea un determinado usuario el que sea tutor o propietario de dicha ejecución. Imaginemos que tenemos una tarea de sistema bajo anacron (tareas que solo root puede ejecutar) pero el programa que queremos ejecutar es de nuestro usuario particular y además (aunque root pueda hacerlo) queremos que lo ejecute nuestro usuario, para conseguir esto podremos crear una tarea anacron que llame a un script cuyo contenido sea similar a:

!/bin/bash
# Ejecutar 'programa' con usuario 'miusuario'
su - 'miusuario' -c "/home/'miusuario'/bin/'programa'

De esta manera root ejecutará la tarea anacron (en este caso este pequeño script) que a su vez llamará a nuestro programa con nuestro usuario.

El archivo /etc/nologin aplica un concepto de seguridad especialmente radical. Si este archivo está presente, sólo root podrá acceder al ordenador.

Configurando /etc/sudoers

Para comenzar a editar este archivo lo abriremos con el comando visudo:

$ visudo /etc/sudoers

Vamos a suponer que realizaremos una configuración avanzada. Lo primero que deberemos de hacer será crear grupos de comandos para luego asignárselos a uno, varios o todos los usuarios, de manera que puedan hacer uso de ellos mediante la herramienta sudo:

# Crear grupos de comandos (Alias) - También podemos crear Alias para grupos, usuarios, equipos y "ejecutar con" (Runas)
 Cmnd_Alias ALMACENAMIENTO = /sbin/fdisk, /sbin/sfdisk, /bin/mount
 Cmnd_Alias PROCESOS = /bin/nice, /bin/kill, /usr/bin/killall

# Definir quien podrá usar los grupos de comandos
# El grupo sys puede usar todos los comandos de ambos grupos (ALMACENAMIENTO y PROCESOS)
 %sys ALL=ALMACENAMIENTO,PROCESOS

# El grupo disk podrá utilizar todos los comandos de ambos grupos y además sin requerir de la password
 %disk ALL=ALMACENAMIENTO NOPASSWD:ALL

# El grupo wheel podrá usar todos los comandos en todas las máquinas y sin password
 %wheel ALL:(ALL) NOPASSWD:ALL

# El usuario nebul4ck podrá usar todos los comandos del grupo proceso solo en la máquina freeser y con el uso de password
 nebul4ck freeser = PROCESOS ALL

# El usuario kafka podrá ejecutar unos determinados comandos en la máquina freeser sin requerir de autenticación:
 kafka freeser = NOPASSWD: /bin/kill, /sbin/fdisk, /bin/chmod, /bin/chown

# El usuario darkns podrá ejecutar ciertos comandos con permisos del usuario nebul4ck y con el grupo kafka:
 darkns blouder = (nebul4ck:kafka) /bin/ls, /usr/bin/lprm, /bin/chmod

 

La configuración de este archivo puede llegar a ser bastante compleja por lo que no vendría mal acudir a las páginas man de sudoers. Podremos usar comodines o crear el particular Alias “Runas” para permitir a ciertos usuarios ejecutar unos determinados comandos como si fuese un usuario específico. Para ejecutar un comando con un usuario o grupo distinto especificado en un Alias Runas podríamos hacerlo así:

$ sudo -u <usuario> <comando>
$ sudo -u <usuario> -g <grupo> <comando>
$ sudo -g <grupo> <comando>

Restringir el acceso a root

Podríamos hacer que el acceso de root al sistema estuviese restringido, algo que no se suele hacer, pero que si trabajamos sobre el archivo /etc/sudoers de manera que tengamos los permisos necesarios para realizar la mayoría de tareas cotidianas sin poner en riesgo la seguridad del sistema, podemos trabajar a diario con un usuario particular limitado a root en ciertos aspectos, evitando así que un intruso se haga con el control pleno a través de root y comprometa nuestro equipo. Lo primero que deberíamos de hacer sería adaptar el archivo de configuración de sudo (/etc/sudoers) de manera que nos otorguemos el derecho de uso de ciertas herramientas de administración del sistema a nuestro usuario particular, luego, desactivaremos el acceso a bash de root editando la línea de /etc/passwd tal que así:

root:x:0:0:root:/root:/usr/sbin/nologin

A partir de este momento no podremos acceder a consola como root ni emplear la herramienta su –

Nota: Cuando estudiemos la herramienta ssh veremos como restringir el acceso remoto de root al sistema, de manera que primero debamos de acceder vía ssh con un usuario estándar pasando luego a root.

 

Definir límites y cuotas a los usuarios

En ocasiones una medida de seguridad puede ser la definición de una serie de límites a los usuarios que hacen uso del sistema de forma que se proteja en cierto modo el uso que hacen de este. Existen diferentes formas de definir límites en el sistema que varían en función del objeto que queremos limitar. Por ejemplo, si lo que queremos es imponer un límite sobre la explotación de recursos que realiza un usuario en el sistema, como el uso de memoria, tiempo de CPU, número de procesos podremos editar el archivo /etc/security/limits.conf o utilizar la herramienta ulimit. Si lo que queremos es imponen un límite en el uso del espacio del disco duro del ordenador o servidor o el número de archivos abiertos simultáneamente por un usuario concreto, podremos utilizar el sistema de cuotas que nos ofrece Linux. Este último método ya se explicó en el capítulo – 4 en la sección “Administrar cuotas de disco”, de todos modos volveremos a refrescar nuestra memoria en esta sección.

Definir límites de accesos, procesos y memoria

La imposición de límites como el número máximo de accesos permitidos, procesos ejecutados de forma simultánea, memoria utilizada o tiempo de CPU es preferible hacerla mediante un módulo PAM (Pluggable Authentication Module, Módulo de autenticación conectable) llamado pam_limits. Esto se hace modificando su archivo de configuración /etc/security/limits.conf cuyo formato de línea es el siguiente:

dominio tipo elemento valor

donde:

  • Dominio :  Es la entidad a la que se le aplica el límite. Puede ser un usuario, un @grupo o un ‘*‘ (lo que coincidiría con todo el mundo.
  • Tipo : Se indica el tipo de límite a imponer. Se pueden definir límites estrictos (hard) o flexibles (soft) cuya diferencia radica en que los límites hard son impuestos por root y no se pueden sobrepasar, mientras que los límites soft pueden ser sobrepasados temporalmente. Para indicar que un límite es tanto hard como soft podemos hacerlo con ‘
  • Elemento : Especifica que tipo de elemento es el que se limita, por ejemplo, core limita el tamaño de los archivos de volcado del kernel, data limita el tamaño del área de datos de un programa, fsize limita el tamaño de los archivos creados por el usuario o grupo limitado, nofile para limitar el número de archivos de datos abiertos, rss tamaño del proceso residente, stack para limitar el tamaño de la pila, con cpu limitaremos el número de minutos que un proceso puede hacer uso de la CPU, nproc para el número de procesos concurrentes, maxlogins limita el número de accesos simultáneos y priority la prioridad de acceso.

Nota: Los elementos data, rss y stack están relacionados con la memoria consumida por un programa.

  • Valor : Indica el valor que será aplicado al límite.

Un ejemplo en el que se limita el tiempo de CPU en 2 minutos de forma estricta para un determinado grupo podría ser:

@migrupo    hard    cpu   2

El tiempo de CPU se cálcula en función del tiempo que la CPU está procesando activamente datos del usuario. Existe otro límite que mide el tiempo de inactividad del usuario, como por ejemplo cuando la consola del usuario está activa pero no hay en ejecución ninguna tarea.

La otra manera de imponer estos límites es empleando la herramienta ulimit. Para ello haremos uso de la siguiente sintaxis:

ulimit [opciones [limite]]

En paralelo a los elementos de limitación anteriormente mencionados usaremos para ello la opción -c (para los volcados del kernel), -f (para el tamaño de los archivos creados por consola por un usuario), -u (para el número de procesos que puede ejecutar un usuario), -t (para limitar el tiempo de CPU en segundos en vez de minutos), -v (define el tamaño total de memoria virtual disponible para la consola), -s (define el tamaño máximo de la pila de memoria), -m (limita el tamaño máximo del conjunto residente), -d (limita el tamaño del conjunto de datos de los programas) y -l (define el tamaño máximo que se puede bloquear en la memoria).

Si lo que queremos es especificar un tipo de límite concreto utilizaremos -H o -S para especificar hard o soft respectivamente.

Para conocer los parámetros actuales de ulimit, pasaremos la opción -a

Advertencia: Como ulimit es un comando nativo de bash, su utilidad como herramienta de seguridad del sistema es limitada. Si los usuarios tienen acceso a herramientas GUI de inicio de sesión o pueden acceder al sistema saltándose bash de algún modo (por ejemplo mediante SSH, dependiendo de como esté configurado), las restricciones impuestas por ulimit carecerán de sentido.

Aplicar cuotas de disco

Como ya se estudió en el capítulo – 4 podemos aplicar límites de cuotas de disco para determinados usuarios o grupo, de manera que cuando se rebase el límite se informe al usuario. Con esto podemos prevenir el desbordamiento de espacio de ciertas particiones que podrían resultar críticas para el sistema. Por ejemplo si tenemos el /home de los usuarios o el directorio /tmp en la misma partición que la raíz ‘/’ y no tenemos un control sobre el uso que se está haciendo de esta, podemos acabar por dejar el sistema inutilizable al llenar la partición. Para prevenir esto podemos implantar el sistema de cuotas, por lo que nuestro kernel deberá de estar compilado con los módulos que ofrecen soporte para las cuotas y además deberemos de usar como root una serie de herramientas, tales como edquota, repquota, quotacheck y quota.

Al igual que con los limites impuestos en el módulo pam_limits también podemos crear quotas estrictas (hard) o flexibles (soft) con un periodo de gracia.

Nota: Para profundizar en el sistema de cuotas de disco volver al Capítulo – 4 sección “Administrando cuotas de disco

 

Permisos sobre archivos

Algo que deberemos de tener en cuenta si queremos hacer poco a poco nuestro sistema mas seguro, y digo poco a poco porque nunca será suficiente y porque ya llevamos aprendidas algunas técnicas pero evidentemente quedan mas, entre ellas por ejemplo el conocer los permisos con los que cuentan los archivos de nuestro sistema. Evidentemente es difícil mantener un control sobre todos los archivos o scripts del sistema pero si seguimos unos patrones podremos identificar gran parte de ellos. Algunas de las acciones que podemos realizar para detectar o prevenir vulnerabilidades son la detección de archivos o scripts con los bits especiales (suid, sgid y sticky bit), prestar especial atención a los parámetros con los que montamos una partición, ficheros con permisos de escritura cuando en realidad no existe motivo especial por el que deban de tenerlo, ficheros extraños como por ejemplo aquellos que no poseen un propietario o ficheros cuya configuración puede resultar peligrosa como los .hosts aunque a estos le dedicaremos una sección.

SUID, SGID y Sticky Bit

Seguir el rastro a estos archivos puede resultar una tarea sencilla y eficaz pues como ya sabemos, el que un archivo o en especial un script tenga alguno de estos bits activados puede resultar en un agujero de seguridad para el sistema, ya que un script con el bit suid activado puede hacer que un intruso eleve sus privilegios tomando el control del sistema. Para localizar los archivos con bits especiales podremos usar el comando find de la siguiente manera:

# find / -perm +7000 -type f

Nota: Usamos -type d si queremos localizar directorios o anulamos esta opción para localizara a todos. Igualmente podemos restringir la búsqueda a tan solo archivos con suid (+4000), sgid (+2000) o con sticky bit (+1000)

Cuando realizamos una búsqueda con -perm +4000 es decir estamos buscando archivos con el suid activado, deberán de aparecer aquellos programas para los que un usuario corriente tiene acceso de ejecución por ejemplo,  si un usuario quiere cambiar su contraseña necesitará acceder al comando passwd, o si necesita cambiar diferentes características de su cuenta con chfn o chsh. Igualmente necesitará acceso a programas como mount, ping, su o sudo. Hay que prestar especial atención a todos los de la lista por si hubiese alguno que no entendemos porque lo tiene, y tras buscar por Internet o las páginas man llegamos a la conclusión de que determinado archivo no debería de tenerlo, podemos empezar a pensar de que nuestro equipo quizás esté comprometido.

nosuid, nodev, noexec

En la mayoría de las ocasiones, o al menos es una buena práctica, el tener una partición para cada uno de los siguientes directorios /home, /usr, /var y /tmp por diferentes razones. Si creemos que son demasiadas particiones, podemos entonces aislar a /home y /var del resto (que entonces compartirán partición con ‘/’) y si aún así tampoco estamos muy convencidos, se aconseja que como mínimo que el /home se encuentre en una partición independiente por motivos de seguridad, comodidad y flexibilidad (entre otros).

Si hemos seguido este buen y ya conocido consejo y tenemos particiones independientes, deberemos entonces de controlar la configuración de /etc/fstab. Normalmente salvo casos excepcionales no existe una buena razón que nos obligue a ejecutar scripts con los bits suid y sgid activados en los directorios /home de los usuarios, o en aquellas particiones con permisos de escrituras para usuarios no root, por lo que una medida que podremos tomar será añadir la opción (si es que no viene ya por defecto) nosuid a estas particiones. Podemos también evitar la creación de archivos de bloques o caracter y ejecución de programas en estos directorios y en /var con las opciones nodev y noexec respectivamente.

Archivos con permisos de escritura

Otra búsqueda que podemos realizar por el sistema es aquella que localice a archivos o directorios que contienen activados el permiso de escritura para todos los usuarios. Es evidente que no querremos dejar que un invitado, intruso, atacante, compañero hostil o cualquier otra persona non grata pueda modificar archivos que consideramos importantes, vulnerables o que simplemente no queremos perder su control, sin mas y mucho menos que un directorio caiga en manos de estos dándoles directamente permisos para añadir o eliminar contenido en él. Para localizar estos archivos y directorios podemos usar el siguiente termino de búsqueda con find:

# find / -perm -2 [-type f|d] -print

Esto imprimirá una larga lista que seguramente resulte bastante tediosa de seguir, por lo que podemos limitar la búsqueda por aquellos directorios que mas nos interesen. Los enlaces simbólicos serán añadidos a la lista pero como sabemos el permiso definitivo será el que tenga el archivo al que enlaza. También aparecerán bastantes archivos bajo /var.

 Archivos sin propietario

Los archivos sin propietario pueden ser un indicio de que alguien ajeno a nosotros a estado fisgoneando nuestro sistema, por lo que no estaría de mas dar un repaso en busca de estos archivos.

# find / -nouser -o -nogroup -print

 

Habilitación de hosts

Durante el capítulo – 6 cuando configuramos el equipo para permitir el acceso remoto de otras aplicaciones al servidor X del sistema, vimos la importancia del comando xhost con el que se indicaba un host  o usuario al que permitir acceso remoto mediante X. En el sistema, dependiendo de a que o para quien otorguemos permisos para una determinada acción, como dar acceso al servidor de X a aplicaciones o usuarios remotos, se crean unos determinados ficheros que de tener una configuración incorrecta o poco cuidada pueden resultar en agujeros de seguridad en el sistema. Aunque siempre será mejor utilizar protocolos seguros como ssh, vamos a citar algunos archivos con los que a la hora de configurarlos si se necesitase, deberíamos de andar con cuidado.

  • ~/.rhost : Cuando este archivo está presente en el directorio /home de un usuario significa que se ha creado una relación entre este usuario y otro usuario o máquina de la red. En otras palabras estaremos dando acceso mediante los comandos (rcp, rlogin, rexec, etc…)  sin contraseña a los usuarios y máquinas especificados en este archivo. Por ello deberemos de tener bastante cuidado a quien ofrecemos nuestro sistema. Un intruso podría utilizar este archivo para crear relaciones con máquinas externas.
  • /etc/hosts.equiv : Es exactamente igual que el archivo anterior pero mas peligroso aún, ya que se crean relaciones a nivel de máquina especificando que servicios, usuarios y grupos pueden acceder sin contraseña a los servicios. Un sigo ‘+‘ otorgará permisos a “cualquier” máquina.

Nota: Normalmente estos archivos ya no suelen existen a consecuencia del uso de protocolos seguros como ssh.

 

Módulos PAM

Los módulos PAM son bibliotecas compartidas que implementan un método que permiten al administrador del sistema controlar cómo se realiza el proceso de autenticación de los usuarios en determinados programas. Las bibliotecas PAM se encuentran en /lib/security mientras que los archivos de configuración para cada aplicación que los utiliza se instalan bajo el directorio /etc/pam.d. Algunas de las aplicaciones que utilizan estos módulos para la autenticación de usuarios podrían ser: cron, su, sudo, samba, login, mdm, xdm, gdm, kdm

Una línea típica de estos ficheros de configuración podría ser:

modulo flag ruta-al-modulo argumentos

donde:

  • Modulo : indica el requisito a realizar como por ejemplo, que sea necesario la autenticación (auth), que se trate de un acceso restringido (account), tareas a realizar cuando un usuario entra o sale (session), indicar la contraseña (password)
  • flag o bandera de control : especifican las necesidades. Que sea un requisito (requisite), necesario (required), suficiente (sufficient) o opcional (optional). Otra posibilidad para las banderas de control es utilizar la sintaxis ‘valor y acción
  • ruta al módulo o path
  • Argumentos :  dependiendo de cada módulo podremos pasar uno u otros argumentos.

A modo de ejemplo se van a mostrar solo tres líneas de uno de los archivos de configuración, algo que no será suficiente. Los módulos PAM son material que no se abarca en LPIC-1 y que solo se han comentado como base de conocimiento. Si se desea profundizar mas, como siempre se recomiendo las páginas man, HOWTOs de Internet, foros, etc…

auth required pam_unix.so nullok
account required pam_unix.so
session optional pam_lastlog.so

 

Administrar la seguridad de la red

Dejamos atrás de cierta forma todo lo que aquí se recoge con respecto a la seguridad local y damos paso al primer o segundo muro con el que chocará un atacante, y decimos primer o segundo por el mismo motivo que comentábamos en la sección de la seguridad local, puesto que dependerá desde donde se produzca el ataque. Lo que ya tenemos claro es que contra mas piedras pongamos en el muro mas difícil o mas tiempo llevará su derribo y con ello su penetración.

En esta sección del capítulo vamos a estudiar aquellos aspectos a tener en cuenta con referencia a la red. Haremos una pequeña introducción sobre alguna de las técnicas mas usadas para el ciberataque y algunas posibles contramedidas.

 

Técnicas utilizadas en los ataques y contramedidas

La ciberseguridad es algo que se encuentra en constante cambio, siempre existen mejoras y al poco tiempo se encuentran vulnerabilidades que explotar para esas nuevas mejoras. Se pueden encontrar vulnerabilidades a nivel de software o hardware por lo que es importante mantenerse siempre actualizado. A continuación se enumerarán algunas técnicas de ataque o tipos de vulnerabilidades y sus contramedidas o posibles métodos preventivos para la detección de lo que puede estar sucediendo en nuestro sistema:

  • Bugs: También llamados holes o agujeros. Son fallos en el software, hardware, servicios, protocolos o directamente en el sistema operativo que se aprovechan para romper la seguridad del sistema y explotar los recursos, obtener información, elevación de privilegios, etc… Para ello se utilizan los llamados bugs exploits, que no son mas que fragmentos de código malicioso y comandos, que realizan técnicas de ataques genéricos o particulares para el elemento afectado. Para aquellos bugs que aún no han sido conocidos y que están siendo explotados suele utilizarse el termino día cero (tanto para el bug como para el exploit). Para remediar en lo posible caer en un ataque por bugs, es aconsejable mantenerse actualizado a nivel de software, hardware y servicios del sistema, así como a la desactivación e incluso desinstalación de todos aquellos programas que han quedado obsoletos o no son utilizados. Como administrador de sistema es igualmente importante mantenerse actualizado con respecto a las vulnerabilidades encontradas, como mínimo de aquellos programas de los que hacemos uso.
  • Virus: Son programas normalmente adjuntos a otros que utilizan técnicas de autocopiado y transmisión, para infectar un sistema. Suelen anexarse a programas que permiten lenguaje de macros (no verificados) como ejecutables, correo electrónico e incluso documentos. En Linux si no hacemos un uso abusivo de root o no ejecutamos programar que desconocemos, estamos casi totalmente a salvo ya que no se utiliza lenguaje de macros no verificados, ni en los documentos ni en el correo electrónico. No obstante, pudiesen aparecer a consecuencia de bugs en el sistema o incluso podemos llamar correo “virulento” a aquel que se pueda reenviar haciendo uso de nuestro sistema vía email como el spam. Para frenar un virus la primera medida a adoptar es la de instalar un sistema de antivirus, anti spam y anti malware. Luego será cosa nuestra el no ejecutar programas sospechosos, sistemas macros no verificados, crear reglas de filtrado tanto a nivel de correo electrónico como de firewall, etc..-
  • Worm: El termino worm o gusano es utilizado para identificar a aquellos programas que aprovechan algún agujero del sistema para realizar ejecuciones de código malintencionado sin permisos, con el fin de hacer uso de los recursos del sistema, como por ejemplo la CPU. Al igual que los virus usan técnicas de autocopiado y transmisión. Una buena medida a adoptar para saber si podemos estar infectados por un gusano es monitorizar nuestro sistema, comprobar el uso de los recursos que se está haciendo, los usuarios que hacen uso de este y sobre todo la explotación de recursos de hardware a horas en las que no existe un porque para que la máquina este trabajando de forma constante. Igualmente importante es analizar el tráfico de entrada y salida a la red.
  • Trojan Horse: El caballo de Troya o troyano son programas útiles pero que ocultan funcionalidades malintencionadas utilizadas para obtener información del sistema o comprometerlo de manera que por ejemplo pueda ser utilizado en un futuro por su creador. Suelen ser buenos métodos de transmisión programas aparentemente muy útiles y utilizados como por ejemplo los generadores de claves usados para crackear algún programa, video-juegos, etc… Las aplicaciones web desarolladas en Java, JavaScript o ActiveX, en caso de existir bugs en estas, pueden ser un buen método de transmisión una vez que el usuario acepta y consiente la ejecución de la aplicación. Si queremos comprobar la integridad de un programa de lo mejor que podemos hacer es verificarlo mediante los mecanismos de suma de verificación y firmado (md5 o gpg). Como con los gusanos, deberemos de prestar atención al uso de red que se está produciendo, filtrando mediante firewall posible tráfico sospechoso.
  • Backdoor: Puerta trasera en Español y que referencia posibles métodos de entrada ‘escondidos‘ en una aplicación o sistema, con el fin de poder evitar la seguridad y acceder a él. En numerosas ocasiones las backdoor son creadas a propósito con el fin de poder acceder a un sistema o programa bajo circunstancias estrictamente necesarias. Lo que se hace básicamente es introducir una secuencia especial dentro del código de programación con el fin de poder evitar los sistemas de seguridad del algoritmo (autentificación) para acceder al sistema o herramienta. Existen herramientas como Netcat que pueden ser empleadas para abrir puertas traseras o defenderse de ellas. Para saber si un software que vamos a proceder a instalar contiene backdoors, es primordial obtener de los proveedores del mismo la certificación de que éste no contiene ningún tipo de puerta trasera escondida no documentada. Si tenemos un programa ya descargado que se ha verificado y probado que no contiene puertas traseras, estaría bien crear una suma de verificación o respaldo del mismo de manera que podamos evitar la creación de una backdoor a posteriori volviendo atrás o comprobando su integridad mediante la suma.
  • Keyloggers: Utilizado para captar la interacción del usuario con el teclado de manera que pueda ‘secuestrar‘ la contraseña del usuario en cuestión. Pueden ser programas individuales o troyanos incorporados en otros programas.
  • Rootkits: La palabra rootkit proviene de la unión de ‘root‘, es decir raíz o administrador en sistemas Linux y ‘kit‘, conjunto de herramientas que permiten a un atacante obtener acceso con privilegio a la máquina esquivando los métodos de autenticación. Los rootkits se han catalogado como malware aunque por si solo no tiene porque afectar el rendimiento de la máquina ya que su función principal es la de esconder la presencia del atacante en el sistema (a él, a los puertos que utiliza, sus conexiones de red, etc..) mediante un conjunto de herramientas (cada unas destinada a un fin concreto). Lo que está claro es que no se instala un rootkit, algo que hace el atacante una vez que ha accedido por primera vez al sistema objetivo (ya sea por Ingeniería Social, fuerza brutal o cualquier otra forma) para nada, es decir instalar un rootkit implica que la máquina va a ser usada con un determinado fin por el atacante y en numerosos casos se trata de explotar sus recursos.

Para defendernos de los keyloggers y los rootkits en la manera de lo posible, conviene revisar con frecuencia o bajo sospecha, los archivos que mantenemos abiertos usando por ejemplo la herramienta que ya conocemos ‘lsof‘, los procesos que se encuentran ejecutándose en el sistema con ‘ps‘ o bien auditar nuestra red con herramientas como netstat o wireshark (entre otras) por si se diera el caso de que un keylogger estuviese realizando envíos externos.

Nota: Podemos comprobar el funcionamiento de un keylogger muy básico con el comando script o verificar los rootkits con chrootkit.

  • Scanner: Es un paso previo a un ataque. Durante el scanner se recolecta información sobre posibles objetivos a través de herramientas que examinan la red en busca de máquinas con puertos abiertos (TCP, UDP, etc…). Una herramienta de uso común para tal propósito es nmap.
  • Sniffers o husmeadores: Este tipo de herramienta captura los paquetes que circulan por una determinada red, de modo que podemos recopilar información acerca de la activad de la red como por ejemplo capturar contraseñas, protocolos utilizados, posibles servicios y servidores, clientes que aceden, etc… Al igual que los scanner no son un ataque en si ya que sirven tanto para auditar nuestra propia red como para encontrar vulnerabilidades en otra. En el Capítulo 8 vimos las herramientas propicias para tal fin y algunos de los puertos a los que deberíamos de prestar especial atención.
  • Hijacking: Conocido como ‘secuestro’ ya que su pretensión es la de “pinchar” las comunicaciones de manera de que se pueda reproducir el funcionamiento o uso de una máquina remota. Esta técnica es comunmente utilizada para captar correos electrónicos, transferencias de ficheros o navegación web. Con respecto a la navegación web lo que se vendría a realizar es una captura de la sesión de manera que tengamos la información  de navegación del usuario(páginas visitadas, tiempo de visita, interacción con formularios, etc…). Contra el hijacking la mejor herramienta es utilizar servicios seguros con encriptación y autentificación, a poder ser con renovación periódica.
  • Denial of Service: Ataque de denegación de servicio o ataque DoS utilizados para dejar una máquina inaccesible a través de la sobrecarga de uno o varios de sus servicios. Básicamente el objetivo es crear muchas peticiones (envíos de miles de paquetes) hacia uno o varios servicios de una máquina hasta provocar su saturación y con ello la caída de la máquina. Una variante de este tipo de ataque es el ataque Distribuido de Denegación de Servicio o ataque DDoS en el que se utiliza una red de ordenadores distribuidos, conocida como botnet, ampliando enormemente la potencia y eficacia de la sobrecarga remota. Estos tipos de ataques suelen estar dirigidos normalmente a servidores que utilizan servicios web como apache o DNS como bind en los que se han encontrado bugs o quizás no estén lo suficientemente actualizados dejando en evidencia sus vulnerabilidades al atacante. Por ejemplo si un atacante detecta que el servidor al que quiere atacar tiene abierto el puerto 80 y además tiene instalado un servidor web, el siguiente paso sería comprobar la versión del servidor web y si está desactualizada, podría irse a páginas del propio servicio en la que se informan de los bugs conocidos para una determinada versión y a raíz de ahí comenzar el ataque concreto. Normalmente estos servicios suelen caer al recibir mas conexiones o peticiones a conexiones de las que pueden soportar.
  • spoofing: Es una de las técnicas mas complejas y suele englobar varios métodos de ataque. Por lo general el fin del spoofing es la falsificación de datos, ya sean IP (falsifican la identidad de una máquina para enviar o recibir datos), interlocutores, correo electrónico falso con el que robar datos empleando Ingeniería Social, etc…
  • Ataque por fuerza bruta: Consiste en averiguar la contraseña de un usuario mediante la combinación de palabras, frases, números, etc… que normalmente se encuentran en uno o varios diccionarios. Básicamente funciona así; conociendo el algoritmo de codificación de la contraseña, se recurre a la comprobación de esas palabras o combinaciones de ellas que posteriormente se codifican con el mismo algoritmo y se comprueba su coincidencia, si no coincide se pasa a otra combinación y así hasta que alguna combinación codificada resulte ser la de la contraseña que buscamos. Para intentar evitar en la medida de lo posible que nuestra contraseña sea averiguada deberemos de seguir una serie de pautas que veremos en secciones posteriores, pero básicamente hay que elegir una contraseña con un mínimo de caracteres, combinando números, letras mayúsculas y minúsculas y caracteres de puntuación de manera que generemos una combinación de caracteres difícil de adivinar. Además es aconsejable modificar la contraseña cada cierto tiempo.

CONCLUSIÓN: Aceptar el software procedente únicamente de fuentes verificadas y de confianza es algo que deberemos de tener siempre en cuenta para frenar de algún modo cualquiera de las técnicas de intrusión o infección anteriormente descritas, además de tenerlo siempre lo mas actualizado posible y mantenernos informado acerca de vulnerabilidades (bugs) que vayan surgiendo. El uso de firewalls y auditores de red (scanners, sniffers, comprobadores de puertos, etc..) pueden sernos de gran utilidad para detectar un tráfico sospechoso entre nuestro sistema y la red, así como detectar puertos que no deberían de mantenerse en escucha, por ejemplo por que no los estemos utilizando. Es de suma importancia con respecto al entorno local, mantener contraseñas consistentes empleando métodos de fabricación de contraseñas que las hagan menos vulnerables, monitorizar el uso de los recursos de hardware, sobre todo en horas en los que el ordenador no debería de tener un funcionamiento constante, controlar los procesos que se están ejecutando, así como los archivos que mantenemos abiertos. Si llevamos a cabo estas estrategias de control seremos menos vulnerables, de lo contrario no esperemos estar seguro suponiendo que ‘alguien‘ o ‘algo‘ está haciendo el trabajo por nosotros, por que no será real.

 

 Controlar los puertos de red que se están utilizando

Una buena herramienta con la que podemos hacer un seguimiento de los puertos que tenemos abiertos e incluso saber como se ve nuestra máquina (con respecto a los puertos) desde el exterior (esto quiere decir que también nosotros podremos ver los puertos “accesibles” desde el exterior para una determinada máquina remota) es nmap.

Nmap es capaz de realizar exámenes mas sofisticados, incluyendo entre otros, exámenes “secretos” que probablemente no detecten la mayoría de cortafuegos, y exámenes mediante ping para detectar que hosts están activos.

Alguno de los usos que podemos hacer de nmap son los siguientes:

  • Comprobar como se muestra nuestra máquina de cara a la red (TCP/UDP)
# nmap -sTU localhost
  • Comprobar si el objetivo está “vivo” (examen de ping):
# nmap -sP <dirección-IP>
  • Quizás el host remoto esté configurado para bloquear intentos de ping, en este caso:
# nmap -nP <dirección-IP>
  • Comprobar únicamente un rango de puertos:
# nmap -p U:53,111,137,T:21-25,80,139,8080 <dirección-IP>

Nota: Se aconseja visitar la página man del comando y practicar con esta herramienta.

Ahora que ya sabemos en que estado se encuentran los puertos en nuestra máquina podremos hacer un análisis y posteriormente tomar precauciones, es decir, quizás existan puertos desconocidos que se encuentren escuchando conexiones, o servicios activos que jamás hemos utilizado o simplemente no son lo suficientemente seguros, por lo que deberemos de hacer algo con ellos. En estos casos lo mas normal es recurrir a los archivos /etc/services en el que podremos ver a que servicio corresponde un determinado puerto o /etc/protocols si tenemos problemas a la hora de identificar un protocolo concreto. Seguramente debamos de utilizar acto seguido herramientas de estado como netstat con la que seguir el rastro de aquellos puertos que desconocemos, para comprobar la posible actividad de puertos sospechosos o de servicios que aparentemente no usamos. Cuando tengamos localizado a que servicio corresponde cada uno de los puertos y tengamos claro si es conveniente utilizarlo o no, podremos entonces desactivar aquellos servicios que nos sean innecesarios. Para desactivar un servicio deberemos normalmente de acudir a nuestra herramienta de administración de servicios (service, initctl o systemd para sysV, upstart y systemd respectivamente) y pasar la opción stop para pararlo. Sería conveniente también desactivarlo del arranque, esto según que sistema de inicialización tengamos podremos hacerlo de una u otra forma, por ejemplo para sysV podremos eliminar el enlace del servicio en cuestión que se encuentre en el directorio de nivel de arranque con el que iniciamos, o utilizar la herramienta chkconfig, para upstart podremos eliminar, renombrar o editar el archivo de configuración de inicio del servicio en /etc/init o /etc/init.d si conserva el modelo de sysV, si estamos utilizando systemd tendremos que trabajar con las units y targets correspondientes ayudándonos de la herramienta systemd.

Muchos servicios están gestionados por por un súper servidor. Los dos súper servidores mas utilizados en Linux son inetd y xinetd, siendo este último el mas utilizado a en la actualidad. Para las distribuciones derivadas de Red Hat es xinetd el súper servidor por defecto, mientras que en derivados de Debian de suele utilizar inetd, aunque podremos sustituirlo sin problemas por xinetd. En próximas secciones hablaremos sobre estos súper servidores y veremos como configurarlos para que tomen el control de ciertos servicios y poder así activarlos o desactivarlos según nuestra necesidad.

 

Comprobar las conexiones de red existentes y los servicios que las provocan

Para esta tarea podemos usar una gran cantidad de herramientas cada cual mas sofisticada y útil. Algunas de ellas podrían ser netstat, nessus o wireshark. Cualquiera de estas tres herramientas nos puede informar de una manera u otra de que es lo que está ocurriendo en nuestra red. netstat es la que vamos a ejemplerizar aquí y digamos que es una herramienta que muestra el estado de la red en un momento concreto, nessus es un detector de vulnerabilidades que se basa en una seríe de plugings y tiene una estructura cliente-servidor, por último, wireshark que es un sniffer o husmeador de redes.

Un uso básico y bastante informativo sería utilizar netstat de la siguiente manera:

# netstat -punta

Con estas opciones estamos indicando que muestre el PID del proceso que está haciendo uso de la conexión (-p), informar sobre los puertos UDP además de los TCP,algo que ya hace por defecto (-u), expresar los nombres de hosts y puertos en dígitos (-n), mostrar el estado de las conexiones (-t), muestra todas las conexiones y puertos de escucha (-a)

Cuando anteriormente ejecutamos el comando nmap -sTU quizás obtuvimos alguno puerto desconocido (unknow) podríamos investigar mas sobre este de la siguiente manera:

# netstat -punta |grep <num-puerto>

 

Los súper servidores inetd y xinetd

Muchos servicios de red que tenemos instalado en nuestro sistema abren puertos de conexión y permanecen en estado de escucha (LISTENING) de forma directa, sin intermediarios. No obstante existen otros muchos servicios que si que operan a través de otro programa el cual los controla de cierta forma, a este programa o servicio se le conoce con el nombre de súper servidor. El súper servidor escucha las conexiones de red para estos otros programas y cuando detectan un inicio de conexión para alguno de ellos, es entonce cuando este (el súper servidor) le pasa el control al programa en cuestión. Este sería el procedimiento desde el punto de vista de los puertos de red, pero igualmente el súper servidor puede controlar quién puede o no acceder a un determinado servicio, arrancar o parar un servicio, configurar los parámetros de seguridad, etc… Estas medidas de seguridad se suelen conseguir gracias a los TCP Wrappers.

TCP Wrappers o simplemente wrappers es básicamente un servicio que actúa de intermediario llamado tpcd (/usr/sbin/tcpd) que se utiliza junto a los súper servidores (xinetd lo lleva ya implementado en su propio paquete) y que sustituye al servicio gestionado por el súper servidor, de manera que cuando TCP Wrappers recibe una petición de acceso al servicio, verifica el usuario y el origen de esta, para determinar si su configuración le permite o no utilizarlo. Además de esto permiten generar logs e informar por correo de los posibles intento de acceso.

Puede que una cierta aplicación venga ya compilada con la biblioteca de wrappers, por lo que podremos gestionar sus permisos directamente desde los archivos /etc/hosts.deny en el que especificaremos que servicio denegamos y a quién, y /etc/hosts.allow donde indicaremos los servicios que vamos a utilizar seguido de la lista de máquinas a las que se le permitirá el acceso. Existen dos comandos útiles para gestionar los wrappers que son tcpdchk con el que verificaremos la configuración y tcpdmatch al que pasaremos un determinado servicio y cliente y nos informará de como reaccionaría ante esta situación.

Podemos recurrir al archivo /etc/services para identificar aquellos servicios que queremos indicar en los archivos de configuración. Se pueden utilizar comodines o ALL para especificar todos los servicios. Para indicar uno o varios clientes podremos utilizar el nombre de las máquinas, la dirección IP o dirección de red, o bien usar el nombre de la propia máquina o dominio. Podemos usar el comodín ALL para cubrir el acceso a todas las máquinas o EXCEPT para generar excepciones.

Nota: /etc/hosts.deny y /etc/hosts.allow son los archivos de configuración de TCP Wrappers. Si una máquina aparece en ambos archivos, tendrá preferencia /etc/hosts.allow

Otra ventaja de utilizar un súper servidor es que podemos reducir la carga de memoria, ya que si este controla muchos servicios que raramente se utilizan solo permanecerán en memoria el súper servidor y uno o dos de los servicios que controla.

Nota: Si queremos saber si estamos utilizando algún súper servidor y en caso afirmativo de cual de ellos se trata, podemos comprobarlo con el comando ps de la siguiente manera:

ps ax | grep inetd

Configurar inetd y xinetd

Tanto la configuración de inetd como xinetd pueden contener varios archivos de configuración, es decir no se trata de una configuración monolítica en la que únicamente se depende de un archivo de configuración. Como en numerosos servicios, existe un archivo de configuración principal desde el que se puede referenciar a un directorio en el que encontrar otros archivos de configuración. Los archivos de configuración principal son /etc/inetd.conf y /etc/xinetd.conf para inetd y xinetd respectivamente, así como el directorio que puede contener archivos de configuración independientes para cada uno de los servicios controlados por estos súper servidores son /etc/inetd.d y /etc/xinet.d.

Nota: Mientras que el archivo de configuración principal de inetd puede contener líneas de configuración de servicios o referencia a un directorio en el que se almacenan archivos de configuración independientes, el archivo de configuración de xinetd contiene solo opciones globales para el súper servidor y una directiva para incluir los archivos almacenados en /etc/xinetd.d. Estos archivos son creados automáticamente cuando se instala un servicio que es gestionado por xinetd.

Si quisiéramos configurar el servicio ftpd bajo inetd podríamos crear una línea como la siguiente en /etc/inetd.conf:

ftp stream tcp nowait root /usr/sbin/tcpd /usr/sbin/in.ftpd -l

donde:

  • ftp : Indica el nombre del servicio
  • stream : En este segundo campo se indica el tipo de socket, es decir que tipo de conexión se espera. En este caso se trata de una conexión fiable en dos sentidos (stream). Otros tipos podrían ser dgram, conexión menos fiable pero con menos sobrecarga o conexión de bajo nivel a la red (raw). Este tipo de información podremos conocerla a través de la documentación de la propia aplicación.
  • tcp : Protocolo utilizado, normalmente tcp o udp.
  • nowait : En este cuarto campo se indica una posible acción, espera/sin espera (wait/nowait). nowait indica que el servidor se conectará a su cliente y liberará el socket, en cambio, wait procesará todos sus paquetes y, después se desconectará pasado un tiempo determinado.
  • root : Las opciones mas habituales para este campo son root o nobody y como se prevé, indica el usuario con  el que se ejecutará el servicio. No obstante, siempre que fuese posible deberíamos de ejecutar el servicio con un usuario con poco privilegios.
  • tcpd : En este penúltimo campo se suele referenciar al binario del servicio, pero como estamos utilizando como intermediario a TCP Wrappers, indicamos que se ejecute primero tcpd quién hará de intermediario recibiendo así las peticiones de conexión.
  • in.ftpd -l : En el último campo se nombrará al servicio final al que van destinada las conexiones, es decir, al servicio que vamos a usar, en este caso ftp. Se aceptan parámetros.

Esto sería con respecto a la configuración de un servicio bajo inetd pero ¿Y para xinetd?. Ya sabemos que en el archivo principal de xinetd (/etc/xinetd.conf) lo que se configura son los parámetros y opciones absolutas, es decir, las que afectan al propio súper servidor, delegándose la configuración de los servicios al directorio /etc/xinetd.d, donde existirá un archivo de configuración por cada servicio instalado que corra bajo xinetd. La configuración para un servicio que corre bajo xinetd no es muy diferente a aquel que lo hace con inetd, lo que ocurre es que el formato utilizado es muy diferente. A continuación vamos a ver un ejemplo, en el que usaremos el archivo de configuración del servicio ftp pero esta vez ejecutándose sobre xinetd.

service ftp
 {
 socket_type = stream
 protocol = tcp
 wait = no
 user = root
 server = /usr/sbin/in.ftpd
 server_args = -l
 }

Existe un parámetro adicional (disable) con el que poder activar o desactivar un servicio. De modo que si quisiéramos desactivar este mismo servicio podríamos haber añadido disable = yes. Si lo que queremos es desactivar varios servicios en una sola línea podremos añadir este mismo parámetro seguido de los nombres de todos los servicios a desactivar en lugar de ‘yes‘ en la sección defaults del archivo /etc/xinetd.conf.

Esto mismo ocurre con la configuración de la seguridad de los servicios. Por ejemplo podremos implementar la seguridad de forma individual para cada servicio con parámetros como:

  • bind : Indica a xinetd en que direcciones IP se escuchará en busca del servicio. Podemos restringir la escucha de manera que solo se disponga del servicio de forma local indicando la interfaz de circuito cerrado (127.0.0.1)
  • only_from : Aceptará solo conexiones provenientes de las direcciones IP, direcciones de red o nombres que indiquemos. Es similar a la función que realiza el archivo /etc/hosts.allow de tcpd.
  • no_acces : Idéntico a only_from solo que en este caso rechaza conexiones. Parecido a la función que ejerce /etc/hosts.deny de tcpd.
  • acces_time : Define el rango horario en el que el servicio estará disponible para los usuarios. Se especifica en formado hora:min-hora:min.

Aviso: El rango horario indica las horas a las que se puede acceder al servicio, independientemente de las horas de las que se haga uso, es decir si el rango está marcado en 08:00-17:30 y un usuario comienza a hacer uso del servicio a las 17:29 podrá hacer uso de él desde ese minuto en adelante, es decir, que no se le va a cortar el acceso en cuanto pase al minuto 17:30, eso si, un nuevo usuario que intente hacer uso del mismo servicio a las 17:31 obtendrá un acceso denegado.

Al igual que ocurría con el parámetro disable, si queremos implementar opciones e seguridad de forma general deberemos de indicarlas en la sección defaults del archivo de configuración principal /etc/xinetd.conf

Importante: Siempre que se realicen cambios en la configuración, tanto a nivel global como individual e independientemente del súper servidor que estemos gestionando, deberemos de recargar su archivo de configuración con reload o bien reiniciar el súper servidor con restart.

 

Protección mediante Firewalls

¿Que es un firewall?

Un firewall o cortafuegos es un sistema o dispositivo que se instala en una red con el objetivo de filtrar el flujo de datos (tráfico) que por ella discurre, de manera que sea capaz de separar los diferentes tipos de ‘conversaciones’ y tratarlas según nosotros, los administradores, hayamos decidido cuando creamos las reglas.

El filtrado actúa mediante la inspección de los paquetes, que representan la unidad básica de transferencia de datos entre ordenadores en Internet.

Al crear las reglas de filtrado en un cortafuegos, normalmente se tienen en cuenta diferentes aspectos, como el origen y destino de los paquetes (por ejemplo desde Internet hacia nuestra red privada), el protocolo utilizado y el puerto de destino. Una vez hemos considerado algunos de estos aspectos, provocaremos que se ejecute una acción. Algunas de ellas podría ser: permitir la entrada de los paquetes, redirigirlos, denegarlos o “perderlos”.

Nota: Existe una diferencia clave entre denegar una conexión (reject rechaza los paquetes) a perderla (drop). Cuando se rechaza una conexión el emisor obtiene un “mensaje de respuesta” (normalmente un paquete ICMP) con el que se informa de la denegación, mientras que si hacemos que se pierdan los paquetes el emisor no recibirá ningana información al respecto.

Un cortafuegos correctamente configurado añade una protección extra a la red, pero en ningún caso debe considerarse suficiente. Cualquier tipo de ataque informático que use tráfico aceptado por el cortafuegos seguirá constituyendo una amenaza.

Un cortafuegos no puede protegernos de aquellos ataques cuyo tráfico no pase a través de él, ni de los fallos de seguridad de los servicios y protocolos cuyo tráfico esté permitido.

Algunas configuraciones

Existen diferentes formas de implementar el firewall en la red, pero sin duda dos de las mas comunes podrían ser las siguientes:

  • Un firewall como muro de una red interna: En este tipo de configuración suele utilizarse un router (el encargado de proporcionarnos el acceso a Internet y redirigir el tráfico de la red) conectado a un switch o directamente a un equipo (un pequeño ordenador portátil o de sobremesa valdría) en el que disponemos de dos interfaces de red. Una de las interfaces será la que conecte al router (nuestra puerta de acceso) mientras que la otra será conectada a un switch donde se comunicará con el resto de ordenadores y servidores de la red interna. Por esta segunda interfaz es por donde pasará todo el tráfico filtrado por nuestro firwall.
  • Un firewall como barrera protectora de un único sistema: La mayoría de las distribuciones Linux traen (activado o no) un cortafuego, se trata del Netfilter IPtables. Con IPtables podremos crear reglas de filtrado de manera que podamos hacer mas segura nuestra conexión con Internet. En ocasiones se suele utilizar para hacer NAT o redirigir conexiones según los puertos (port forwarding), por ejemplo cuando tenemos varios servidores como smtp, web, ftp, etc.. en diferentes ordenadores de la red privada.

NAT (Network Address Translation) : técnica que permite ocultar varios ordenadores (red privada) tras una sola IP pública. Esto se logra mediante el NAT masquerading. Los routers proporcionados por nuestro ISP (Internet Service Provider) emplean esta técnica además de implementar un firewall en la mayoría de los casos.

Netfilter: IPtables

IPtables permite realizar diferentes configuración mediante el uso de las reglas que afectan al sistema de filtrado, ya sea generación de logs, acciones de pre y post routing de paquetes, NAT o forwarding.

IPtables se constituye en tres tablas: filter (para el sistema de filtrado), nat (enmascaramiento y reenvío) y mangled (configuración de opciones de paquetes). Estas tablas a su vez contienen una serie de cadenas que agruparán determinadas reglas según su función. Por ejemplo para la tabla NAT contamos con PREROUTING que permitirá modificar paquetes entrantes antes de su enrutamiento, POSTROUTING los modificará antes de que salgan al destino y OUTPUT que modifica los paquetes generados una vez se hayan enrutado, mientras que en la tabla FILTER podemos añadir reglas a las cadenas (chains) INPUT para los paquetes que entran, OUTPUT para los que salen y FORWARD si quisiéramos realizar un reenvío.

Importante: Cuando queremos hacer forwarding de paquetes, por defecto GNU/Linux no trae habilitada la opción por lo que deberemos de activarla nosotros. Podemos hacerlo de forma temporal (será volátil) a través del sistema de ficheros /proc o bien de forma estática:

  • Volátil:
echo 1 > /proc/sys/net/ipv4/ip_forward
  • Permanecerá a reinicios: deberemos de editar el archivo /etc/sysctl.conf y añadir:
net.ipv4.ip_forward = 1

Los paquetes son analizados primeramente por la tabla NAT, a continuación la tabla FILTER decidirá si pasarán (en caso de que vayan destinado a nosotros) o si hay que reenviarlos a otro destino.

No podemos abarcar ni 1% de lo que supone IPtables por lo que se recomienda acudir a su página man. No obstante se va a explicar como crear algunas reglas básicas para las tablas FILTER y NAT.

Para comenzar a utilizar IPtables deberemos de tener el servicio corriendo. Esto ya sabremos como hacerlo, en función del sistema de inicialización que estemos usando. Para sysV bastará con /etc/init.d/iptables start (stop para pararlo).

Sería interesante comprobar de que reglas dispone la configuración actual de IPtables:

$ sudo iptables -L

Crear reglas en la tabla FILTER

Para crear una regla básica en la tabla FILTER y en la cadena INPUT, podríamos utilizar la siguiente sintaxis:

$ sudo iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT

Con -s <ip> indicamos el origen (source) con -j la acción (en este caso aceptar) y podríamos haber utilizado -d para indicar un destino.

El orden de las reglas es importante, por lo que deberemos de colocar siempre las menos restrictivas en las primeras posiciones, podemos hacerlo directamente desde la línea de comandos, tal que así:

$ sudo iptables -I INPUT 3 -s 192.168.1.0/24 -j ACCEPT

Esto haría que la regla se colocara en la tercera posición. La opción -A simplemente añade, -I inserta en una determinada posición.

Podremos eliminar por ejemplo esta misma regla si pasamos la opción -D

$ sudo iptables -D INPUT 3

o

$ sudo iptables -D INPUT -s 192.168.1.0/24 - ACCEPT

Una regla mas elaborada podría quedar así:

$ sudo iptables -A INPUT -p tcp --dport 80 -s 0.0.0.0 -d 192.168.1.23 -j ACCEPT

Con esta regla indicamos que cualquier conexión proveniente (-s) de cualquier origen con destino (-d) al equipo con IP 192.168.1.23 concretamente por el puerto 80 (–dport, puerto destino) con protocolo tcp (-p) sea (-j) aceptada.

Y con alguna opción:

$ sudo iptables - A INPUT -p tcp --dport 80 -s 0.0.0.0 -d 192.168.1.23 -j REJECT --reject-with tcp-reset

Aquí rechazamos las conexiones (REJECT) y ademas emitimos una respuesta del tipo tcp-reset

Cuando modificamos las reglas deberemos de salvarlas. Para hacerlo en Red Hat bastaría con pasarle el parámetro ‘save‘ (service iptables save o /etc/init.d/iptables save y estas se guardarán en /etc/sysconfig/iptables.

Si estamos usando una distribución Debian o derivado además de ‘save‘ deberemos de pasarle un nombre por lo que acabarán guardándose en /var/log/iptables/<nombre-reglas>

Aviso: Si el directorio no existe deberemos de crearlo.

Para cargar las reglas podremos pasar el parámetro ‘load‘ en Red Hat y ‘load nombre-reglas‘ en Debian.

Crear reglas en la tabla NAT

Podemos ver las reglas para una determinada tabla con el parámetro -t y en nombre de la tabla:

$ sudo -t nat -L

Si queremos ser mas meticulosos y ver las reglas de una cadena concreta y ademas con detalles:

$ sudo -t nat -L PREROUTING -n -v

La opción -n da resultados numéricos y -v detalla información

Podemos eliminar todas las reglas de una tabla:

$ sudo -t nat -F

O concretar a solo las de una determinada cadena de una tabla concreta:

$ sudo -t nat -F OUTPUT

Podemos además de eliminar todas las reglas, poner los contadores a cero (útil cuando vamos a comenzar a definir reglas desde 0):

$ sudo -t nat -F
$ sudo -t nat -Z

Nota: Podemos omitir la tabla para que afecte de forma global.

Crear la regla de oro, es decir, conectar todos los ordenadores de una red privada con Internet a través de un dispositivo que posee dos interfaces de red, una conectada hacia Internet y la otra hacia el switch de la red privada. Esto recibe el nombre de Source NAT o SNAT (cambia la dirección IP de origen, en este caso para convertirla en la IP pública de nuestro ISP):

$ sudo iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to 88.23.144.210

Añadimos esta regla a la cadena POSTROUTING indicando el origen (-s) nuestra red privada. Solo se aplicará a los paquetes que salgan (-o, output) por la interfaz de red ‘eth0‘, la acción (-j) será SNAT y la nueva IP es 88.23.144.210 (la ofrecida por nuestro ISP). Existen diferentes formas de conocer nuestra IP pública, por ejemplo a través del router o de Internet, accediendo a direcciones como http://www.cualesmiip.com

Aviso: Este tipo de regla es configurada de esta manera cuando la IP que nos ofrece nuestro ISP es estática. Suele ser un servicio extra ofrecido por la compañía mediante pago.

Ahora vamos a crear la misma regla pero para una IP dinámica, es decir, lo común en cuanto a las IP ofrecidas por los ISP.

$ sudo iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE

Como vemos solo cambia la acción, que en este caso usamos MASQUERADE que lo que hace es usar la IP que tiene en esos momentos configurada nuestra interfaz eth0

Para terminar con la configuración de reglas básicas de IPtables vamos a crear una regla común, que por lo general se suele hacer a nivel ‘casero‘ desde el propio firewall del router ofrecido por nuestro ISP, y es la de direccionar peticiones de acceso a un determinado servicio que escucha en un puerto concreto. El circuito típico sería, una conexión que entra desde la IP pública y que debe ser encaminada hacia una dirección IP privada específica en la cual puede haber corriendo varios servicios pero en concreto queremos configurar el servidor web que por defecto escucha en el puerto 80. Para conseguir esto deberemos de aplicar la regla a la cadena PREROUTING ya que el paquete acaba de entrar y seremos nosotros quien le cree la ruta de encaminamiento.

$ sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth0 -j DNAT --to 192.168.1.52

Nuevas opciones serían la -i (input) y la acción DNAT que es equivalente a –to-destination con la que se modifica la IP de destino.

ufw el front-end de IPtables

Algunas distribuciones como Debian y sus derivados, traen preinstalados el paquete ufw (Uncomplicates Firewall) que no es mas que un front-end para IPtables, de manera que podamos crear reglas de una forma mas sencilla. Para los fanáticos del GUI existe GUFW que igualmente es un front-end (esta vez gráfico) para crear reglas IPtables.

Un uso sencillo de ufw podría ser el siguiente:

  • Denegar todo el tráfico entrante y permitir todo el saliente:
$ sudo ufw default deny incoming
$ sudo ufw default allow outgoing
  • Abrir un puerto para un determinado servicio (bien por número o por nombre de servicio):
$ sudo ufw allow 139
$ sudo ufw allow samba

Nota: Para eliminar una regla añadimos delete entre ufw y allow

  • Comprobar los nombres de servicio que maneja ufw:
$ sudo ufw app list
  • Abrir un puerto y especificar el tipo de protocolo:
$ sudo ufw allow 443/tcp

Nota: Para abrir un rango usamos xxxx:yyyyy/protocolo

  • Crear una regla algo mas compleja (permitir todas las conexiones ssh a mi máquina cuyo origen se encuentra dentro de mi red)
$ sudo ufw allow from 192.168.1.0/24 to 127.0.0.1 app ssh
  • Ver la configuración actual:
$ sudo ufw status verbose
  • Resetear todas las reglas:
$ sudo ufw reset
  • Habilitar o deshabilitar el servicio al inicio:
$ sudo ufw enable/disable

 

Sistemas de detección de intrusos (IDS)

Los sistemas de detección de intrusos (IDS) nos permiten mediante la utilización de nuestros propios recursos y la explotación de nuestro sistema, detectar posibles intrusiones en tiempo real. Lo normal es utilizar un detector de intrusos cuando hemos “terminado” aparentemente de configurar la seguridad de nuestra red y sistemas, de manera que los IDS que instalemos nos encuentren posibles vulnerabilidades que podamos intentar resolver, cerrando con ello agujeros de seguridad no deseados en nuestros sistemas. Igualmente su uso periódico nos informará de posibles ataques, uso malicioso de los recursos del sistema, modificación de ficheros, tráfico sospechoso, puertos que no deberían de permanecer abiertos, etc…

Podemos instalar y explotar un IDS destinado a localizar vulnerabilidades en el sistema local, denominado IDS basado en host, de forma que filtre los registros del sistema producidos por el demonio syslogd y los compare con una base de datos interna en la que se registran vulnerabilidades y ataques conocidos. Aquellos registros de log que hayan sido catalogados como anómalos por el IDS serán re-etiquetados con el nivel de criticidad que estime oportuno el detector de intrusos y se recopilarán en un nuevo log que posteriormente será enviado al administrador para su análisis. Para aquellos archivos de configuración típicos o servicios bastantes usuales, los IDS suelen crear sumas de verificación con md5sum o sha1sum cuyo resultado servirá para ir comparando periódicamente si los archivos han sufrido algún tipo de modificación. Con todo esto podremos encontrar archivos de configuración de servicios típicos que hayan sido modificados, servicios que trabajan de forma sospechosa, explotación indebida de los recursos del sistema, etcétera.

Igualmente podemos analizar la red en busca de servicios mal configurados, puertos abiertos que experimentan tráfico sospechoso, interfaz de red en modo promiscuo, etc…

Algunos de los sistemas de detección de intrusos mas populares son:

  • Tripwire: Es el IDS basado en host mas popular. No está soportado en Red Hat. Mantiene una base de datos de sumas de verificación de los ficheros mas importantes del sistema con la que poder comparar cada cierto tiempo en busca de posibles modificaciones. De esta forma sirve como medida preventiva ante posibles modificaciones en archivos de configuración del sistema provocados frecuentemente por los rootkit. La herramienta libre cuyo funcionamiento se asemeja al de TripWire es AIDE.
  • RPM como IDS basado en host: Es posible usar el gestor de paquetes de Red Hat como un IDS basado en host. Para ello deberemos de importar la GPG de Red Hat a nuestro llavero de claves públicas de forma que se puedan comparar los paquetes instalados con la base de datos de Red Hat. Las opciones que nos ayudarán a esto serán -V, sola o junto con otras opciones como ‘a‘ que verifica todos los paquetes o ‘f‘ que verifica un único archivo dentro de un paquete. Por defecto -V <nombre_de_paquete> verifica todos los archivos que contiene el paquete y -K útil para comprobar la suma de verificación y la GPG de un determinado paquete .rpm. Esta última opción es útil si queremos comprobar que un paquete a sido firmado por Red Hat (veremos las firmas GPG en la última sección de este capítulo).
  • SWATCH: Aunque no fue diseñado para ser un IDS basado en host, hace el trabajo de este al comprobar los registros del sistema y alertar de cualquier posible amenaza.
  • LIDS (Linux IDS): Parche del kernel y herramienta de administración útil para controlar las modificaciones en archivos a través de ACLs.
  • Snort: IDS basado en red de poco peso capaz de realizar análisis del tráfico de red en tiempo real. Permite filtrar por protocolos o contenido mediante la creación de reglas. Snort identifica gran cantidad de intrusiones y pruebas como buffer overflows, escaneos indetectables de puertos, pruebas de SMB, intentos de reconocimientos del sistema operativo, etc…

 

El servicio SSH

En la sección sobre la seguridad en la red vimos algunos servicios o protocolos de conexión remota (Telnet, ftp, VNC, escritorio remoto mediante X, etc..) los cuales compartían una vulnerabilidad, enviar los datos sin encriptar. Si estuviésemos utilizando algunos de estos servicios y existe en nuestra red un fisgón o intruso que esta monitorizando nuestras transferencias, este podría hacerse fácilmente con nuestras credenciales.

Para cerrar esta gran brecha de seguridad se diseñó el protocolo SSH, el cual utiliza técnicas de encriptación fuerte en todas las partes de la conexión de red, lo que lo convierte en un protocolo de conexión remota mucho mas seguro. El protocolo SSH nos permite transferir archivos (scp), conexión remota con X (ssh -X), utilizar servicios como ftp de forma segura (sftp) e incluso la posibilidad de crear túneles por los que transmitir la información de otros protocolos que no encriptan sus datos.

Nota: Podemos usar el comando scp de manera similar a como lo hacemos con cp, de forma que podamos copiar uno o varios archivos a una máquina remota de forma segura. Para utilizar scp bastaría con utilizar la siguiente sintaxis:

scp <archivo_a_copiar> usuario_remoto@ip_o_nombre_de_máquina_remota:/directorio/donde/copiaremos/el/archivo

Aviso: Es obligatorio conocer la contraseña del usuario remoto, a menos que tengamos activado un acceso sin contraseña, algo que aprenderemos en una sección posterior.

La principal desventaja de SSH es que la encriptación y desencriptación consumen tiempo de CPU lo que ralentiza las conexiones degradando incluso el rendimiento global del sistema.

El servidor mas popular en Linux es OpenSSH (sshd), del que se dispone también de su versión cliente (ssh).

 

Configurando SSH

Podremos iniciar el servidor sshd desde un súper servidor o mediante su script de inicio. Siempre que modifiquemos su configuración será necesario el reinicio del servicio o recarga del archivo de configuración.

La mayoría de la configuración de sshd se realiza a través de su archivo de configuración /etc/ssh/sshd_config mientras que la configuración del cliente podremos llevarla a cabo mediante el archivo /etc/ssh_config.

El archivo de configuración /etc/sshd_config se compone mayormente de líneas que adoptan el siguiente formato:

opción valor

Por regla general el servicio ssh (tanto el cliente como el servidor) vienen preconfigurado de manera que podemos hacer un uso seguro de él, no obstante conviene revisar algunas de las opciones, sobre todo de cara a la parte del servidor, como por ejemplo:

  • El nivel de protocolo que estamos usando: OpenSSH admite los niveles 1 y 2, siendo el 2 el mas seguro aunque en ocasiones se encuentra límitado con respecto a la comunicación con otros clientes. Podemos configurar el nivel de protocolo de manera que se use uno u otro o incluso los dos que según cual señalemos como primera opción será el que se use por defecto, por ejemplo 2,1.
  • Permitir el acceso directo de root mediante OpenSSH: Una medida de seguridad sería establecer la opción PermitRootLogin en no de manera que para hacerse con privilegios de root no baste con conocer solo su contraseña, si no que deberá de acceder primero con otro usuario vía ssh, por lo que deberá de conocer a parte de la clave de root la de ese determinado usuario y acto seguido cambiar a root mediante su. Ya vimos como además cambiando el shell por defecto del usuario root en /etc/passwd podemos incluso prohibirle el acceso a la consola.
  • Activar X remoto: Con la opción X11Forwarding podremos indicar si deseamos activar la funcionalidad del túnel para X. Si deseamos usar ssh -X usuario@host para acceder de forma remota al servidor X, deberemos de cambiar el valor de esta opción a yes.

Lo ideal sería que configuráramos SSH para que solo aceptara conexiones de nivel 2 del protocolo y rechazara accesos directos como root. Si no es necesario el redireccionamiento de X, deberíamos de desactivar la opción X11Forwarding. En la medida de lo posible deberemos de utilizar un cortafuegos (filtrando el puerto 22) o TCP Wrappers (/etc/hosts.allow y /etc/hosts.deny) para limitar los equipos que pueden contactar con el servidor SSH. Igual que podíamos restringir la conexión directa de root a través de ssh, podemos hacer que se permita solo su acceso. Si existe el archivo /etc/nologin SSH lo tendrá en cuenta y negará el acceso a todos los usuarios menos a root.

Como con todos los servidores deberemos de mantenerlo actualizado pues siempre existe la posibilidad de que un bug cause problemas.

Configurar túneles SSH

Como ya se comentó, SSH tiene la capacidad de crear túneles por donde otros protocolos conducirán sus datos de manera que estos sean encriptados, evidentemente esto precisa de configuraciones adicionales.

Nota: A la creación de túneles SSH para conducir el flujo de datos creados por otros protocolos se le conoce como tunneling

Para que veamos de una forma mas o menos clara el funcionamiento del tunneling vamos a ejemplarizar una configuración en la que se desea que el tráfico de correo electrónico desde el servidor IMAP (en este caso) hacia el cliente, se realice bajo un túnel SSH de manera que se conserve la privacidad. Para ello el servidor de correos dispondrá tanto del servidor IMAP (protocolo que hará uso del túnel) como del servidor SSH, y de la misma manera el cliente deberá de tener ejecutándose un cliente SSH y un cliente del protocolo que hará uso del túnel (un cliente de correos en este caso). Con esto la comunicación será encriptada por SSH y enviada a través del túnel bajo el protocolo IMAP.

Para que esta comunicación sea posible deberemos de activar la opción AllowTcpForwarding en el archivo de configuración del servidor SSH (/etc/sshd_config) y en el lado del cliente deberemos de crear una conexión especial con el servidor de correos como esta:

# ssh -N -f -L 143:mail.freeser.com:143 nebul4ck@undominio.es

donde:

  • -N indica que no ejecute un comando remoto
  • -f que se ejecute en segundo plano tras solicitar la contraseña
  • -L indica el puerto local en el que se escucha (normalmente 143 para el protocolo IMAP, utilizado tanto en el cliente como en el servidor)
  • Tras los primer dos puntos ‘:‘ encontramos la dirección del servidor de correos y el puerto en el que se escucha. El último parámetro el usuario y host con el que estableceremos el túnel.

Una vez establecido el túnel podremos utilizar nuestro programa cliente para conectarnos al puerto local especificado (143)

 

Uso de las claves SSH

Uno de los sistemas de seguridad que implementa el protocolo SSH es el uso de claves, especialmente dos, la clave pública (con la que podremos desencriptar mensajes) y la clave privada (la utilizada para encriptar mensajes). En una comunicación cifrada cada lado envía su clave pública al otro extremo de manera que solo con esa clave se puedan descifrar los mensajes que han sido encriptados por su respectiva clave privada.

Los datos encriptados con una clave pública solo podrán ser descifrados por la clave privada coincidente. Un ejemplo sería la conexión remota entre un cliente y un servidor bajo ssh, donde el cliente tendrá la clave pública del servidor al que conecta y cuando codifique información lo hará mediante esta clave de manera que solo el servidor bajo su clave privada pueda descifrar estos datos.

Importante: Si algún intruso se hiciese con la clave privada del servidor, correríamos el riesgo de que todos nuestros datos fueran descifrados por el atacante.

Las claves públicas de uso individual de los servidores, se guardan en el directorio ~/.ssh/known_hosts del cliente, mientras que las de uso global se encuentran en el archivo ssh_known_hosts que suele colgar de /etc o /etc/ssh. Una modificación en una clave pública sería motivo de sospecha de falsificación.

En el pasado podíamos comprobar el contenido de estos archivos con editores de texto, en cambio, desde OpenSSH 4.0 es posible habilitar la encriptación para los datos de este archivo de manera que la información se codifique mediante un algoritmo de encriptación de único sentido (hash). Así ni los intrusos ni nosotros mismos, podremos identificar el servidor al que nos conectamos, únicamente el cliente y servidor compararán el hash y si coincide se aceptará la conexión.

Para que este sistema funcione hacen falta un total de cuatro a seis claves generadas automáticamente cuando se ejecuta el script de inicio de sshd. Estas claves necesarias son las correspondiente a las dos o tres herramientas de encriptación que admite SSH (rsa, rsa1 y dsa) y se suelen almacenar bajo /etc/ssh. Las mas corriente suelen ser ssh_host_rsa_key y ssh_host_dsa_key a las que se le añadde la extensión .pub para sus coincidentes claves públicas. Quizás haya sistemas que cuenten con esta otra: ssh_host_rsa1_key

Si no disponemos de la privada y pública (rsa1) y no podemos poner el sistema en funcionamiento, podremos probar a utilizar el comando ssh-keygen de la siguiente manera:

# ssh-keygen -q -t rsa1 -f /etc/ssh/ssh_host_key -C '' -N ''

Esto generará tanto la privada como la pública y también es válido para rsa y dsa.

Aviso: Debemos utilizar permisos restrictivos para los archivos de las claves privadas, normalmente 0600 (rw——-) con propietario root. A las públicas debería de tener acceso todo el mundo.

 

Accediendo vía SSH

Para acceder a un servidor remoto bajo ssh es tan sencillo como instalar el paquete OpenSSH client y ejecutar el siguiente comando:

$ ssh usuario@maquina

A continuación, si es la primera vez que accedemos al sistema remoto se nos pedirá confirmación, de manera que tras introducir la clave del usuario, la clave pública de la máquina remota será guardada en nuestro llavero de claves públicas (~/.ssh/known_hosts). El resto de las veces no se nos pedirá confirmación pero si la clave del usuario remoto.

Este sería el método normal para acceder bajo SSH a un sistema remoto. No obstante, existen otras formas para acceder sin hacer uso de una password, de manera que podamos loguearnos a través de por ejemplo tareas automatizadas con shell scripting.

Uso de ssh-Agent

Otra opción para conectar es emplear el programa ssh-agent el cual solicitará una contraseña (passphrase) para iniciar las conexiones.

Para utilizar ssh-agent deberemos de seguir unos pasos sencillos pero necesarios:

1 . Desde el sistema cliente (el que utilizaremos para conectarnos al servidor remoto) generaremos una clave SSH versión 2 (rsa y dsa, o rsa1 para versión 1):

$ ssh-keygen -q -t rsa -f ~/.ssh/id_rsa -C ''
2 . Se nos pedirá una frase (passphrase) de contraseña la cual será la que utilicemos para futuras conexiones:

3 . Ahora será el momento de acceder al servidor remoto:

 $ ssh usuario_remoto@servidor

Escribiremos la contraseña del usuario_remoto accediendo ya al servidor. Ahora copiaremos el contenido de nuestro archivo id_rsa.pub (creado en el paso 1) al final del archivo ~/.ssh/authorized_keys o ~/.ssh/authorized_keys2 (anillo de claves públicas) del directorio /home de usuario_remoto. Si no existiese ninguno de estos dos archivos deberíamos de crear uno de ellos.

Nota: Puede que en algunos sistemas tengamos que cambiar los permisos del archivo ~/.ssh/authorized_keys y directorios. Normalmente es suficiente con eliminar los permisos de escritura (0600) y asegurándonos de que el propietario es usuario_remoto.

4 . Ahora ya podremos usar ssh-agent desde el sistema cliente. Para ello ejecutaremos

$ ssh-agent /bin/bash

Esto abrirá un nuevo shell dentro del que hemos usado para ejecutar este comando. No notaremos nada, solo si vemos los procesos ejecutados podremos ver el nuevo proceso creado:

ssh-agent

Desde esta ‘sesión‘ escribiremos primeramente ssh-add ~/.ssh/id_rsa para añadir nuestra clave RSA al conjunto gestionado por ssh-agent. Se nos pedirá que introduzcamos la frase/clave que introducimos al crear el par de claves en el paso 1.

Aviso: Cada vez que queramos volver a realizar accesos al sistema remoto al que hemos facilitado nuestra clave pública no deberemos de dar la contraseña del usuario remoto, pero si que tendremos que repetir el paso 4.

Si utilizamos este sistema con frecuencia desde nuestro usuario local, podemos hacer que cada vez que se inicia bash lo haga ejecutando ssh-agent. Esto podemos lograrlo modificando /bin/bash por ssh-agent /bin/bash en la línea de nuestro usuario del archivo /etc/passwd.

Acceder sin contraseñas

Hemos pasado de acceder a un host remoto bajo credenciales (usuario y contraseña) de un usuario específico de ese sistema, a acceder con un usuario del sistema pero sin que se nos solicite mas clave que una propia creada cuando generamos nuestra clave pública. Lo siguiente es ya acceder directamente sin esa clave, es decir, conectaremos contra un host remoto sin que se nos solicite ningún tipo de password, ni la del usuario remoto, ni la nuestra propia.

Para conseguir esto, podremos recurrir a estas dos opciones:

A. Realizaremos el paso 1, y 3 vistos anteriormente cuando utilizábamos ssh-agent. En este caso el paso 1 debe modificarse añadiendo la opción -N ‘ ‘ quedando así:

$ ssh-keygen -q -t rsa -f ~/.ssh/id_rsa -C '' -N ''

Nos hemos saltado el paso 2 puesto que con este comando no se nos solicitará ninguna clave. En el paso 3 todo igual, el usuario de la máquina remota (usuario_remoto en nuestro ejemplo) debe tener el contenido de nuestra clave pública en su archivo de autorización, normalmente ~/.ssh/authorized_keys

Si ahora salimos del servidor remoto y volvemos a entrar no se nos pedirá ningún tipo de contraseña.

B. Esta forma es aún mas sencilla. Haremos uso del comando ssh-keygen y de ssh-copy-id (con este último, evitaremos tener que entrar al servidor remoto y copiar el contenido de nuestra clave pública en el archivo de autorización del usuario_remoto, es decir, realizar el paso 3 de ssh-agent de forma automática)

1 . Creamos nuestro par de claves:

$ ssh-keygen -b 4096 -t rsa

donde:

-b genera una clave de 4096 bits, por defecto (si no usamos -b) se generará de 2048, que suele ser suficiente.

-t indica el tipo de clave, en nuestro caso rsa para protocolo 2

Nota: Deberemos de pulsar tres veces [ENTER]

2 . Copiamos de forma automática nuestra clave pública en un equipo remoto para un usuario específico, tal que así:

$ ssh-copy-id usuario@ip_del_equipo

En este paso se nos pedirá el password de “usuario”. Con esto habremos acabado. El resto de veces que queramos acceder a esa máquina con ese usuario, NO, se nos solicitará password ni passphrase. Esto resulta muy útil cuando tenemos tareas programas con shell scripts que pretenden acceder a un servidor remoto de forma automática.

 

 

Encriptar y firmar datos con GPG

GPG (GNU Privacy Guard) es una herramienta de cifrado y firmas digitales de código libre implementada de la herramienta propietaria PGP (Pretty Good Privacy, Privacidad bastante buena). Con GPG podremos por ejemplo, encriptar mensajes de correo electrónico, de manera que mantengamos una cierta privacidad en cualquier punto de la red que este atraviesa, además de poder firmarlo digitalmente. El firmar un mensaje implica que el destinatario del mismo pueda verificar mediante su herramienta GPG que el contenido no haya sido alterado.

Nota: GPG se utiliza principalmente para proteger y verificar correos electrónicos, por lo que la mayoría de clientes de correo de Linux proporcionan interfaces GPG

 

Generar, exportar, importar y recovar claves con GPG

Al igual que ocurre con las claves SSH, necesitaremos una clave privada y una clave pública GPG. Con la clave privada firmaremos los mensajes mientras que con la pública los lectores del mismo podrán realizar la verificación de la misma o bien, podremos encriptar un mensaje con la clave pública de un destinatario de manera que solo él mediante su clave privada pueda descifrarlo.

Generar claves

Para generar un par de claves utilizaremos el comando gpg con su opción –gen-key tal que así:

$ gpg --gen-key

Tras responder a una serie de preguntas relacionadas con la clave, como por ejemplo el nombre completo de la persona, dirección de correos, contraseña (muy importante recordarla y no perderla), etc… se crearán las claves en el directorio ~/.gnupg.

Nota: Es posible que generar la clave tarde un poco, esto irá en función del tamaño de clave que hayamos puesto (por defecto 2048 bits) y la rapidez de generación de números aleatorios de nuestro sistema (entropía), podemos forzar esto moviendo continuamente por ejemplo el ratón. Sería interesante que se buscara información de como generar la entropía, no obstante tampoco es un requisito indispensable el saber esto.

Ahora podremos usar la opción -k de gpg para ver el ID de la clave, algo que no será útil para exportarla.

$ gpg -k
pub 2048R/BC9DAD91 2015-03-28 [expires: 2015-03-30]
uid 4sysadmins <nebul4ck@4sysadmins.com>
sub 2048R/24D3B0D1 2015-03-28 [expires: 2015-03-30]

Exportar las claves

Una vez generadas las claves podremos exportarlas de manera que podamos crear una clave pública para cada usuario que quiera descifrar o verificar nuestro correo, o bien encriptar sus mensajes con ella para que solo nosotros bajo nuestra clave privada podamos leerlo.

Para exportar una clave basta con utilizar el comando gpg pero esta vez con su opción –export. Le pasaremos como parámetro el ID del propietario, normalmente el nombre o correo electrónico que introducimos al crear la clave, o bien el número BC9DAD91 que tenemos en la línea pub de la salida del comando anterior (este ID es solo un ejemplo, deberemos de reemplazarlo por el que generemos nosotros). Podremos utilizar el nombre o correo electrónico del usuario al que irá destinada nuestra clave publica o un identificador global si la vamos a compartir con un departamento, organización, etc… o bien utilizar nuestro nombre o correo de manera que el destinatario relacione la clave con nosotros.

$ gpg --export nuestro_ID > nebul4ck-gpg.pub

o

$ gpg --output nebul4ck-gpg.pub --export nuestro_ID

Con este comando estaremos generando una clave pública (nebul4ck-gpg.pub) la cual se creará en el directorio en el que estamos trabajando y que posteriormente distribuiremos para que puedan verificar nuestros correos/documentos o encriptar sus mensajes para que solo nosotros podamos descifrar.

Si teníamos pensado enviar nuestra clave pública por correo, podríamos haber añadido la opción –armor al comando gpg –export de manera que se generara una salida ASCII.

Otras formas de distribuir nuestra clave puede ser como adjunto en un email, subirla a un sitio Web o a través de un servidor de claves. Un servidor de claves es un servidor de red que funciona como un depósito donde se almacenarán las claves públicas a distribuir. Podemos almacenar nuestra clave pública en un depósito de claves de la siguiente manera:

$ gpg --keyserver pgp.rediris.es --send-keys ID_denuestraclave
  gpg: sending key BC9DAD91 to hkp server pgp.rediris.es

Este comando enviará nuestra clave al servidor de claves pgp.rediris.es (servidor de claves públicas) para que posteriormente pueda ser descargada por algún interesado.

Aviso: Para crear claves públicas anteriormente utilizamos el uid (nombre o correo electrónico) o bien el código de la línea pub de la salida del comando gpg -k. Para subir una clave pública a un depósito de clave solo servirá el ID de la linea pub.

Nota: Existen diferentes servidores públicos de claves gpg públicas. Es muy importante generar un certificado de revocación de clave si hemos decidido enviar nuestra clave a un servidor, ya que está será distribuida en pocos minutos al resto del mundo. Veremos esto en el aparatado “Revocando claves en desuso

Importando claves de terceros

Ahora que hemos visto como exportar nuestra clave, es igualmente importante saber importar la clave de un usuario con el que queremos mantener una cierta privacidad, ya sea porque vaya a firmar documentos que nos interese corroborar que vienen emitidos por el sin ser alterados, o porque vayamos a encriptar información mediante su clave pública de manera que solo él con su clave privada pueda descifrar.

Podremos añadir la clave de un tercero a nuestro depósito de la siguiente forma:

$ gpg --import <nombre-archivo>

O bien, importarla desde un servidor de claves:

$ gpg --key-server <nombre_host> --recv-keys <id_clave>

De la misma manera que comprobamos la existencia de nuestra clave, podremos verificar el uid e id pub de la nueva clave agregada:

$ gpg --list-keys

Nota: Esto es igual que emplear la opción -k

Revocando claves en desuso

Cuando generamos un nuevo par de claves es importante el crear acto seguido un certificado de revocación de clave. Imaginemos que queremos dejar de usar nuestra clave pública por el motivo que sea, por ejemplo porque se encuentre en un depósito de claves público y nuestra clave privada se ha visto comprometida o simplemente hemos olvidado nuestra contraseña de clave y no queremos que se haga mas uso de ella. Una clave pública revocada puede ser utilizada para verificar firmas realizadas en el pasado o descifrar mensajes que hayan sido cifrados antes de la revocación, siempre y cuando el usuario todavía tenga acceso a su clave privada. Lo que no será posible es cifrar datos una vez la clave sea revocada.

Para crear el certificado de revocación haremos lo siguiente:

$ gpg --gen-revoke <ID_clave>

Podemos añadir la opción –output <nombre_archivo.gpg> si en vez de mostrar el certificado por la stdout se añada a un archivo.

Una vez tengamos generado el certificado deberemos de copiar y pegar el texto mostrado por la stdout en un archivo (en caso de que no hayamos agregado la opción –output directamente). Este será nuestro certificado de revocación. Si llega el momento de revocar la clave deberemos de importar este certificado en nuestra clave, bastará con:

$ gpg --import <nombre_archivo.gpg>

Deberemos de distribuir esta revocación a los usuarios que estaban haciendo uso de nuestra clave. Si la teníamos subida a un depósito de claves público, deberemos de volver a usar el comando gpg con las opciones –keyserver y –send-keys para importar nuestra clave revocada.

Cifrar y descifrar documentos

Para cifrar un documento con la clave pública de un usuario (por ejemplo jjgomez) desde el usuario nebul4ck podremos hacer lo siguiente:

1 . Se supone que ta tenemos importada a nuestro anillo de claves la clave pública de jjgomez por lo que vamos a comprobar su ID:

$ gpg -k
/home/nebul4ck/.gnupg/pubring.gpg
--------------------------------
pub 2048R/BCK2ADAK 2015-03-28 [expires: 2015-03-30]
uid nebul4ck <nebul4ck@freeser.com>
sub 2048R/2AD3B0D9 2015-03-28 [expires: 2015-03-30]
pub 2048R/5GJ945FD 2015-03-30 [expires: 2015-04-01]
uid Jose Julio Gómez (Mi mail) <jjmgomez@gmail.com>
sub 2048R/CB851754 2015-03-30 [expires: 2015-04-01]

2 . Ciframos de la siguiente manera (usaremos el nombre, correo o ID de jjgomez)

$ sudo gpg --output contabilidad_2015.dot.gpg --recipient 5GJ945FD --encrypt contabilidad_2015.gpg

De esta manera obtendremos un archivo binario, por lo que no podremos pasarlo directamente por email a menos que sea como adjunto. Podremos añadir la opción –armor para codificarlo en ASCII y poder copiar y pegar el texto en un correo.

$ sudo gpg --output contabilidad_2015.dot.gpg --recipient 5GJ945FD --armor --encrypt contabilidad_2015.dot

Ahora vamos a descifrar el documento desde el usuario jjgomez:

$ sudo --output contabilidad_2015.dot --decrypt contabilidad_2015.dot.gpg

Nos pedirá la contraseña (la que introdujo en este caso jjgomez cuando generó su par de claves). Y listo! ya podremos leer el documento.

Firmar mensajes y verificar firmas

Ahora, vamos solamente a firmar el documento anterior (contabilidad_2015.dot) de manera que nuestro destinatario (jjgomez en nuestro caso) pueda verificar que se trata de un documento emitido por nosotros.

Para firmar un documento podremos usar las opciones –sign o –clearsign de gpg. La diferencia entre ambas opciones es que –sign además de firmar el documento, lo encriptará con la clave privada, de manera que el destinatario (jjgomez) podrá verificar que se trata de un documento procedente de nosotros mediante la opción –verify <archivo> pero no podrá leerlo a menos que lo descifre antes con –decrypt. Si utilizamos –clearsign el documento irá sin cifrar, por lo podrá leerse sin problemas y comprobar igualmente mediante –verify que el documento fue emitido por nebul4ck.

Utilizar –sign provocará que se cree un archivo encriptado con el mismo nombre que el original pero con extensión .gpg. Si utilizamos –clearsign el archivo resultando tendrá la terminación .asc

$ gpg --clearsign contabilidad_2015.dot
$ gpg --verify contabilidad_2015.dot.asc

Si queremos profundizar algo mas en el uso de gpg podremos acudir a la siguiente dirección https://www.gnupg.org/gph/es/manual.html, y además leer la página man de gpg.

 


 

Capítulo – 10

 

Licencia Creative Commons
LPIC1 400 – Capítulo 10 – por nebul4ck se distribuye bajo una Licencia Creative Commons Atribución-CompartirIgual 4.0 Internacional.

Anuncios

Deja un comentario, Gracias!

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: