Seguridad
PHP Manual

Reporte de Errores

Hablando de la seguridad en PHP, hay dos caras en lo que se concierne al reporte de errores. Una es benéfica al incremento de la seguridad, la otra va en dirección de su detrimento.

Una táctica de ataque típica involucra la acumulación de un perfil de datos del sistema alimentándolo con datos inapropiados, y luego chequear los tipos de errores que son devueltos, y sus contextos. Esto permite que el cracker del sistema pueda adquirir información del servidor, para así determinar posibles debilidades. Por ejemplo, si un atacante ha recogido información sobre una página creada a partir de los datos de un formulario, él podría intentar sobrescribir las variables, o modificarlas:

Example#1 Ataque a Variables con una página HTML personalizada

<form method="post" action="destino_del_ataque?username=badfoo&amp;password=badfoo">
<input type="hidden" name="username" value="badfoo" />
<input type="hidden" name="password" value="badfoo" />
</form>

Los errores de PHP que son devueltos normalmente pueden ser bastante útiles para un desarrollador que esté tratando de depurar un script, indicando cosas como la función o archivo que falló, el archivo PHP y el número de línea en donde ocurren los fallos. Toda esta es información de la que puede sacarse provecho. No es extraño que un desarrollador php use show_source(), highlight_string(), o highlight_file() como medida de depuración, pero en un sitio en producción, esta acción puede exponer variables ocultas, sintaxis sin chequear, y otra información peligrosa. Algo especialmente peligroso es ejecutar código que proviene de fuentes bien conocidas con gestores de depuración incorporados, o que usan técnicas de depuración comunes. Si el atacante puede determinar qué técnica general está usando, puede intentar un ataque de fuerza bruta sobre una página, enviando varias cadenas comunes de depuración:

Example#2 Explotación de variables comunes de depuración

<form method="post" action="destino_del_ataque?errors=Y&amp;showerrors=1&amp;debug=1">
<input type="hidden" name="errors" value="Y" />
<input type="hidden" name="showerrors" value="1" />
<input type="hidden" name="debug" value="1" />
</form>

Independientemente del método de gestión de errores, la capacidad de conseguir que un sistema revele sus posibles estados de error representa un camino para darle información al atacante.

Por ejemplo, el estilo mismo de un error de PHP genérico indica que el sistema está ejecutando PHP. Si el atacante estuviera viendo una página .html, y quisiera consultar qué está siendo usado para la generación de ella por detrás (en busca de debilidades conocidas en el sistema), podría determinar que el sistema fue creado usando PHP alimentándolo con información equivocada.

Un error de función puede indicar si el sistema está ejecutando un tipo particular de motor de base de datos, o dar pistas sobre cómo fue programada o diseñada una página web. Esto facilita posteriores investigaciones en determinados puertos abiertos de bases de datos, o en busca de fallos específicos o debilidades en una página web. Al entregar diferentes trozos de datos inválidos al sistema, por ejemplo, un atacante puede determinar el orden de autenticación en un script, (a partir de los números de línea de los errores) así como averiguar sobre vulnerabilidades que pueden aprovecharse en diferentes puntos del script.

Un error del sistema de archivos o en general de PHP puede indicar qué permisos tiene el servidor web, así como la estructura y organización de los archivos en el servidor web. Algún código de gestión de errores escrito por el desarrollador puede agravar este problema, llevando a la fácil explotación de información hasta entonces "escondida".

Existen tres soluciones principales a este problema. La primera es revisar cuidadosamente todas las funciones, y tratar de compensar por la mayoría de errores encontrados. La segunda es deshabilitar el reporte de errores completamente del código que está siendo ejecutado. La tercera es usar las funciones de gestión de errores personalizables de PHP para crear su propio gestor de errores. Dependiendo de su política de seguridad, puede encontrar que todas ellas pueden ser aplicables a su situación.

Una forma de detectar este problema por adelantado es hacer uso del reporte de errores propio de PHP (error_reporting()), para ayudarle a asegurar su código y encontrar uso de variables que pueda ser peligroso. Al probar su código, previamente a su entrega final, con E_ALL, puede encontrar rápidamente áreas en donde sus variables pueden estar abiertas a la manipulación y explotación en distintas formas. Una vez esté listo para liberar su código, es buena idea que deshabilite el reporte de errores por completo definiendo error_reporting() a 0, o desactive la impresión de errores usando la opción de php.ini display_errors, de modo que pueda aislar su código de ataques potenciales. Si elige la última opción, debe definir también la ruta a su archivo de registro usando la directiva ini error_log, y habilitar log_errors.

Example#3 Detección de variables peligrosas con E_ALL

<?php
if ($nombre_usuario) {  // Variable no inicializada o chequeada antes de su uso
    
$login_correcto 1;
}
if (
$login_correcto == 1) { // Si la condición anterior falla, esta variable
                            // no se encuentra inicializada ni validada
                            // antes de su uso

    
readfile ("/informacion/altamente/confidencial/index.html");
}
?>


Seguridad
PHP Manual