Esconder la version de nginx y PHP

En mi caso, me he vuelto un tanto fan de usar LNMP como plataforma Web.

Y también como fan de la seguridad y dado el post anterior, aquí procedo a explicar cómo esconder la versió de nginx así como la existencia de PHP en un servidor web.

Para el primer caso, cuando intentamos entrar a un directorio inexistente, una página no permitida o un error de servidor, tenemos los típicos errores 404, 403 o 500 respectívamente:

Como vemos, se muestra la versión del servidor, lo cual puede ser útil para algún atacante, pues puede encontrar vulnerabilidades específicas para la versión en cuestión.

Para solucionar esto, debemos mirar en el archivo de configuración de nginx. Típicamente /etc/nginx/ngiinx.conf o /etc/nginx.conf.

Debemos agregar la siguiente linea en la seccion http:

server_tokens off;

Reiniciamos/recargamos el servidor web, y obtenemos lo siguiente:

 

 

Para el caso de PHP, existen por defecto algunos huevos de pascua, que propiamente no representan un compromiso de seguridad. Pero, dado que existen entornos empresariales muy estrictos en que es preferible mantener en secreto las plataformas que se utilizan, es preferible esconderlos.

Si nos vamos a cualquier servidor web con PHP, obtenemos esto colocando el parámetro adecuado en cualquier script:

  • http://www.example.com/algunscript.php?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000

Se muestran los créditos de PHP:

  • http://www.example.com/algunscript.php?=?=PHPE9568F36-D428-11d2-A769-00AA001ACF42

Se muestra una imagen que depende de la versión de PHP, por ejemplo alguna de estas (para PHP 5.3 y 5.2):

  • http://www.example.com/algunscript.php?=?=PHPE9568F35-D428-11d2-A769-00AA001ACF42

El logo de Zend Engine:

  • http://www.example.com/algunscript.php?=?=PHPE9568F34-D428-11d2-A769-00AA001ACF42

Otro logo de PHP:

Para desactivar el funcionamiento de estas URL especiales,  lo que hay que hacer es modificar el archivo php.ini (en mi caso en la carpeta /etc/php5/cgi ) y buscar la línea:

expose_php = On

y reemplazarla por

expose_php = Off

Reiniciamos PHP (o Apache u otro servidor web si es el caso) y hemos terminado.

Finalmente, como decía respecto a plataformas empresariales, una medida adicional sería reemplazar las extensiones .php por alguna otra modificando los archivos de configuración del servidor web, de manera que no sea posible deducir que el servidor está corriendo bajo un entorno PHP.

En el caso de nginx, debemos cambiar una líneas en el vhost correspondiente, supongamos que queremos modificarlo para que utilice la extensión .tech en vez de .php:

de ser:

location ~ .*\.php$ {
...
}

 

pasa a ser esto:

location ~ .*\.tech|$ {
...
}

Y ahora podemos utilizar la extensión .tech en nuestra aplicación Web.

Esconder versión de un proxy Squid

Este post sería para quien esté familiarizado con el uso de un proxy HTTP. En particular, el más popular es Squid:  http://www.squid-cache.org/

Nota: Estas instrucciones funcionan para Squid 2.x No he probado Squid 3 y desconozco si la configuración es similar o probablemente haya cambiado.

En particular yo lo utilizo justamente como un proxy caché, que me permite visitar algunas de mis páginas más frecuentes un poco más rápido. Y más aún, lo permite a toda la red local. De modo que, si tengo por ejemplo dos máquinas en mi red local y la primera visita http://techsurveyor.com/ a través del proxy, y posteriormente la segunda máquina visita la misma página, con un poco de suerte no tendrá que cargar desde Internet todo el contenido de la misma, sino que podrá tomar algunos elementos desde el caché de Squid, lo que acelera la carga.

Volviendo al punto, si alguno de ustedes ha visitado sitios para ver la dirección IP pública en que se encuentran, visitando estos sitios vía el proxy Squid veremos que se muestra información un tanto sensitiva, y que hablando de seguridad, podría ser inconveniente tenerla a la vista:

 

Este es un recorte de lo que se obtiene normalmente en una página como whatismyip.com (cubro la IP por privacidad):

 

Es decir, solamente la IP pública de donde nos conectamos.

Este, es un recorte de lo que se puede ver cuando usamos un proxy como Squid:

Demasiada información, y es una muestra de que cualquier servidor puede obtenerla y explotarla de algún modo. En resumen, se muestra lo siguiente y que no es del todo conveniente:

  • Que estamos usando un proxy.
  • Que el proxy es Squid.
  • Que el proxy usa el puerto 33000.
  • Que el proxy tiene un hostname llamado micompu.
  • Que el proxy está usando la versión 2.7.STABLE9 (esta parte puede ser la más comprometedora).
  • Adicionalmente, si nos vamos a una página cmyip.com también se muestra la IP interna de la máquina desde la cuál se está visitando (digamos, para una red privada, típicamente algo en el segmento 192.x.x.x), lo cual tampoco es del todo cómodo.

Entonces, para aquellos fanáticos de la seguridad, aquí unos pequeños tips para tratar de hacer más anónima la navegación a través de un proxy Squid.

En el archivo /etc/squid/squid.conf hemos de hacer las siguientes modificaciones, si la línea no existe hay que agregarla:

  1. visible_hostname elhostqueyoquiera
    Esta modificación sustituirá el hostname, en el ejemplo micompu por elhostqueyoquiera.
  2. httpd_suppress_version_string on
    Esto esconde la versión de Squid que estemos utilizando.
  3. via off
    Como alternativa, este cambio elimina el encabezado que muestra que nos estamos conectando desde Squid.
  4. forwarded_for off
    Finalmente, esta linea esconde la IP interna del visitante (para el caso de cmyip.com).

Todas las opciones se encuentran en la documentación, e incluso en el archivo squid.conf de ejemplo se habla de sus funciones y opciones.

Al final reiniciamos squid, o lo que es más rápido:

squid -k reconfigure

Con estos cambios, se obtiene una conexión más transparente y anónima a los sitios web. Hay más cambios (que aún no he probado), pero estas son las opciones más típicas para este propósito.

Para quien quiera investigar más a fondo, puede revisar en la documentación sobre el modo paranoia de Squid en el que se añaden una serie de líneas para restringir aún más los encabezados que se envían. Aunque como consecuencia de esto, en mi caso algunos sitios dejaron de funcionar correctamente (como whatismyip.com).

Espero le sirva a más de algún paranoico como yo =P

Migración de usuarios y passwords de un servidor MySQL

Ciertamente, debe haber muchos posts respecto a este asunto en otros blogs, foros o el foro oficial de MySQL, sin embargo en mi búsqueda no encontré una solución inmediata al problema.

Bien, pues como dice el título era necesario realizar una migración de las bases de datos de un servidor a otro. Bien, ciertamente había hecho volcados (dumps) de bases de datos para reinsertarlas en otro servidor. Hasta ahí todo bien. La pregunta es… ¿Y cómo copio los usuarios? Y es que una vez que lograra copiar todas las bases de datos, tendría que recrear a mano cada uno de los usuarios, lo cual no parece ser una buena solución.

Bueno, la herramienta típicamente utilizada para efectuar estas tareas es mysqldump

Y para copiar una base de datos a un archivo de texto, tenemos esto

mysqldump -u usuariodb -p basededatosacopiar > volcado.sql

Leyendo un poco la documentación, sabemos dos cosas para solucionar el problema con los usuarios:

  • Los privilegios y usuarios/passwords se guardan en la base de datos de nombre mysql.
  • El comando mysqldump provee una opción para dumpear todas las bases de datos llamada –all-databases

Así que me animé a hacer mis pruebas:

mysqldump -u root -p --all-databases > dump.sql

SCP al otro servidor, y ahi dentro…

mysql -u root -p < dump.sql

Termina la copia, salgo, entro en un shell MySQL, todo bien… Ok, reiniciemos el servidor MySQL:

service mysql restart

Stopping MySQL database server: mysqld failed!
Starting MySQL database server: mysqld already running.
/usr/bin/mysqladmin: connect to server at 'localhost' failed
error: 'Access denied for user 'debian-sys-maint'@'localhost' (using password: YES)'

Wow! ¿Y eso qué onda!?!? En debian, existe un usuario denominado debian-sys-maint, que se encarga de realizar algunas tareas de mantenimiento al iniciar y detener el servidor MySQL, y algunas tareas con los logs del servicio.
Así que buscando un poco, hay un archivo /etc/mysql/debian.cnf similar al .my.cnf que se puede crear en nuestro home para acceder automáticamente a un servidor determinado, sin preguntar usuario, host, o incluso el password.
Comparando ambos archivos, en el servidor anterior y el nuevo, tenían passwords diferentes. El archivo tiene una estructura así:

# Automatically generated for Debian scripts. DO NOT TOUCH!
[client]
host     = localhost
user     = debian-sys-maint
password = passdedebiansysmaint
socket   = /var/run/mysqld/mysqld.sock
[mysql_upgrade]
user     = debian-sys-maint
password =  passdedebiansysmaint
socket   = /var/run/mysqld/mysqld.sock
basedir  = /usr

Y como dice do not touch, mejor le hacemos caso 😛
Así que hay que decidí seguir el procedimiento para cambiar el password de un usuario en MySQL:
update user set password=PASSWORD("passdedebiansysmaint") where User='debian-sys-maint';
Y finalmente hacemos un:
flush privileges;
Y listo! El servidor reinicia normalmente:
service mysql restart

Stopping MySQL database server: mysqld.
Starting MySQL database server: mysqld.
Checking for corrupt, not cleanly closed and upgrade needing tables..

Espero les sirva =)

SCP: sobre archivos incompletos, pausar y resumir (rsync)

Cuando queremos transferir archivos entre computadoras, utilizamos algún tipo de protocolo como puede ser HTTP (al descargar un archivo de la web) o FTP.
Cuando queremos transferir archivos de forma SEGURA, utilizamos el protocolo SCP, que está basado en SSH y permite utilizar criptografía de llave pública para mantener seguras las conexiones.

Uno de los problemas típicos, es cuando la conexión entre las dos computadoras se corta, y las transferencias quedan interrumpidas. La cuestión es, ¿qué tal que era un archivo enorme de 10GB y se quedo a la mitad del camino, o peor aún, estaba por terminar? Pues con scp no hay modo de reanudar la transferencia y se tiene que reiniciar

El problema empeora cuando intentamos hacer una copia de un directorio con múltiples archivos (y posiblemente más directorios) y entonces la conexión se interrumpe.

#Caso 1: copiando un directorio con todo su contenido
scp -r midirectorio usuario@servidor:~/
#Caso 2: copiando sólo los archivos de un directorio dado
scp midirectorio/* usuario@servidor:~/destino/

En ambos casos, si la conexión se interrumpe, e intentamos repetir el comando, la copia comienza desde cero otra vez. Algunos pensaremos… “pues verifico que cosas se copiaron y que cosas no, y entonces repito el comando sólo para lo que no se copió”. Bueno, ¿y si el directorio tenía 10000 fotografías y otros 100 subdirectorios con más contenido? ¿Voy a seleccionar uno por uno? Creo que no es la mejor opción.

Una derivación de este último caso, es cuando tenemos un directorio que deseamos copiar digamos cada semana. Por ejemplo, hacer una copia de seguridad de un sitio web cada semana en otra computadora. Si lo hacemos con scp, cada semana hay que copiar el directorio COMPLETO. ¿Por qué desperdiciar todo ese ancho de banda?

Un caso similar, es cuando hacemos una copia de un archivo muy grande y por algún motivo DEBEMOS interrumpir la copia. Tenemos que empezar nuevamente si usamos scp. Esto no es conveniente.

Bueno, la solución está en el comando rsync que nos permite realizar copias incrementales y reanudar transferencias. No hasta hace mucho lo conocí en persona, a pesar de que ya había escuchado de él y muchas veces me encontré con los problemas mencionados.

El comando que utilizo es el siguiente:

rsync -avzP midirectorio usuario@servidor:~/directoriodestino

A grandes rasgos, cada flag significa los siguiente:

  • -a : Básicamente hará una copia recursiva del directorio preservando lso atributos de cada archivo.
  • -v : El famoso flag “verbose” para ver con mayor detalle lo que está ocurriendo durante la ejecución.
  • -z : Usar compresión. Muy útil para cuando el ancho de banda es escaso y se transmiten archivos de texto.
  • -P : Es la combinación de dos flags –progress y –partial. La primera, es para mostrar el progreso de la transferencia, y la segunda, y más importante, permite reanudar la transferencia desde un archivo “parcial” o incompleto si es que existe. Esto lo hace verificando el tamaño y la fecha de modificación de ambos archivos.

Hagan sus pruebas, y espero les sirva de algo este pequeño artículo. Cualquier error, háganmelo saber.