next up previous contents
Siguiente: FTP invitado Subir: El servicio FTP Anterior: El servicio FTP   Índice General

FTP anónimo

Los problemas relacionados con la seguridad del servicio FTP son especialmente preocupantes cuando se trata de configurar un servidor de FTP anónimo; muchos de estas máquinas situadas en universidades españolas se convierten en servidores de imágenes pornográficas o de warez (copias ilegales de programas comerciales). Conseguir un servidor de FTP anónimo seguro puede llegar a ser una tarea complicada: incluso en las páginas de ayuda de algunas variantes de Unix (como Solaris) se trata de facilitar el proceso para el administrador mediante un shellscript que - por defecto - presenta graves problemas de seguridad, ya que deja una copia del fichero de claves del sistema como un archivo de acceso público y anónimo.

Para configurar correctamente un servidor de este tipo necesitamos en primer lugar crear al usuario ftp en /etc/passwd y /etc/shadow, así como su directorio de conexión (algunos Unices, como Linux, ya incorporan esto al instalar el sistema). Este directorio ha de pertenecer a root (ningún fichero o subdirectorio ha de pertenecer nunca a ftp) y al grupo al que pertenece ftp: con esto conseguimos que los permisos de propietario sean para el administrador y los de grupo para los usuarios anónimos; estos permisos serán 555.

Dentro del $HOME de ftp hemos de crear el árbol de directorios mínimo para poder trabajar correctamente; esto es debido a la llamada a chroot() que se utiliza en los accesos anónimos, que permite a esos usuarios ver el directorio raíz de su conexión en el directorio real ~ftp/. Al menos dos directorios son necesarios: etc/ y bin/, ambos propiedad de root y con modo 111. En el primero de ellos hemos de crear un fichero passwd y otro group, utilizados no con propósitos de autenticación sino para visualizar el propietario y grupo de cada fichero en el entorno sobre el que se ha aplicado chroot() al ejecutar ls: por tanto, no hace falta ninguna contraseña en ese fichero passwd, y sólo ha de contener entradas para los usuarios que posean ficheros bajo la jerarquía de ftp, como root; de la misma forma, el fichero group sólo ha de contener las entradas correspondientes a grupos que posean ficheros en dicha jerarquía:
anita:~# cat /export/home/ftp/etc/passwd
root:*:0:1:El Spiritu Santo:/:/sbin/sh
anita:~# cat /export/home/ftp/etc/group
root::0:
other::1:
daemon::2:
ftp::30000:
anita:~#
Como vemos, el usuario ftp tiene un shell denominado /bin/false; aunque aquí no tiene ningún efecto, en el archivo de contraseñas real de la máquina esto es útil para prevenir que dicho usuario pueda conectar mediante TELNET o similar.

Por su parte, en el otro directorio que hemos creado (bin/) hemos de almacenar una copia del programa ls, de forma que los usuarios puedan listar los contenidos de los directorios cuyos permisos lo permitan; si utilizamos una versión estática del programa, como hace por ejemplo Linux, no hemos de configurar nada para que la aplicación funcione, pero si en cambio utilizamos un ls dinámico (como SunOS o Solaris) hemos de crear el directorio lib/ dentro de ~ftp/ y copiar en él las librerías necesarias para que el programa funcione (podemos ver de cuáles se trata con ldd).

Con estos pasos ya tenemos configurada la base de nuestro servidor de FTP anónimo; no obstante, es habitual crear dos directorios más, uno denominado pub/ y otro incoming/, dentro de la misma jerarquía que los anteriores (esto es, en el $HOME del usuario ftp). El primero suele contener directorios con todos los ficheros que deseemos ofrecer a los usuarios anónimos; su modo ha de ser 555, o 2555 en los sistemas que utilicen el bit setgid en un directorio para que sus subdirectorios y ficheros hereden el grupo del propietario. El directorio incoming es justo lo contrario: sirve para que esos usuarios anónimos puedan enviar archivos a nuestra máquina. Y es aquí donde suelen comenzar muchos problemas: al permitir el upload de software, es posible que algunos piratas utilicen nuestra máquina para crear servidores warez, subiendo programas comerciales a este directorio y luego indicando su localización exacta a otras personas, para que los puedan descargar. Por tanto, los permisos de incoming son vitales para nuestra seguridad (incluso si no deseamos que los usuarios anónimos nos envíen ficheros podemos borrar este directorio): esos permisos han de ser 1733, y el propietario del directorio es el root. >Para qué ponemos el bit de permanencia? Muy sencillo: para que los usuarios no puedan sobreescribir o borrar ficheros existentes; aunque la mayoría de servidores FTP no permiten a los usuarios anónimos sobreescribir ficheros, si no pusiéramos este modo un usuario normal del sistema sí que podría hacerlo.

El siguiente shellscript puede utilizarse para configurar cómodamente un entorno restringido destinado a los usuarios de FTP anónimo siguiendo las directrices que acabamos de comentar; funciona correctamente (en teoría) sobre Solaris, Linux y AIX15.3. Al igual que sucede con muchas tareas automatizadas, conviene repasar manualmente la estructura de directorios y ficheros creados para comprobar que todo es como esperábamos:
anita:~# cat /usr/local/sbin/creaentorno
#!/bin/sh
# Script para crear un entorno chroot()eado.
# Funciona OK en Linux, Solaris y AIX.
# 

# Esta variable es una lista con los programas que necesitamos en el 
# entorno restringido. 
PROGS="/bin/ls"
# Imprime modo de uso
if (test $# -lt 1); then
        echo "Usage: $0 /path/to/chroot-environment"
        exit
fi
# Detectamos clon de Unix
OS=`uname -s`
# Creamos estructura de directorios
echo "Creando estructura de directorios para $OS"
if [ ! -d $1 ]; then
        mkdir -p $1
fi
chown root $1
for i in bin etc; do
        if [ ! -d $1/$i ] ; then
               mkdir -p $1/$i
        fi
        chown root $1/$i
done
# En funcion del Unix, la estructura sera una u otra...
if [ $OS = "Linux" ]; then
        if [ ! -d $1/lib ]; then
               mkdir -p $1/lib
        fi
        chown root $1/lib
fi
if ( test $OS = "SunOS" || test $OS = "AIX" ); then
        if [ ! -d $1/usr/lib ]; then
                mkdir -p $1/usr/lib
        fi
        chown root $1/usr/lib
        cd $1
        ln -s ./usr/lib $1/lib
fi
# Instalamos programas y las librerias que necesitan
echo "Instalando programas y librerias..."
for i in $PROGS; do
        if [ ! -f $1/$i ]; then
                cp $i $1/bin
        fi
        chmod 111 $1/bin
        chown root $1/bin
        if [ $OS = "AIX" ]; then 
        for j in `ldd $i|awk -F"(" '{if(NR!=1) print $1}'`; do
                if [ ! -f $1/$j ]; then
                        cp $j $1/lib
                fi
                chown root $1/$j
        done
        else 
                for j in `ldd $i|awk '{print $3}'`; do
                        if [ ! -f $1/$j ]; then
                                cp $j $1/lib
                        fi
                        chown root $1/$j
                done
        fi
done
# Estos ficheros quizas sea necesario retocarlos a mano, en funcion del tipo
# de entorno restringido que fabriquemos.
# Generamos PASSWD
echo "Generando /etc/passwd..."
awk -F: '$1=="root" {print $1":*:"$3":"$4":"$5":"$6":"$7}' /etc/passwd >\
$1/etc/passwd
awk -F: '$1=="bin" {print $1":*:"$3":"$4":"$5":"$6":"$7}' /etc/passwd>>\
$1/etc/passwd
awk -F: '$1=="daemon" {print $1":*:"$3":"$4":"$5":"$6":"$7}' /etc/passwd>>\
$1/etc/passwd
chmod 444 $1/etc/passwd
chown root $1/etc/passwd
# Quizas hay que anyadir otros grupos que nos interesen
# Generamos GROUP con algunas entradas
echo "Generando /etc/group..."
awk -F: '$1=="root" {print $1":*:"$3":"$4}' /etc/group>$1/etc/group
awk -F: '$1=="bin" {print $1":*:"$3":"}' /etc/group>>$1/etc/group
awk -F: '$1=="daemon" {print $1":*:"$3":"}' /etc/group>>$1/etc/group
chmod 444 $1/etc/group
chown root $1/etc/group
# Generamos pub/ e incoming/
echo "Generando pub/ e incoming/..."
if [ ! -d $1/pub ]; then
        mkdir -p $1/pub
fi
chmod 2555 $1/pub
chown root $1/pub
if [ ! -d $1/incoming ]; then
        mkdir -p $1/incoming
fi
chmod 1733 $1/incoming
chown root $1/incoming
# Si estamos en Solaris, aun no hemos acabado
if [ $OS = "SunOS" ]; then
        # Mas librerias
        echo "$OS: Instalando librerias..."
        for i in ld.so.1 libc.so.1 libdl.so.1 libmp.so.2 libnsl.so.1 \
        libsocket.so.1 nss_compat.so.1 nss_dns.so.1 nss_files.so.1 \
        nss_nis.so.1 nss_nisplus.so.1 nss_xfn.so.1 straddr.so \
        straddr.so.2; do
               cp /usr/lib/$i $1/usr/lib
        done
        if [ ! -d $1/dev ]; then
                mkdir -p $1/dev
        fi
        chown root $1/dev
        # Generamos dispositivos
        echo "$OS: Generando dispositivos..."
        for i in /dev/zero /dev/tcp /dev/udp /dev/ticotsord; do
                MAJOR=`ls -lL $i|awk '{print $5}'|sed s/","//g`
                MINOR=`ls -lL $i|awk '{print $6}'`
                TYPE=`ls -lL $i|cut -c1-1`
                /usr/sbin/mknod $1/$i $TYPE $MAJOR $MINOR
        done
        chmod 666 $1/dev/*
fi
echo "FIN"
# FIN de Solaris
anita:~#
Algunos problemas relacionados con incoming/ provienen de los permisos con que se crean sus ficheros y subdirectorios: aunque los usuarios anónimos no puedan leer el directorio, con algunos servidores ftpd sí que es posible que puedan leer los ficheros contenidos en él (y sus subdirectorios), con lo que sigue siendo posible acceder a los archivos conociendo su nombre exacto; para evitar este problema, muchos administradores planifican un sencillo shellscript para que cada cierto tiempo mueva los contenidos de incoming a otro lugar, fuera del alcance de los usuarios anónimos (por ejemplo, un subdirectorio con modo 000 de /tmp/). Ciertos servidores, como WU-ftpd, tienen un fichero de configuración (/etc/ftpaccess) donde indicar - entre otras cosas - los modos con que se van a crear entradas en incoming/.

Un ataque típico a los servidores de FTP es una negación de servicio llenando todo el espacio disponible para el upload de ficheros; para minimizar las consecuencias de este ataque, es conveniente situar el directorio ~ftp/ en una partición separada del resto del sistema de ficheros, donde sólo se encuentre dicho directorio; algunos demonios permiten directamente limitar la cantidad de ficheros subidos al servidor en cada sesión.

Otra negación de servicio muy habitual contra los servidores de FTP anónimo es obligar a las máquinas a consumir una excesiva cantidad de CPU, ralentizando el sistema hasta que la calidad de servicio es muy baja; esto se produce en servidores que permiten descargar directorios completos como un único archivo, empaquetados con tar y/o comprimidos con gzip. Veamos un ejemplo extraído de una sesión de FTP anónimo:
ftp> pwd
257 "/pub/utils" is current directory.
ftp> ls
200 PORT command successful.
150 Opening ASCII mode data connection for /bin/ls.
total 377
drwxr-xr-x   2 root     root         1024 Sep 18 22:28 .
drwxrwxr-x   3 root     wheel        1024 Sep 18 22:28 ..
-rw-r--r--   1 root     root       163519 Sep 18 22:28 transfig-3.1.2.tar.gz
-rw-r--r--   1 root     root       217850 Sep 18 22:27 tth_C.tgz
226 Transfer complete.
ftp>  cd ..
250 CWD command successful.
ftp> pwd
257 "/pub" is current directory.
ftp> ls
200 PORT command successful.
150 Opening ASCII mode data connection for /bin/ls.
total 3
drwxrwxr-x   3 root     wheel        1024 Sep 18 22:28 .
drwxrwxr-x   8 root     wheel        1024 Aug  1  1994 ..
drwxr-xr-x   2 root     root         1024 Sep 18 22:28 utils
226 Transfer complete.
ftp> get utils.tar.gz
local: utils.tar.gz remote: utils.tar.gz
200 PORT command successful.
150 Opening BINARY mode data connection for /bin/tar.
226 Transfer complete.
381369 bytes received in 1.07 secs (3.5e+02 Kbytes/sec)
ftp>
Como podemos ver, acabamos de descargar un directorio completo empaquetado y comprimido sin más que añadir al nombre de dicho directorio la extensión .tar.gz (o simplemente .tar si no hubiéramos querido comprimirlo). Evidentemente esto resulta muy útil en determinadas situaciones pero, >nos hemos parado a pensar que sucedería si alguien intentara descargar el directorio /pub.tar.gz en un servidor con unos cuantos Gigabytes de ficheros? La carga del sistema crecería muchísimo, ya que estamos empaquetando y comprimiendo un archivo de grandes dimensiones; si ahora extendemos esto a varios usuarios que ejecutan la misma orden simultáneamente podemos hacernos una idea de la sobrecarga introducida en la máquina: una razón más que suficiente para tener cuidado con los directorios que permitimos descargar de esta forma...

Por último, es una buena idea mostrar un mensaje cuando los usuarios anónimos conectan a nuestra máquina donde se indiquen claramente los fines del sistema y la atención a su uso indebido; este mensaje puede sernos útil tanto con fines jurídicos (así el atacante no podrá argumentar que desconocía la finalidad del sistema) como con fines disuasorios: si el pirata se da cuenta de que nos preocupamos por la seguridad de nuestro servidor, es posible que lo abandone y busque otro menos protegido. Por ejemplo, si utilizamos WU-ftpd, en ~ftp/welcome.msg podemos escribir el mensaje mostrado al conectar al sistema, y en diferentes ficheros .message el mensaje que se vuelca a acceder a un directorio (estos nombres son configurables en /etc/ftpaccess). Un ejemplo del mensaje de entrada puede ser el siguiente:
anita:~# cat /export/home/ftp/welcome.msg

                  * * *         ANITA        * * *
           -----------  Bienvenid@s a ANITA  ------------
  Esta maquina es propiedad de la Universidad Politecnica de Valencia y
  sus fines son exclusivamente academicos y de investigacion. Cualquier
  otro uso sera perseguido y castigado con el maximo rigor.
  Cualquier actividad realizada en, desde o hacia este sistema esta
  sujeta a monitorizacion sin previo aviso.

anita:~#

next up previous contents
Siguiente: FTP invitado Subir: El servicio FTP Anterior: El servicio FTP   Índice General
2003-08-08