Seguridad en Unix y Redes
Libro en Formato HTML y PDF de seguridad informática realizado por Antonio Villalon Huerta

Los contenidos pueden estar desactualizados con respecto al original

Este documento se encuentra disponible también en formato PDF

Solaris

next up previous contents
Siguiente: Linux Subir: Algunos sistemas Unix Anterior: Algunos sistemas Unix   Índice General

Subsecciones

Solaris

Introducción

Solaris es el nombre del actual entorno de trabajo Unix desarrollado por Sun Microsystems; con anterioridad esta compañía ofrecía SunOS, un sistema basado en BSD, pero a partir de su versión 5 el sistema fué completamente revisado, adoptó el modelo System V y se pasó a denominar Solaris, que es como se conoce actualmente10.1. Hasta la versión 6, el producto era conocido como `Solaris 2.x' - equivalentemente, `SunOS 5.x' -, pero desde su versión 7 se eliminó el `2.x' y simplemente se pasó a llamar `Solaris x', aunque se sigue manteniendo el nombre `SunOS 5.x'; en la actualidad, Sun Microsystems ofrece Solaris 8, y se espera que en 2001 aparezca en el mercado Solaris 9.

Solaris es uno de los Unix más extendidos hoy en día, ya que sus posibilidades comprenden un abanico muy amplio; aunque funciona sobre arquitecturas x86 (lo que permite que cualquiera pueda instalar y utilizar el operativo en un PC casero), el principal mercado de Solaris está en las estaciones y los servidores SPARC (Scalable Processor ARChitecture). Dentro de esta familia de procesadores podemos encontrar todo tipo de máquinas, desde estaciones que pueden ser equivalentes en potencia a un PC (como la UltraSPARC 5) a grandes servidores (por ejemplo, los Ultra Enterprise 10000), pasando por supuesto por servidores medios, como los Ultra Enterprise 3500; esta amplia gama de máquinas hace que Solaris se utilice en todo tipo de aplicaciones, desde equipos de sobremesa o servidores web sencillos hasta sistemas de bases de datos de alta disponibilidad. Su uso como plataforma de aplicaciones relacionadas con la seguridad (típicamente, sistemas cortafuegos funcionando con Firewall-1) también está muy extendido.

Para conocer más el entorno de trabajo Solaris podemos descargar las imágenes del operativo, tanto para arquitecturas SPARC como para x86, y de forma completamente gratuita, desde la web corporativa de Sun Microsystems: http://www.sun.com/. También podemos obtener documentación de casi cualquier tema relacionado con Solaris en la dirección http://docs.sun.com/, o consultar los BluePrints que la compañía publica periódicamente en http://www.sun.com/blueprints/. Existen además numerosas publicaciones relacionadas con diversos aspectos de Solaris: por ejemplo, de su seguridad se habla en [Gre99], y de su diseño interno en [MM00]; sus aspectos genéricos de uso o administración se pueden consultar en cualquier libro de Unix, aunque en muchas ocasiones uno se pregunta si vale la pena realmente comprar algunos libros cuando en Internet tenemos a nuestra disposición cientos y cientos de hojas de magnífica documentación sobre Solaris.

Tal y como se instala por defecto, Solaris - como la mayoría de operativos - no es un sistema especialmente seguro; es necesario dedicar un mínimo de tiempo a retocar y personalizar algunos aspectos de su configuración: tras estos pequeños detalles, un servidor puede pasar a trabajar directamente en explotación con un nivel de seguridad más que aceptable. En este capítulo vamos a hablar de aspectos de configuración, de software, de procedimientos de trabajo...aplicables en Solaris; aunque evidentemente los aspectos de los que hemos venido hablando durante todo el trabajo se pueden - y deben - aplicar en este sistema operativo, aquí entraremos algo más a fondo en algunos aspectos particulares de Solaris.

Seguridad física en SPARC

Los mecanismos de seguridad de más bajo nivel que ofrece Solaris sobre estaciones y servidores SPARC son los que estos implantan en su EEPROM, una memoria RAM no volátil (NVRAM, Non-volatile RAM) a la que se puede acceder pulsando las teclas `Stop-A' (teclados Sun) o `Ctrl-Break' (terminales serie). Esta memoria, también denominada OpenBoot PROM o simplemente OBP es en muchos aspectos similar a la BIOS de un simple PC, pero mucho más potente y flexible; sus funciones son verificar el estado del hardware e inicializarlo (ofreciendo para ello una amplica gama de herramientas empotradas), y por supuesto arrancar el sistema operativo.

Como antes hemos dicho, cualquiera con acceso físico a una máquina SPARC puede interactuar con su NVRAM sin más que pulsar la combinación de teclas `Stop-A'; sin importar el estado en que se encuentre el sistema, automáticamente se detendrán todos los procesos en ejecución y se mostrará en consola el prompt `ok ', que indica que podemos comenzar a teclear órdenes de la OBP. La máquina no pierde en ningún momento su estado a no ser que explícitamente la detengamos: al salir de la OBP podemos continuar la ejecución de todos los procesos que teníamos al entrar, desde el mismo punto en que los detuvimos y con el mismo entorno que poseían, pero mientras estemos interactuando con la EEPROM ningún proceso avanzará en su ejecución.

Al interactuar con la EEPROM, cualquier persona10.2 puede interrumpir al operativo y rearrancarlo desde un disco, un CD-ROM, o un sistema remoto, lo que evidentemente le proporciona un control total sobre el sistema; podemos deshabilitar la función de las teclas `Stop-A' mediante la directiva del kernel `abort_enable' en el fichero /etc/system, o - lo que suele ser más útil - proteger mediante contraseña el reinicio de una máquina desde su memoria NVRAM. Para ello, las máquinas SPARC ofrecen tres niveles de seguridad: `none-secure', `command-secure', y `full-secure'. El primero de ellos, `none-secure' es el que está habilitado por defecto, y como su nombre indica no ofrece ningún tipo de seguridad: cualquiera que pulse `Stop-A' desde la consola del sistema10.3obtiene un acceso total a la EEPROM sin necesidad de conocer ningún tipo de contraseña y puede reiniciar la máquina de la forma que le plazca.

Los dos modos siguientes son los que ofrecen un nivel de seguridad algo superior; si activamos `command-secure' será necesaria una clave para reiniciar el sistema de cualquier dispositivo que no sea el utilizado por defecto (que generalmente será el disco, disk), y si elegimos `full-secure' la contraseña es obligatoria independientemente del dispositivo elegido para arrancar. En cualquier caso, esta clave es diferente de la utilizada para acceder a Solaris como superusuario; si olvidamos la contraseña de la EEPROM pero tenemos acceso root a la máquina podemos usar desde línea de órdenes el comando `eeprom' para modificar (o consultar) cualquier parámetro de la NVRAM, passwords incluidos. Si hemos perdido la contraseña de la EEPROM y no podemos arrancar la máquina, es muy posible que necesitemos sustituir nuestra memoria NVRAM por una nueva, por lo que hemos de tener cuidado con las claves que utilicemos para proteger la OBP; por supuesto, si utilizamos el modo `full-secure' podemos ir olvidándonos de reinicios programados del sistema sin un operador que teclee el password en consola: la seguridad en muchas ocasiones no es del todo compatible con la comodidad o la funcionalidad.

Como hemos adelantado, para consultar o modificar el modo en el que se encuentra nuestra memoria NVRAM podemos ejecutar la orden `eeprom'; en nuestro caso queremos conocer el estado de la variable `security-mode', por lo que desde una línea de comandos teclearíamos lo siguiente:
marta:/# eeprom security-mode
security-mode=none
marta:/#
Podemos ver que en este caso nuestra máquina no tiene habilitado ningún tipo de seguridad; si quisiéramos habilitar el modo `command-secure', ejecutaríamos:
marta:/# eeprom security-mode
security-mode=none
marta:/# eeprom security-mode=command
Changing PROM password:
New password:
Retype new password:
marta:/# eeprom security-mode
security-mode=command
marta:/#
También es posible realizar estos cambios desde el propio prompt de la memoria NVRAM, mediante la orden `setenv'10.4:
ok setenv security-mode command
security-mode =       command
ok
A partir de este momento, cuando el sistema inicie desde un dispositivo que no sea el utilizado por defecto, se solicitará la clave que acabamos de teclear; de forma similar podríamos habilitar el modo `full-secure'. Para eliminar cualquier clave de nuestra memoria no tenemos más que restaurar el modo `none-secure', de la forma habitual:
marta:/# eeprom security-mode=none
marta:/# eeprom security-mode
security-mode=none
marta:/#
Si en los modos `command-secure' o `full-secure' queremos cambiar la contraseña de la NVRAM podemos utilizar de nuevo la orden `eeprom', esta vez con el parámetro `security-password':
marta:/# eeprom security-password=
Changing PROM password:
New password:
Retype new password:
marta:/# eeprom security-password
security-password= data not available.
marta:/#
Como podemos ver, al consultar el valor de la variable, este nunca se muestra en pantalla.

El tercer y último parámetro relacionado con la seguridad de la memoria EEPROM es
`security-#badlogins'
, que no es más que un contador que indica el número de contraseñas incorrectas que el sistema ha recibido; podemos resetear su valor sencillamente asignándole `0'10.5:
marta:/# eeprom security-#badlogins
security-#badlogins=4
marta:/# eeprom security-#badlogins=0
marta:/# eeprom security-#badlogins
security-#badlogins=0
marta:/#
Antes de finalizar este punto quizás sea necesario recordar que los parámetros de seguridad de la memoria EEPROM que acabamos de ver sólo existen en máquinas SPARC; aunque en la versión de Solaris para arquitecturas Intel también existe una orden denominada `eeprom' que nos mostrará los valores de ciertos parámetros si la ejecutamos, únicamente se trata de una simulación llevada a cabo en un fichero de texto denominado `bootenv.rc'. Es posible dar valor a las variables que hemos visto, pero no tienen ningún efecto en máquinas Intel ya que estas se suelen proteger en el arranque mediante contraseñas en la BIOS, como veremos al hablar de Linux.

Servicios de red

Probablemente el primer aspecto relacionado con la seguridad al que debemos prestar atención en un sistema Solaris es a los servicios ofrecidos desde inetd; con la instalación out of the box el número de puertos a la escucha es realmente elevado, y muchos de ellos son servidos desde inetd (después hablaremos de los servicios que se inician al arrancar el sistema). Aparte de los servicios clásicos (telnet, finger...) que - como en el resto de Unices - es imprescindible deshabilitar, en Solaris encontramos algunas entradas de /etc/inetd.conf algo más extrañas, que en muchos casos no sabemos si podemos eliminar (o comentar) si que ello afecte al funcionamiento de la máquina: se trata de ciertos servicios basados en RPC, como cmsd o sprayd. En casi todos los servidores podemos deshabilitar estos servicios sin mayores problemas, pero evidentemente tomando ciertas precauciones: es necesario conocer cuál es la función y las implicaciones de seguridad de cada uno de ellos; en [Fly00a] (especialmente en la segunda parte del artículo) se puede encontrar una referencia rápida de la función de algunos de estos servicios `extraños', así como notas con respecto a su seguridad.

Realmente, de todos los servicios ofrecidos por inetd ninguno es estrictamente necesario, aunque por supuesto alguno de ellos nos puede resultar muy útil: lo normal es que al menos telnet y ftp se dejen abiertos para efectuar administración remota. No obstante, algo muy recomendable es sustituir ambos por SSH, que permite tanto la terminal remota como la transferencia de archivos de forma cifrada; si nos limitamos a este servicio y lo ofrecemos desde inetd, esta será la única entrada no comentada en /etc/inetd.conf:
anita:/# grep -v ^\# /etc/inetd.conf
ssh     stream  tcp     nowait  root    /usr/local/sbin/sshd    sshd -i
anita:/#
Otros de los servicios que Solaris ofrece tras su instalación son servidos por demonios independientes que se lanzan en el arranque del sistema desde scripts situados en /etc/init.d/ y enlazados desde /etc/rc2.d/ y /etc/rc3.d/; al igual que sucedía con los servidos desde inetd, muchos de estos servicios no son necesarios para un correcto funcionamiento del sistema, y algunos de ellos históricamente han presentado - y siguen presentando - graves problemas de seguridad. No vamos a entrar aquí en cuáles de estos servicios son necesarios y cuáles no, ya que eso depende por completo del tipo de sistema sobre el que estemos trabajando; es necesario conocer las implicaciones de seguridad que algunos de los demonios lanzados en el arranque presentan, y para ello una buena introducción es [Fly00b].

Al arrancar una máquina Solaris, por defecto el proceso init situa al sistema en su runlevel 3, lo cual implica que - entre otras acciones - se invoca a /sbin/rc2 y /sbin/rc3; estos dos shellscripts se encargan de recorrer los directorios /etc/rc2.d/ y /etc/rc3.d/, ejecutando cualquier fichero cuyo nombre comience por `S'. De esta forma, para evitar que un determinado script se ejecute automáticamente al arrancar una máquina lo más recomendable es ir directamente a /etc/rc2.d/ o /etc/rc3.d/ y sustituir la `S' inicial de su nombre por otro carácter; esta práctica suele ser más habitual que eliminar el fichero directamente, ya que así conseguimos que si es necesario lanzar de nuevo el script al arrancar Solaris no tengamos más que cambiarle de nuevo el nombre. Por ejemplo, si queremos que el demonio sendmail no se lance en el arranque, no tenemos más que ir al directorio correspondiente y renombrar el script que lo invoca; aparte de eso, es probable que nos interese detenerlo en ese momento, sin esperar al próximo reinicio del sistema:
anita:/# cd /etc/rc2.d/
anita:/etc/rc2.d# mv S88sendmail disabled.S88sendmail
anita:/etc/rc2.d# ./disabled.S88sendmail stop
anita:/etc/rc2.d#
Podemos ver que para detener el demonio hemos invocado al mismo fichero que lo arranca, pero pasándole como parámetro `stop'; si quisiéramos relanzar sendmail, no tendríamos más que volver a ejecutar el script pero pasándole como argumento `start'.

Usuarios y accesos al sistema

Durante la instalación de Solaris se crean en /etc/passwd una serie de entradas correspondientes a usuarios considerados `del sistema' (adm, bin, nobody...); ninguno de estos usuarios tiene por qué acceder a la máquina, de forma que una buena política es bloquear sus cuentas. Podemos comprobar qué usuarios tienen el acceso bloqueado consultando el estado de su contraseña: si es `LK' (locked), la cuenta está bloqueada:
anita:/# passwd -s -a|grep LK
daemon  LK    
bin  LK    
sys  LK    
adm  LK    
lp  LK    
uucp  LK    
nuucp  LK    
listen  LK    
nobody  LK    
noaccess  LK    
nobody4  LK    
anita:/#
Podemos bloquear una cuenta de acceso a la máquina mediante `passwd -l', de la forma siguiente:
anita:/# passwd -s  toni
toni  PS    06/15/01    7  7  
anita:/# passwd -l toni
anita:/# passwd -s  toni
toni  LK    06/27/01    7  7  
anita:/#
A pesar de su estado, las cuentas bloqueadas son accesibles si ejecutamos la orden `su' como administradores, por lo que si estamos bastante preocupados por nuestra seguridad podemos asignarles un shell que no permita la ejecución de órdenes, como /bin/false10.6:
anita:/# su - adm
$ id
uid=4(adm) gid=4(adm)
$ ^d
anita:/# passwd -e adm
Old shell: /bin/sh
New shell: /bin/false
anita:/# su - adm
anita:/# id
uid=0(root) gid=1(other)
anita:/#
Si realmente somos paranoicos, de la lista de usuarios que hemos visto antes incluso nos podemos permitir el lujo de eliminar a nobody4, ya que se trata de una entrada que existe para proporcionar cierta compatibilidad entre Solaris y SunOS que actualmente apenas se usa. No obstante, muchísimo más importante que esto es eliminar o bloquear a cualquier usuario sin contraseña en el sistema; es recomendable comprobar de forma periódica que estos usuarios no existen, para lo cual también podemos utilizar `passwd -s -a' y vigilar las claves cuyo estado sea `NP' (No Password):
anita:/# passwd -s -a|grep NP
prueba  NP
anita:/# passwd -l prueba
anita:/#
Tras estas medidas de seguridad iniciales, lo más probable es que en nuestro sistema comencemos a dar de alta usuarios reales; sin duda, lo primero que estos usuarios tratarán de hacer es conectar remotamente vía telnet:
rosita:~$ telnet anita
Trying 192.168.0.3...
Connected to anita.
Escape character is '^]'.


SunOS 5.8

login: toni
Password: 
Last login: Fri Jun 22 10:45:14 from luisa
anita:~$
A estas alturas ya debemos saber que es una locura utilizar telnet para nuestras conexiones remotas por el peligro que implica el tráfico de contraseñas en texto claro, por lo que debemos obligatoriamente utilizar SSH o similar. Si de cualquier forma no tenemos más remedio que permitir telnet (no encuentro ningún motivo para ello, y personalmente dudo que los haya...), quizás nos interese modificar el banner de bienvenida al sistema, donde se muestra claramente que la máquina tiene instalada una versión concreta de Solaris: esto es algo que puede ayudar a un pirata que busque información de nuestro sistema. Para cambiar el mensaje podemos crear el archivo /etc/default/telnetd, en el que la entrada `BANNER' especifica dicho mensaje:
anita:/# cat /etc/default/telnetd 
BANNER="\nHP-UX anita A.09.05 E 9000/735 (ttyv4)\n\n" 
anita:/# telnet 0
Trying 0.0.0.0...
Connected to 0.
Escape character is '^]'.

HP-UX anita A.09.05 E 9000/735 (ttyv4)

login:
Algo similar se puede hacer con el fichero /etc/default/ftpd para el servicio de FTP, aunque de nuevo dudo que haya algún motivo para mantenerlo abierto; estos mensajes evidentemente no van a evitar que alguien pueda obtener datos sobre el sistema operativo que se ejecuta en una máquina (veremos al hablar del sistema de red en Solaris como conseguir esto), pero al menos no le dejarán esa información en bandeja.

Siguiendo con las conexiones remotas a un sistema, uno de los aspectos que nos puede llamar la atención si estamos comenzando a trabajar con Solaris es que el usuario root sólo puede conectar desde la propia consola de la máquina; si lo intenta de forma remota, se le negará el acceso:
luisa:~$ telnet anita
Trying 192.168.0.3...
Connected to anita.
Escape character is '^]'.

login: root
Password: 
Not on system console
Connection closed by foreign host.
luisa:~$
Esto es debido a que el parámetro `CONSOLE' tiene como valor dicha consola (/dev/console) en el fichero /etc/default/login; para trabajar como superusuario de forma remota es necesario acceder al sistema como un usuario sin privilegios y después ejecutar el comando su. Esta forma de trabajo suele ser la más recomendable, ya que ofrece un equilibrio aceptable entre seguridad y funcionalidad; no obstante, si nos interesara que root pudiera conectar directamente de forma remota (no suele ser recomendable), podríamos comentar la entrada `CONSOLE' en el fichero anterior, mediante una almohadilla (`#'). Si por el contrario queremos que el administrador no pueda conectar al sistema ni desde la propia consola, y sólo se puedan alcanzar privilegios de superusuario mediante la ejecución de su, podemos dejar la entrada correspondiente a `CONSOLE' en blanco:
anita:/# grep -i console /etc/default/login
# If CONSOLE is set, root can only login on that device.
CONSOLE=
anita:/#
En el fichero anterior (/etc/default/login) existen otros parámetros interesantes de cara a incrementar nuestra seguridad. Por ejemplo, el parámetro `TIMEOUT' indica el número de segundos (entre 0 y 900) que han de pasar desde que la máquina solicita el login al conectar remotamente hasta que se cierra la conexión si el usuario no lo teclea; esto nos puede ayudar a evitar ciertos ataques de negación de servicio, pero puede ser un problema si tenemos usuarios que conecten a través de líneas de comunicación lentas o muy saturadas, ya que con un timeout excesivamente bajo es posible que antes de que el usuario vea en su terminal el banner que le solicita su login la conexión llegue a cerrarse.

Relacionada en cierta forma con el parámetro anterior, y también dentro del archivo
/etc/default/login
, la entrada `SLEEPTIME' permite indicar el número de segundos - entre 0 y 5 - que han de transcurrir desde que se teclea una contraseña errónea y el mensaje login incorrect aparece en pantalla. Con `RETRIES' podemos especificar el número de intentos de entrada al sistema que se pueden producir hasta que un proceso de login finalice y la conexión remota asociada se cierre: en otras palabras, indicamos el número de veces que un usuario puede equivocarse al teclear su clave antes de que el sistema cierre su conexión.

Otra directiva interesante de /etc/default/login es `PASSREQ': si su valor es `YES', ningún usuario podrá conectar al sistema sin contraseña, y si es `NO', sí que se permiten este tipo de entradas. Evidentemente, el valor recomendable es el primero, aunque el incremento que conseguimos en nuestra seguridad no es excesivo y sólo se puede encontrar útil en circunstancias muy concretas, ya que a los usuarios que no tengan contraseña simplemente se les obligará a elegir un password al intentar entrar al sistema:
anita:~$ telnet 0
Trying 0.0.0.0...
Connected to 0.
Escape character is '^]'.

login: prueba
Choose a new password.
New password:
Si realmente queremos asegurarnos de que no tenemos usuarios sin clave podemos ejecutar periódicamente la orden `logins -p', que nos mostrará los información acerca de los usuarios sin contraseña en la máquina; si su salida es no vacía, tenemos un grave problema de seguridad:
anita:/# logins -p
prueba            107     staff           10      Usuari en proves
anita:/# passwd prueba
New password: 
Re-enter new password: 
passwd (SYSTEM): passwd successfully changed for prueba
anita:/# logins -p
anita:/#
Para finalizar con /etc/default/login, vamos a hablar de un par de entradas en el fichero relacionadas con la auditoría de los accesos al sistema: el parámetro `SYSLOG' con un valor `YES' determina si se han de registrar mediante syslog los accesos al sistema como root, así como los intentos de login fallidos, y el parámetro `SYSLOG/SMALL>_FAILED/SMALL>_LOGINS' indica el número de intentos de entrada fallidos que se han de producir antes de emitir un mensaje de error; es recomendable que esta segunda variable tenga un valor `0', que implica que syslog registrará todos los intentos fallidos de login:
anita:/# grep -i ^syslog /etc/default/login 
SYSLOG=YES
SYSLOG_FAILED_LOGINS=0
anita:/#
Otro archivo interesante de cara a incrementar aspectos de la seguridad relacionados con los usuarios de nuestro sistema es /etc/default/passwd, donde se pueden definir parámetros para reforzar nuestra política de contraseñas; por ejemplo, podemos definir una longitud mínima para los passwords de los usuarios dándole un valor a la variable `PASSLENGTH':
anita:/# grep -i passlength /etc/default/passwd 
PASSLENGTH=8
anita:/#
Por defecto, la longitud mínima de una clave es de seis caracteres; si le asignamos a `PASSLENGTH' un valor menor (algo poco recomendable de cualquier forma), el sistema simplemente lo ignorará y obligará a los usuarios a utilizar passwords de seis o más caracteres. Además, sea cual sea la longitud de las claves que definamos, debemos tener siempre en cuenta que Solaris sólo interpetará los ocho primeros caracteres de cada contraseña; el resto son ignorados, por lo que dos passwords cuyos ocho primeros caracteres sean iguales serán equivalentes por completo para el modelo de autenticación.

Una contraseña en Solaris debe poseer al menos dos letras (mayúsculas o minúsculas) y al menos un número o carácter especial. Tampoco debe coincidir con el nombre de usuario, ni con rotaciones del mismo (por ejemplo el usuario `antonio' no podrá utilizar como clave `antonio', `ntonioa', `oinotna', etc.), y debe diferir del password anterior en al menos tres caracteres; para cualquiera de estos efectos comparativos, las letras mayúsculas y las minúsculas son equivalentes. Sólo el root puede adjudicar contraseñas que no cumplan las normas establecidas, pero a efectos de seguridad es recomendable que las claves que asigne tengan tantas restricciones como las que pueden escojer los usuarios (o más).

Volviendo de nuevo a /etc/default/passwd, dentro de este archivo tenemos un par de entradas útiles para establecer una política de envejecimiento de claves en nuestro sistema; se trata de `MAXWEEKS' y `MINWEEKS', que como sus nombres indican definen los tiempos de vida máximo y mínimo (en semanas) de una contraseña. Un tercer parámetro, `WARNWEEKS', define el periodo de tiempo (de nuevo, en semanas) a partir del cual se avisará a un usuario de que su password está a punto de caducar; dicho aviso se produce cuando el usuario inicia una sesión:
rosita:~$ telnet anita
Trying 192.168.0.3...
Connected to anita.
Escape character is '^]'.

login: toni
Password: 
Your password will expire in 5 days.
Last login: Sun Jun 24 03:10:49 from rosita
anita:~$
Como no todo va a ser hablar bien de Unix a cualquier precio (aunque Solaris tiene muchos aspectos para hablar bien del operativo), podemos hacer un par de críticas a mecanismos relacionados con las contraseñas en Solaris. En primer lugar, quizás deja algo que desear la granularidad que nos ofrece para el envejecimiento de claves: especificar los valores máximo y mínimo en semanas a veces no es apropiado, y seguramente si Solaris nos permitiera indicar dichos valores en días podríamos definir políticas más precisas; aunque en la mayoría de ocasiones la especificación en semanas es más que suficiente, en casos concretos se echa de menos el poder indicar los días de vigencia de una contraseña. Otro aspecto que se podría mejorar en Solaris es la robustez de las claves: limitarse a rotaciones del nombre de usuario es en la actualidad algo pobre; un esquema como el ofrecido en AIX, donde se pueden especificar incluso diccionarios externos al operativo contra los que comparar las claves que un usuario elige, sería mucho más potente.

Contra el primero de estos comentarios quizás se podría decir, en defensa de Solaris, que realmente en /etc/shadow podemos especificar días en lugar de semanas, pero eso implicaría modificar el archivo a mano para cada usuario, algo que no suele ser recomendable en ningún sistema Unix, o bien ejecutar /usr/bin/passwd con las opciones apropiadas, de nuevo para todos los usuarios en cuestión. Contra el segundo también se podría argumentar que existen utilidades de terceros para reforzar las contraseñas que eligen los usuarios, o bien que no es difícil escribir un módulo de PAM para evitar que esos usuarios elijan claves triviales, pero el hecho es que Sun Microsystems por defecto no incorpora ninguno de estos mecanismos en Solaris.

El sistema de parcheado

Como en el resto de Unices, en Solaris un parche se define como un grupo de ficheros y directorios que reemplaza o actualiza ficheros y directorios existentes en el sistema para tratar de garantizar la ejecución correcta del software ([Mic98]); con la instalación de parches aumentamos - al menos teóricamente - la seguridad y la disponibilidad de un sistema, y es muy recomendable seguir una política de parcheado estricta, al menos en cuanto a parches de seguridad se refiere.

Sun Microsystems distribuye entre sus clientes con contrato de mantenimiento los parches para Solaris y el resto de sus productos vía CD-ROM cada pocas semanas, pero - mucho más rápido -, también los ofrece a través de Internet, desde http://sunsolve.sun.com/; aunque el acceso a ciertos parches está restringido a clientes con contrato, los relativos a la seguridad de los sistemas y los recomendados son completamente públicos.

Desde Sun Microsystems, cada parche es referenciado mediante un dos números: un `patch id', que es el realmente el identificador del parche, y un número de revisión del parche, separados ambos por un guión; de esta forma cuando descargamos un parche desde SunSolve y lo descomprimimos, o cuando lo recibimos en un CD-ROM, dicho parche estará contenido en un directorio cuyo nombre es justamente esa referencia:
anita:/var/tmp# ls 110899-01/
README.110899-01  SUNWcsu
anita:/var/tmp#
Dentro del directorio anterior encontraremos generalmente un fichero donde se nos explica la utilidad del parche, los problemas que soluciona y la forma de aplicarlo; además, existirán una serie de subdirectorios cuyos nombres son los paquetes de software a los que ese parche afecta directamente (es decir, de los que sustituye o actualiza directorios o archivos). Como podemos ver, en el ejemplo anterior sólo encontramos uno de estos subdirectorios, SUNWcsu, lo que indica que el parche sólo afectará a ficheros de ese paquete. A su vez, dentro de cada uno de los directorios que diferencian paquetes software encontramos más archivos y subdirectorios que contienen realmente las versiones actualizadas de programas, así como órdenes post-instalación, descripción del software actualizado, información sobre archivos y directorios modificados, etc.

Desde Sun Microsystems se definen cinco modelos básicos de parches; los standard son parches que solucionan un problema software o hardware específico, por lo que si ese problema no afecta a nuestros sistemas no tenemos por qué instalarlos. Los parches recommended son aquellos que Sun recomienda sea cual sea nuestro entorno para prevenir problemas en el futuro, y los security son los que resuelven problemas de seguridad; evidentemente ambos son de instalación casi obligatoria. Un cuarto tipo son los parches Y2K, que como su nombre indica son los que aseguran el cumplimiento con el año 2000 en todos los productos de Sun; a no ser que trabajemos con versiones de software o hardware antiguo, rara vez tendremos que instalar uno de estos parches, ya que los productos más o menos nuevos no han de tener problemas con el año 2000. Finalmente, el quinto tipo de parches son los patch clusters; no son realmente otro modelo, sino que se trata de agrupaciones de los anteriores que se distribuyen en un único archivo para descargarlos e instalarlos más cómodamente: incluyen un script denominado `install_cluster' que instala en el orden adecuado todos los parches del grupo, lo que evita al administrador tener que hacerlo uno a uno.

Para instalar un parche podemos utilizar la orden `patchadd' en Solaris 7 o superior, o
`installpatch'
en la versión 2.6 o anteriores, en ambos casos evidentemente como root del sistema; suele ser recomendable, en función del tipo de parche y su criticidad, situar a la máquina en modo monousuario antes de aplicarlo, para evitar que actividades de los usuarios puedan interferir con el proceso de parcheado. De esta forma, si queremos aplicar el parche anterior (110899-01), los pasos a seguir serían los siguientes:
anita:/var/tmp# who -r
   .       run-level S  Jun  8 06:37     S      0  ?
anita:/var/tmp# unzip 110899-01.zip
anita:/var/tmp# patchadd 110899-01/

Checking installed patches...
Verifying sufficient filesystem capacity (dry run method)...
Installing patch packages...

Patch number 110899-01 has been successfully installed.
See /var/sadm/patch/110899-01/log for details

Patch packages installed:
  SUNWcsu

anita:/var/tmp#
Muchos parches necesitan un reinicio del sistema para aplicarse correctamente, en especial aquellos que modifican algún parámetro del núcleo de Solaris; si instalamos bloques de parches más o menos grandes, como los Maintenance Updates o los Recommended and Security, el reinicio es casi seguro.

Para comprobar qué parches para el operativo tenemos instalados en una máquina podemos utilizar las órdenes `showrev -p' o `patchadd -p':
anita:/# showrev -p |grep 110899-01
Patch: 110899-01 Obsoletes:  Requires:  Incompatibles:  Packages: SUNWcsu
anita:/#
Es importante resaltar lo de `para el operativo', ya que estas órdenes no muestran en ningún caso los parches aplicados a la OBP; además, hemos de tener presente que si un parche necesita que se reinicie el sistema, `showrev' nos dirá que está instalado, pero aunque la orden no muestre ningún mensaje de error, el parche no tendrá efecto hasta el siguiente reinicio de la máquina. Siguiendo con nuestro ejemplo para ver la información que se nos muestra de cada parche, podemos ver que el parche que hemos instalado afecta al paquete SUNWcsu (algo que ya sabíamos), no deja obsoletas a versiones anteriores, no necesita que esté aplicado otro parche para poder instalarse, y tampoco tiene incompatibilidades.

Si por cualquier motivo deseamos eliminar del sistema un parche que hemos instalado con anterioridad podemos usar la orden `patchrm' en Solaris 7 o superior, o `backoutpatch' si utilizamos versiones más antiguas. Esto restaurará el estado que poseía el sistema - en cuanto a ficheros y directorios - antes de aplicar el parche:
anita:/# who -r
   .       run-level S  Jun  8 06:37     S      0  ?
anita:/# patchadd -p|grep 110899-01
Patch: 110899-01 Obsoletes: Requires: Incompatibles: Packages: SUNWcsu
anita:/# patchrm 110899-01

Checking installed patches...

Backing out patch 110899-01...

Patch 110899-01 has been backed out.

anita:/# patchadd -p|grep 110899-01
anita:/#
El hecho de poder desinstalar un parche con tanta facilidad es debido a que, si no indicamos lo contrario, cuando utilizamos `patchadd' para añadirlo esta orden hace una copia de seguridad de los ficheros y directorios que van a modificar o actualizar, y la guarda en /var/; podemos utilizar la opción `-d' del comando si no queremos esta copia se genere, pero si lo hacemos hemos de tener presente que no podremos desinstalar el parche aplicado: por tanto esto sólo es recomendable en los casos en los que el espacio libre en /var/ sea muy limitado y no tengamos opción de aumentarlo (por ejemplo, ampliando el filesystem o simplemente borrando o comprimiendo archivos).

Sun Microsystems distribuye entre sus clientes con contrato la utilidad PatchDiag, una herramienta realmente útil para mantener al día nuestro nivel de parcheado (y con él, nuestra seguridad); la principal función de este software es determinar el nivel de parcheado de una máquina y compararlo con la lista de parches Recommended and Security de Sun. Esta lista contiene los parches cuya instalación es básica de cara a garantizar la seguridad o el correcto funcionamiento de los sistemas Solaris, y representa los parches que obligatoriamente deben estar instalados en sistemas críticos, como los cortafuegos, si queremos que sean seguros. PatchDiag no aplica estos parches en ningún momento, sino que se limita únicamente a indicar cuáles son necesarios en la máquina donde se ejecuta.

Extensiones de la seguridad

ASET

ASET (Automated Security Enhancement Tool) es un conjunto de herramientas integradas dentro de Solaris que permiten monitorizar ciertos valores de parámetros de los ficheros del sistema, desde atributos ubicados en los inodos (permisos, propietario...) hasta el contenido de cada archivo. Estas herramientas se encuentran en el directorio /usr/aset/, y su utilidad es evidente: permite detectar cualquier cambio en uno de nuestros ficheros, cambio que si no ha sido realizado por un usuario debidamente autorizado puede esconder desde un troyano hasta una puerta trasera de entrada al sistema.

De todas las utilidades de que dispone ASET, la más importante es sin duda /usr/aset/aset, un shellscript encargado de invocar al resto de herramientas. Desde línea de comandos, este programa puede recibir como parámetro el nivel de seguridad deseado en la comprobación: `low', que se limita a informar de las vulnerabilidades potenciales, `mid', que modifica ciertos parámetros que considera incorrectos, y `high', el más restrictivo, que modifica más aún dichos parámetros, y que es recomendable en sistemas en los que la seguridad de Solaris sea un elemento por encima de cualquier otro, como el funcionamiento; incluso en la página man de aset se advierte que algunas aplicaciones pueden dejar de funcionar si utilizamos este nivel de seguridad.

Podemos invocar a /usr/aset/aset indicándole mediante el parámetro `-l' el nivel de seguridad deseado:
anita:/# /usr/aset/aset -l low
======= ASET Execution Log =======

ASET running at security level low

Machine = anita; Current time = 0628_03:11

aset: Using /usr/aset as working directory

Executing task list ...
        firewall
        env
        sysconf
        usrgrp
        tune
        cklist
        eeprom

All tasks executed. Some background tasks may still be running.

Run /usr/aset/util/taskstat to check their status:
     /usr/aset/util/taskstat     [aset_dir]

where aset_dir is ASET's operating directory,currently=/usr/aset.

When the tasks complete, the reports can be found in:
     /usr/aset/reports/latest/*.rpt
You can view them by:
     more /usr/aset/reports/latest/*.rpt
anita:/#
La orden anterior habrá generado un directorio de informes cuyo nombre hace referencia a la fecha y hora de ejecución, y que al ser el último se enlaza también con el nombre latest; todos los reports generados por aset tienen extensión `.rpt' (son simples ficheros ASCII), y se guardan en /usr/aset/reports/. Cada uno de ellos contiene el informe de las potenciales vulnerabilidades que aset ha encontrado durante su ejecución, así como de los cambios que haya realizado en función del nivel de seguridad especificado. Como aset indica, el hecho de que la ejecución del comando haya finalizado no implica que los informes se hayan realizado completamente; podemos ejecutar /usr/aset/util/taskstat para ver que tareas no han finalizado aún.

Además de los informes de los que acabamos de hablar, la primera ejecución de aset genera una serie de archivos en el directorio /usr/aset/master/: en ellos se guarda una imagen del estado que la herramienta ha encontrado en el sistema, de forma que una ejecución posterior del programa - dentro del mismo nivel de seguridad - puede comprobar qué parámetros han cambiado en cada uno de los ficheros analizados; evidentemente, es vital para nuestra seguridad evitar que un atacante pueda modificar esta imagen, ya que de lo contrario podría `engañar' sin problemas a `aset'. Por ejemplo, al ejecutar `/usr/aset/aset' con un nivel de seguridad `low' se ha guardado en esa imagen cierta información sobre un fichero importante como /etc/inittab (en /usr/aset/asetenv se define la lista de directorios de los que se guarda una imagen en cada nivel de seguridad); parte de esta información se encuentra en /usr/aset/masters/cklist.low:
anita:/usr/aset/masters# grep inittab cklist.low 
-rw-r--r-- 1 root sys 1087 Jan 5 23:38 2000 /etc/inittab  26732 3
anita:/usr/aset/masters#
Podemos ver que los parámetros registrados de este archivo: propietario y grupo, permisos, número de enlaces, tamaño, fecha y hora de la última modificación y un checksum. Si ahora un atacante decidiera modificar ese fichero (por ejemplo para situar un troyano en él) casi con total seguridad modificaría alguno de esos parámetros, por lo que la siguiente ejecución de la herramienta reportaría este hecho:
anita:/# grep inittab /usr/aset/reports/latest/cklist.rpt 
< -rw-r--r-- 1 root sys 1087 Jan 5 23:38 2000 /etc/inittab  26732 3
> -rw-r--r-- 1 root sys 1237 Jun 28 19:58 2001 /etc/inittab  37235 3
anita:/#
Quizás una práctica recomendable para incrementar nuestra seguridad pueda ser planificar la ejecución de `aset' para que se ejecute a intervalos periódicos desde `crond' y para que nos avise (por ejemplo, mediante correo electrónico) de cualquier anomalía detectada en la máquina. Si lo hacemos así, hemos de tener siempre presente que el nivel `high' prima la seguridad por encima de cualquier otra cosa, por lo que tras una ejecución planificada de `aset' es posible que alguna aplicación puntual deje de funcionar.

JASS

JASS (JumpStart Architecture and Security Scripts, también conocido como Solaris Security Toolkit) es un paquete software formado por diferentes herramientas cuyo objetivo es facilitar y automatizar la creación y el mantenimiento de entornos Solaris seguros; ha sido desarrollado por Alex Noordergraaf y Glenn Brunette, dos expertos en seguridad de Sun Microsystems conocidos - especialmente el primero de ellos - por los BluePrints que periódicamente publican. Se puede ejecutar sobre una máquina donde previamente hemos instalado Solaris (Standalone Mode), o bien durante la propia instalación del operativo (JumpStart Technology Mode): conseguimos así una instalación por defecto segura, algo que se echa de menos en casi cualquier Unix.

Probablemente la parte más importante de JASS son los denominados drivers, ficheros ón que especifican diferentes niveles de ejecución de la herramienta, definiendo qué scripts se han de ejecutar en cada uno de esos niveles y qué archivos se instalarán como resultado de la ejecución. Cada uno de estos drivers está ubicado en el subdirectorio Drivers/ del programa, y tiene tres partes bien diferenciadas ([NB01b]): la primera se encarga de inicializar ciertas variables de entorno necesarias para una correcta ejecución del driver, la segunda de definir qué ficheros se han de modificar y qué scripts se han de ejecutar, y una tercera parte es la encargada final de llevar a cabo los cambios correspondientes.

En un sistema Solaris ya instalado podemos invocar desde línea de órdenes a JASS pasándole como parámetro el driver que deseemos ejecutar, por ejemplo secure.driver (un driver que implementa por sí sólo todas las funcionalidades de JASS):
anita:/var/tmp/jass-0.3# ./jass-execute -d secure.driver -o jass.log
./jass-execute: NOTICE: Executing driver, secure.driver
./jass-execute: NOTICE: Recording output to jass.log
anita:/var/tmp/jass-0.3#
Todos los cambios que la ejecución anterior provoca (en el ejemplo anterior podemos verlos en el archivo `jass.log', o en salida estándar si no utilizamos la opción `-o') quizás convierten a nuestro sistema en uno `demasiado seguro': es posible que perdamos parte de la funcionalidad de la que disponíamos, debido al elevado número de restricciones llevadas a cabo en el sistema; es necesario que cada administrador revise sus necesidades y los scripts a los que va a invocar antes de ejecutar JASS. Afortunadamente, una de las características más importantes de esta herramienta es su capacidad para deshacer los cambios que cualquiera de sus ejecuciones haya llevado a cabo:
anita:/var/tmp/jass-0.3# ./jass-execute -u -o jass-undo.log
./jass-execute: NOTICE: Executing driver, undo.driver
Please select a JASS run to restore through:
1.  July 06, 2001 at 03:59:40 (//var/opt/SUNWjass/run/20010706035940)
Choice?  1
./jass-execute: NOTICE: Restoring to previous run //var/opt/SUNWjass/run/\
                20010706035940
./jass-execute: NOTICE: Recording output to jass-undo.log
anita:/var/tmp/jass-0.3#
Podemos ver que la desinstalación de los cambios llevados a cabo previamente, mediante la opción `-u' del programa, nos pregunta qué ejecución de JASS queremos desinstalar; como sólo lo habíamos lanzado una vez, hemos elegido `1', pero si ya hubiéramos ejecutado la herramienta en diferentes ocasiones se nos mostrarían todas ellas, con lo cual siempre podemos devolver a la máquina a un estado previo a cualquier ejecución de JASS. Esta característica es bastante importante, ya que volvemos a insistir en que, en función del driver al que invoquemos, el sistema puede quedar incluso demasiado `securizado': por poner un ejemplo, la ejecución de secure.driver eliminaría cualquier acceso estándar al sistema (telnet, FTP, rsh...), con lo que sería necesario de disponer de una consola o de SSH para acceder remotamente a la máquina tras la ejecución de JASS.

Como hemos dicho antes, también es posible integrar JASS en la propia instalación del sistema operativo Solaris; para ello hemos de basarnos en la arquitectura JumpStart de Sun Microsystems ([Noo01]), copiando el paquete de software en el directorio raíz del servidor JumpStart y siguiendo unos pasos simples explicados con detalle en [NB01c]. Con unas sencillas modificaciones de algunos ficheros, conseguiremos una instalación por defecto segura, lo que evitará que el administrador de los sistemas tenga que ir máquina a máquina para realizar el típico hardening postinstalación (cerrar puertos, configurar accesos...).

La que acabamos de ver es una herramienta muy recomendable en cualquier sistema Solaris, ya que consigue automatizar muchas tareas que de otra forma el administrador debería realizar manualmente. Su potencia, unida a su sencillez de uso (y `desuso'), la convierten en algo si no imprescindible sí muy importante en nuestros sistemas; incomprensiblemente no se utiliza de forma extendida, aunque es previsible que con sus nuevas versiones (actualmente está disponible la 0.3) esto comience a cambiar pronto. Podemos obtener información adicional de esta herramienta en los BluePrints publicados por Sun Microsystems y que se distribuyen, aparte de vía web, en el directorio Documentation/ de la misma: [NB01b], [NB01a], [NB01c], [NB01d]...

sfpDB

La base de datos sfpDB (Solaris Fingerprint Database) es un servicio gratuito de Sun Microsystems que permite a los usuarios verificar la integridad de los archivos distribuidos con Solaris, tanto con la base del operativo como con productos concretos de Sun o parches; esto permite por una parte verificar que lo que acabamos de instalar en una máquina es realmente una distribución de Solaris oficial de Sun, y por otra detectar si un pirata ha logrado modificar alguno de los ficheros del sistema (como /bin/login), típicamente para situar troyanos o puertas traseras en una máquina atacada: se trata de un sistema de detección de intrusos basado en host, como veremos a la hora de hablar de IDSes.

Para lograr su objetivo, desde http://sunsolve.sun.com/ se puede comparar la función resumen MD5 de determinados archivos que tenemos en nuestra máquina con el resumen almacenado por Sun Microsystems. Para ello en primer lugar hemos de generar el resumen de los ficheros que deseemos verificar, mediante la orden md5 (instalada como parte del paquete SUNWkeymg o de forma independiente):
anita:/# pkgchk -l -p /usr/sbin/md5
Pathname: /usr/sbin/md5
Type: regular file
Expected mode: 0755
Expected owner: root
Expected group: sys
Expected file size (bytes): 24384
Expected sum(1) of contents: 12899
Expected last modification: Nov 11 20:19:48 1999
Referenced by the following packages:
        SUNWkeymg      
Current status: installed

anita:/# md5 /bin/su
MD5 (/bin/su) = 79982b7b2c7576113fa5dfe316fdbeae
anita:/#
Una vez hecho esto, introduciremos este resumen en un formulario web, y se nos proporcionará información sobre el mismo; si no hay problemas, el resultado será similar al siguiente:
Results of Last Search

79982b7b2c7576113fa5dfe316fdbeae - (/bin/su) - 1 match(es) 
           canonical-path: /usr/bin/su 
           package: SUNWcsu 
           version: 11.8.0,REV=2000.01.08.18.17 
           architecture: i386 
           source: Solaris 8/Intel
Mientras que si el resumen que hemos obtenido no se corresponde con el de ningún fichero de las diferentes versiones de Solaris u otro software de Sun, se nos dará el error Not found in this database. Este error de entrada implica que en nuestra máquina tenemos algo cuanto menos `extraño', ya que es extremadamente raro que un archivo del sistema como /bin/su, /bin/ps o /bin/ls sea modificado en un sistema. Si fuera este el caso, y como administradores desconocemos a qué puede ser debida esa modificación, con una alta probabilidad nos han instalado un rootkit, un conjunto de herramientas utilizadas por los piratas principalmente para ocultar su presencia y garantizarse el acceso en una máquina donde han conseguido privilegios de root; un rootkit instala versiones troyanizadas de casi todos los programas que pueden ayudar en la detección del pirata, como `ls' o `netstat', lo que provoca que si no ponemos un mínimo de interés sea muy difícil detectar la intrusión.

Existen además ciertas extensiones a la sfpDB cuyo objetivo es facilitar el uso de la base de datos [DNO01]; una de ellas es sfpC (Solaris Fingerprint Database Companion), que automatiza el proceso de generar y verificar los resúmenes MD5 de un número considerable de archivos mediante un script en PERL (recordemos que un simple interfaz web que invoca a un CGI no es apropiado para todas las aplicaciones, por lo que Sun Microsystems está estudiando la posibilidad de publicar de otra forma el contenido completo de la base de datos). Para conseguirlo, sfpC acepta como entrada un fichero que contiene una lista de resúmenes, dividiéndola en diferentes partes para enviarlas por separado a la sfpDB, y generando resultados globales en función de cada uno de los resultados individuales obtenidos.

Otra de estas herramientas es sfpS (Solaris Fingerprint Database Sidekick), un sencillo shellscript que funciona en conjunción con la propia sfpDB y con sfpC y cuyo objetivo es simplificar la detección de troyanos; para ello, almacena una lista de ejecutables comúnmente troyanizados por cualquier rootkit, y es el contenido de dicha lista el que se compara contra la base de datos mediante el script en PERL de sfpC.

Evidentemente esta base de datos de Sun Microsystems y sus utilidades asociadas (que podemos descargar libremente desde las páginas web de esta compañía), como cualquier otro producto a la hora de hablar de seguridad, no es la panacea, sino sólo una herramienta más que nos puede ayudar a detectar intrusiones en una máquina. También tiene puntos débiles, ya que por ejemplo un atacante que sea capaz de modificar ciertas utilidades del sistema podrá hacer lo mismo con el ejecutable `md5', de forma que simule generar resultados similares a los originales cuando verificamos la integridad de utilidades troyanizadas; contra esto, una solución efectiva puede ser utilizar un `md5' estático y guardado en una unidad de sólo lectura, y por supuesto generado a partir de fuentes confiables. Sin ser una herramienta excluyente, mediantes consultas automatizadas a la base de datos proporcionada por Sun Microsystems tenemos la posibilidad de descubrir intrusiones graves en nuestros sistemas en un tiempo mínimo, y de forma sencilla.

El subsistema de red

Antes de hablar de la seguridad del subsistema de red en Solaris quizás sea necesario introducir el comando `ndd'; esta orden permite tanto consultar (mediante el símbolo `?') como modificar la configuración de ciertos drivers del sistema, en concreto los que soportan la pila de protocolos TCP/IP:
anita:/# ndd -get /dev/tcp tcp_strong_iss 
1
anita:/# ndd -set /dev/tcp tcp_strong_iss 2
anita:/# ndd -get /dev/tcp tcp_strong_iss 
2
anita:/#
Si quisiéramos comprobar qué parámetros ofrece un determinado driver (por ejemplo /dev/tcp), lo haríamos con la orden siguiente:
anita:/# ndd -get /dev/tcp \?
El uso del carácter `' no es más que un escape del shell para el símbolo `?'. es importante conocer qué parámetros ofrece cada driver de nuestro sistema antes de planificar una modificación de sus valores, especialmente en Solaris 8, versión en la que ha cambiado ligeramente el nombre de alguno de ellos y además se han incluido algunos nuevos relativos a IPv6 (que no mostramos aquí).

Los primeros parámetros que nos interesará modificar para incrementar la seguridad de nuestro sistema pueden ser los relacionados con el forwarding, el reenvío de paquetes de cierto tipo que llegan a la máquina. En primer lugar, es importante evitar que nuestro equipo se convierta en un enrutador; aunque en algunas versiones de Solaris es suficiente con crear el fichero /etc/notrouter, lo más recomendable es deshabilitar por completo el IP Forwarding a nivel del subsistema de red, lo cual se consigue mediante la siguiente orden:
anita:/# ndd -set /dev/ip ip_forwarding 0
anita:/#
También es importante evitar que en hosts con múltiples tarjetas se reenvíen tramas entre ellas; con esto conseguimos hacer más difícil un ataque de IP Spoofing, ya que el sistema conoce en todo momento a través de que interfaz le llega un paquete, y si lo hace por una que no le corresponde, la trama se ignora. Para lograr este objetivo podemos modificar el valor del parámetro ip_strict_dst_multihoming:
anita:/# ndd -set /dev/ip ip_strict_dst_multihoming 1
anita:/#
Los últimos parámetros relacionados con el reenvío de tramas en la máquina afectan a los broadcasts y a los paquetes source routed (aquellos que contienen en su interior el camino a seguir, total o parcialmente, hasta su destino). Por supuesto, no es recomendable el forwarding de broadcasts dirigidos desde una estación fuera de una red hacia todos los equipos de esa red, algo que una máquina Solaris con el IP Forwarding activado hace por defecto; de la misma forma, no se deben reenviar tramas que marquen el camino a su destino, ya que en la mayor parte de redes no existen motivos válidos para la emisión de este tipo de paquetes, y muchos de ellos son denotativos de actividades sospechosas. Podemos evitar ambos reenvíos mediante las siguientes órdenes respectivamente:
anita:/# ndd -set /dev/ip ip_forward_directed_broadcasts 0
anita:/# ndd -set /dev/ip ip_forward_src_routed 0
anita:/#
Otros parámetros a tener en cuenta para incrementar nuestro nivel de seguridad son algunos relativos a ataques contra el protocolo ARP; para prevenir el ARP Spoofing es recomendable reducir el timeout que Solaris presenta por defecto y que marca la frecuencia de borrado de las entradas de la tabla ARP y de la tabla de rutado, fijando ambas en un minuto. Esto lo conseguimos mediante las órdenes siguientes (en las que especificamos el tiempo en milisegundos):
anita:/# ndd -get /dev/arp arp_cleanup_interval 60000
anita:/# ndd -get /dev/ip ip_ire_flush_interval 60000
anita:/#
Dentro del protocolo ICMP también existen parámetros del subsistema de red interesantes para nuestra seguridad; un grupo de ellos son los relacionados con los diferentes tipos de tramas ICMP que pueden implicar un broadcast: ICMP/SMALL>_ECHO/SMALL>_REQUEST, ICMP/SMALL>_TIMESTAMP e ICMP/SMALL>_ADDRESS/SMALL>_MASK. Todos ellos pueden ser utilizados para causar negaciones de servicio, por lo que una buena idea en la mayor parte de situaciones es simplemente ignorarlos; incluso en el segundo caso (ICMP/SMALL>_TIMESTAMP) Solaris ofrece la posibilidad de ignorar las tramas de este tipo aunque no sean broadcasts, simplemente paquetes dirigidos a un host deterinado, ya que pueden proporcionar información del sistema útil de cara a un ataque. Para conseguir ignorar todas estas tramas podemos ejecutar estas órdenes:
anita:/# ndd -get /dev/ip ip_respond_to_echo_broadcast 0
anita:/# ndd -get /dev/ip ip_respond_to_timestamp_broadcast 0
anita:/# ndd -get /dev/ip ip_respond_to_address_mask_broadcast 0
anita:/# ndd -get /dev/ip ip_respond_to_timestamp 0
anita:/#
Todavía dentro del protocolo ICMP, otro tipo de mensajes que nos pueden causar problemas son los ICMP/SMALL>_REDIRECT; es conveniente deshabilitar tanto su emisión (sólo un router tiene la necesidad de enviar este tipo de tramas) como su recepción, ya que pueden ser utilizados para generar rutas falsas en el subsistema de red de una máquina. Para lograr ambas cosas podemos ejecutar las siguientes órdenes:
anita:/# ndd -get /dev/ip ip_ignore_redirects 1
anita:/# ndd -get /dev/ip ip_send_redirects 0
anita:/#
La generación de los números iniciales de secuencia TCP es otro parámetro que seguramente nos interesará modificar en un sistema Solaris; por defecto esta generación se basa en incrementos pseudoaleatorios, lo que puede facilitar ataques de IP Spoofing contra el sistema. Podemos aumentar nuestro nivel de seguridad utilizando un esquema de generación más robusto, basado en [Bel96], simplemente modificando el fichero /etc/default/inetinit para asignarle al parámetro TCP/SMALL>_STRONG/SMALL>_ISS un valor de 2:
anita:/# cat /etc/default/inetinit
# @(#)inetinit.dfl 1.2 97/05/08
#
# TCP_STRONG_ISS sets the TCP initial sequence number generation parameters.
# Set TCP_STRONG_ISS to be:
#     0 = Old-fashioned sequential initial sequence number generation.
#     1 = Improved sequential generation, with random variance in increment.
#     2 = RFC 1948 sequence number generation, unique-per-connection-ID.
#
TCP_STRONG_ISS=2
anita:/#
Al contrario de lo que sucede con ndd, cuyos cambios se pierden al reiniciar el sistema y hay que planificar en el arranque si necesitamos hacerlos permanentes, la modificación del fichero anterior no tendrá efecto hasta que el sistema vuelva a arrancar; si no queremos detener la máquina, podemos conseguir lo mismo mediante la orden `ndd' sobre el núcleo en ejecución:
anita:/# ndd -set /dev/tcp tcp_strong_iss 2
anita:/#
También mediante ndd podemos modificar en Solaris las restricciones relativas a los puertos reservados (aquellos que sólo el root puede utilizar, por defecto los que están por debajo del 1024). En primer lugar, podemos definir el mínimo puerto no reservado, para que las conexiones al sistema o los procesos de usuario puedan utilizar sólo los que están por encima de él; si por ejemplo queremos que el rango de puertos reservados comprenda a todos los que están por debajo del 5000 podemos ejecutar la orden siguiente:
anita:/# ndd -set /dev/tcp tcp_smallest_nonpriv_port 5000
anita:/#
Además, desde su versión 2.6 Solaris permite marcar puertos individuales como reservados, tanto UDP como TCP, y también eliminar esta restricción de puertos que previamente hayamos reservado; por defecto, aparte de los primeros 1024 puertos, Solaris define como reservados - en TCP y UDP - los puertos 2049 (nfsd) y 4045 (lockd). En el siguiente ejemplo se muestra cómo consultar los puertos marcados de esta forma, cómo añadir un alguno a la lista, y cómo eliminarlo de la misma; aunque el ejemplo se aplica a TCP, el caso de UDP es completamente análogo pero sustituyendo el nombre del dispositivo contra el que ejecutamos la orden (que sería /dev/udp) y la cadena `tcp' del nombre de cada parámetro por `udp':
anita:/# ndd /dev/tcp tcp_extra_priv_ports
2049
4045
anita:/# ndd -set /dev/tcp tcp_extra_priv_ports_add 5000
anita:/# ndd /dev/tcp tcp_extra_priv_ports
2049
4045
5000
anita:/# ndd -set /dev/tcp tcp_extra_priv_ports_del 5000
anita:/# ndd /dev/tcp tcp_extra_priv_ports
2049
4045
anita:/#
Antes de finalizar este punto es importante insistir en que los cambios producidos por `ndd' sólo se mantienen hasta el siguiente reinicio del sistema; de esta forma, las modificaciones que hemos visto aquí se mantendrán sólo mientras la máquina no se pare, pero si esto sucede en el arranque todos los parámetros del subsistema de red tomarán sus valores por defecto. Por tanto, lo más probable es que nos interese planificar en el inicio del sistema las modificaciones estudiadas en este punto para que se ejecuten de forma automática; para conseguirlo, no tenemos más que crear el script correspondiente y ubicarlo en el directorio /etc/rc2.d/ con un nombre que comience por `S', con lo que hacemos que se ejecute siempre que la máquina entre en un runlevel 2:
anita:~# cat /etc/init.d/nddconf
#!/sbin/sh
#
# Configuracion segura del subsistema de red de Solaris
#
ndd -set /dev/ip ip_forwarding 0
ndd -set /dev/ip ip_strict_dst_multihoming 1
ndd -set /dev/ip ip_forward_directed_broadcasts 0
ndd -set /dev/ip ip_forward_src_routed 0
ndd -get /dev/arp arp_cleanup_interval 60000
ndd -get /dev/ip ip_ire_flush_interval 60000
ndd -get /dev/ip ip_respond_to_echo_broadcast 0
ndd -get /dev/ip ip_respond_to_timestamp_broadcast 0
ndd -get /dev/ip ip_respond_to_address_mask_broadcast 0
ndd -get /dev/ip ip_respond_to_timestamp 0
ndd -get /dev/ip ip_ignore_redirects 1
ndd -get /dev/ip ip_send_redirects 0
ndd -set /dev/tcp tcp_strong_iss 2
#
anita:~# chmod 744 /etc/init.d/nddconf
anita:~# chown root:sys /etc/init.d/nddconf
anita:~# ln /etc/init.d/nddconf /etc/rc2.d/S70nddconf
anita:~#
Si queremos conocer mejor la configuración de seguridad del subsistema de red de Solaris una excelente obra que no debería faltar en la mesa de ningún administrador de sistemas es [NW99]; todo este punto está basado ampliamente en ella. Incluye, además de explicaciones claras sobre el porqué del valor de cada parámetro para prevenir posibles ataques, un shellscript para planificar en el inicio del sistema, muchísimo más completo que el presentado aquí, y aplicable a varias versiones de Solaris (incluyendo la 8); en sistemas en los que la seguridad es un factor a tener en cuenta (>todos?) es casi obligatorio utilizar esta planificación.

Parámetros del núcleo

En el archivo /etc/system el administrador de un equipo Solaris puede definir variables para el núcleo del sistema operativo, como el número máximo de ficheros abiertos por un proceso o el uso de memoria compartida, semáforos y mensajes para intercomunicación entre procesos. En este apartado vamos a comentar algunos de estos parámetros que pueden afectar a la seguridad; hablaremos especialmente de aquellos que pueden y deben ser limitados para evitar diversos tipos de negaciones de servicio, ataques que recordemos afectan a la disponibilidad de nuestros recursos.

Si deseamos ver el valor de alguno de los parámetros en el kernel que se está ejecutando en este momento, lo podemos hacer con la orden adb (nótese que no ofrece ningún prompt, hemos de escribir directamente el parámetro a visualizar, con un `/D' al final para que nos muestre el valor en decimal):
anita:~# adb -k /dev/ksyms /dev/mem
physmem 38da
maxusers/D
maxusers:
maxusers:       56
maxuprc/D
maxuprc:
maxuprc:        901
^d
anita:~#
Una negación de servicio muy típica en Unix es el consumo excesivo de recursos por parte de usuarios que lanzan - voluntaria o involuntariamente - demasiados procesos; esto es especialmente común en sistemas de I+D, donde muchos usuarios se dedican a programar, y un pequeño error en el código (a veces denominado `runaway fork') puede hacer que el sistema se vea parado por un exceso de procesos activos en la tabla. La gravedad del problema aumenta si pensamos que también es muy habitual que los usuarios lancen simulaciones que tardan en ejecutarse varios días (o varias semanas), de forma que una parada inesperada puede causar la pérdida de muchas horas de trabajo. Por tanto, parece obvio que es recomendable limitar el número de procesos simultáneos por usuario; en Solaris este número está ilimitado por defecto, por lo que si deseamos asignar un valor máximo hemos de editar el fichero /etc/system e incluir una línea como la siguiente:
set maxuprc=60
De esta forma limitamos el número de procesos por usuario a 60 (un número aceptable en la mayoría de sistemas10.7), consiguiendo así que un error en un programa no sea capaz de detener la máquina.

Un parámetro del sistema operativo especialmente importante, y que quizás nos interese modificar (sobre todo en máquinas con pocos recursos) es maxusers. Al contrario de lo que mucha gente cree, maxusers no hace referencia al número máximo de usuarios que pueden conectar simultáneamente al sistema, sino que es un valor que escala a otros parámetros del núcleo (como max_nproc, número máximo de procesos en la tabla) o maxuprc. Para modificarlo, podemos incluir en /etc/system una línea con el valor deseado, generalmente el tamaño en MB de la memoria física de nuestra máquina ([Dik99]):
set maxusers=128
También puede ser conveniente limitar parámetros del sistema operativo relativos al sistema de ficheros, ya que también se pueden producir negaciones de servicio relacionadas con ellos. Por ejemplo, es interesante poder limitar el número máximo de ficheros abiertos mediante los parámetros rlim_fd_max (límite hard) y rlim_fd_cur (límite soft) o evitar que los usuarios puedan utilizar chown() en sus ficheros, especificando un valor 1 para la variable rstchown (este es el comportamiento por defecto; si no lo seguimos, aparte de comprometer la seguridad los usuarios sin privilegios podrían ignorar el sistema de quotas).

Dejando ya de lado los límites que se pueden imponer a los recursos consumidos por los usuarios del sistema, existe otra serie de parámetros del núcleo interesantes para aumentar la seguridad de un sistema Solaris. Por ejemplo, en algunas arquitecturas SPARC (concretamente en sun4u, sun4d y sun4m) es posible, desde Solaris 2.6, establecer una protección hardware para prevenir ataques de buffer overflow. Esta protección consiste en impedir que los programas puedan ejecutar código en su pila, recibiendo la señal SIGSEGV si tratan de hacerlo: para ello, en /etc/system hemos de incluir una línea como
set noexec_user_stack=1
Y si además queremos monitorizar los intentos de ataque de este tipo (como mensajes del núcleo de Solaris, con priority `kern' y nivel `notice', por defecto en /var/adm/messages), podemos incluir en el archivo la línea
set noexec_user_stack_log=1
Si administramos un servidor NFS y deseamos que ignore las peticiones de clientes que no provengan de puertos privilegiados (es decir, que no hayan sido solicitadas por un usuario privilegiado de la máquina cliente) podemos definir la variable NFS/SMALL>_PORTMON en /etc/system; si usamos versiones de Solaris anteriores a la 2.5, debemos incluir una línea como
set nfs:nfs_portmon = 1
mientras que en Solaris 2.5 y posteriores utilizaremos
set nfssrv:nfs_portmon = 1
Por último, como ya comentamos en el punto dedicado a la seguridad EEPROM, podemos deshabilitar el acceso que se consigue a la misma al pulsar la combinación de teclas `Stop-A' en un teclado Sun; para ello es necesario añadir en el fichero /etc/system una entrada como
set abort_enable=0
Antes de finalizar este punto, es necesario tener en cuenta que los cambios que se realicen en /etc/system no tendrán efecto hasta que la máquina se reinicie, y que un pequeño error en los contenidos de este archivo puede provocar que un sistema no arranque, por lo que es siempre recomendable guardar una copia antes de realizar cualquier modificación del fichero.
next up previous contents
Siguiente: Linux Subir: Algunos sistemas Unix Anterior: Algunos sistemas Unix   Índice General
2002-07-15