10 trucos para securizar PHP

php 5.3.6

En esta entrada vamos a ver unos cuantos puntos que nos servirán para securizar PHP en nuestro servidor web. Nos centramos en la configuración propia de PHP, hay que tener en cuenta que la securización de la capa aplicación es tanto o más importante que la de la configuración del servidor. Hay que tener siempre actualizados a la última versión estable y con los parches de seguridad correctamente aplicados cualquier cms o script de terceros tipo WordPress, Joomla, Oscommerce, etc.

Ocultar la versión de PHP

En su día hice un artículo completo sobre esto, podéis verlo aquí (ocultar la versión de PHP). Básicamente evitamos que con un simple telnet puedan averiguar la versión de PHP que hay corriendo en el servidor:

# telnet servidor 80

Connected to xxx.com (xx.xx.xx.xx).
Escape character is '^]'.
HEAD / HTTP/1.0

HTTP/1.1 200 OK
Date: Fri, 13 Aug 2010 14:18:09 GMT
Server: Apache/1.3.26 (Unix) mod_gzip/1.3.26.1a PHP/5.3.3
Last-Modified: Fri, 12 Feb 2010 12:22:56 GMT
ETag: "44967c-6f-53ca4800"
Accept-Ranges: bytes
Content-Length: 111
Connection: close
Content-Type: text/html

Connection closed by foreign host.

Para evitar esto cambiamos a off la siguiente variable en el fichero de configuración general php.ini:

expose_php Off

Deshabilitar funciones peligrosas

También hice un artículo hace un tiempo: PHP: Deshabilitar funciones peligrosas. Existen funciones que en servidores con aplicaciones estándar rara vez se usan, pero que por contra pueden generar graves problemas de seguridad si el atacante consigue utilizarlas. Es preferible desactivar el mayor número posible y en caso de que una de ellas sea necesario valorar su activación o proponer alternativas.

Las funciones a deshabilitar se añaden en la directiva «disable_functions» en el fichero php.ini. Aquí tenéis un ejemplo con funciones peligrosas que conviene desactivar:

disable_functions = «apache_child_terminate, apache_setenv, define_syslog_variables, escapeshellarg, escapeshellcmd, eval, exec, fp, fput, ftp_connect, ftp_exec, ftp_get, ftp_login, ftp_nb_fput, ftp_put, ftp_raw, ftp_rawlist, highlight_file, ini_alter, ini_get_all, ini_restore, inject_code, mysql_pconnect, openlog, passthru, php_uname, phpAds_remoteInfo, phpAds_XmlRpc, phpAds_xmlrpcDecode, phpAds_xmlrpcEncode, popen, posix_getpwuid, posix_kill, posix_mkfifo, posix_setpgid, posix_setsid, posix_setuid, posix_setuid, posix_uname, proc_close, proc_get_status, proc_nice, proc_open, proc_terminate, shell_exec, syslog, system, xmlrpc_entity_decode»

O un ejemplo más conservador:

disable_functions ="system,passthru,escapeshellarg,escapeshellcmd,proc_close,proc_open,ini_alter,popen,show_source,pcntl_exec"

deshabilitar session ID en URL

Si queremos que las URL’s de nuestros sitios PHP no muestren los ID de sesiones:

http://ejemplo.com/?PHPSESSID=4kgj577sgabvnmhjgkdiuy1956if6ska

Modificamos la directiva siguiente en el fichero php.ini:

session.use_trans_sid = off

Deshabilitar register_globals

Pese a ser una directiva antigua y que se encuentra en periodo de extinción todavía quedan desarrolladores/programadores que la utilizan. Esta función permite al atacante manipular cualquier variable global definida en la programación. Por defecto está deshabilitada en las versiones actuales de PHP, pero conviene revisarlo por si en algún momento se ha activado:

register_globals = Off

Desactivar acceso a URL remotas en funciones de manejo de ficheros

Funciones como include, fopen o file_get_contents permiten, además de hacer llamadas a ficheros locales, llamar a ficheros vía URL, esto puede provocar graves errores de seguridad invocando a scripts maliciosos que se encuentran fuera de nuestro servidor y su ejecución remota.

Para deshabilitarlo modificamos la directiva allow_url_fopen a Off en el php.ini:

allow_url_fopen = Off

Evitar el acceso a la información de PHP

Como ya sabéis con un simple script como el siguiente podemos ver vía URL toda la información de PHP, su compilación, sus módulos activados, versión, directivas de configuración, etc.

<? phpinfo() ?>

Si queremos desactivarlo, únicamente hay que modificar a Off la siguiente directiva en el fichero php.ini:

expose_php = Off

Si en algún momento necesitáis conocer alguna información, siempre podéis averiguarla desde línea de comandos: información sobre PHP desde línea de comandos

Safe Mode

safe_mode = On

Si bien por defecto safe_mode On puede significar una restricción demasiado fuerte en determinados entornos, puede ayudar mucho a incrementar la seguridad de nuestro servidor. Activar safe_mode implica que los scripts PHP únicamente pueden acceder a los ficheros que tienen como propietario el mismo que ellos. De este modo evitamos por ejemplo que tengan acceso de lectura a ficheros de sistema como /etc/passwd entre otros.

Efectivamente, esto puede ser un problema en el momento que necesitamos acceder a información generada por otros usuarios en el sistema (ficheros de otras aplicaciones. La solución es la siguiente:

safe_mode = Off
safe_mode_gid = On

Activamos safe_mode_gid en lugar de safe_mode, de modo que en lugar de revisar el usuario se revisa el grupo. Independientemente del UID del fichero, necesitaremos que estar dentro del grupo para poder acceder al ficheros. El grupo del script PHP deberá ser el mismo que el del fichero a acceder.

Otro punto a tener en cuenta con safe_mode es que no podremos ejecutar binarios. Únicamente aquellos que ubiquemos en el directorio especificado en la configuración:

safe_mode_exec_dir = /directorio

Esto se solaparía con las funciones deshabilitadas anteriormente, como por ejemplo system() o exec().

open_basedir

open_basedir = /directorio

La directiva open_basedir permite configurar que PHP pueda acceder únicamente a los ficheros de un único directorio (y sus subdirectorios). Es una buena forma de enjaular PHP si realmente sólo necesitamos que acceda a un determinado directorio.

Visualización y registro de errores

display_errors = Off
log_errors = On
error_log = /ruta/fichero/log

Con estas tres directivas, evitamos que cualquier error o warning se muestre por pantalla y hacemos que se registren directamente en un log especificado. De este modo podemos evitar que se muestre información sensible por pantalla. También podéis hacer uso de la directiva error_reporting si queréis mostrar por pantalla los errores. Con ella podéis especificar que se muestren únicamente los warning, los notice o lo que queráis.

SQL Injection

En su día se utilizaba magic_quotes para limpiar los datos de entrada de un script PHP, pero es una directiva obsoleta a partir de PHP 5.3 así que no merece la pena hablar de ella. En su defecto, si usáis servidor web Apache, os recomiendo encarecidamente configurar mod_security y habilitar sus reglas que permiten detectar y parar una gran cantidad de ataques de este tipo, y sino, puedes crear tus propias reglas.

Como último apunte, conviene siempre si es posible mantener una versión estable de PHP, libre de bugs y fallos de seguridad. Seguro además que una vez aplicados estos trucos os toca lidiar con los programadores. Se quejarán de algo seguro ;)

Un comentario en “10 trucos para securizar PHP

Comments are closed.