El uso de PHP como un binario CGI es una opción para el tipo de situaciones en las que por alguna razón no se desea integrar PHP como módulo de algún software de servidor web (como Apache), o en donde se espera usar PHP con diferentes tipos de capas que envuelven el entorno CGI para crear ambientes chroot y setuid seguros para la ejecución de scripts. Esta configuración usualmente involucra la instalación de un binario ejecutable del intérprete PHP en el directorio cgi-bin del servidor web. El aviso de seguridad de CERT CA-96.11 recomienda que se evite la colocación de cualquier intérprete bajo cgi-bin. Incluso si el binario PHP puede ser usado como un intérprete independiente, PHP está diseñado para prevenir el tipo de ataques que esta configuración hace posible:
Acceso a archivos del sistema: http://mi.servidor/cgi-bin/php?/etc/passwd
La información del query en una URL, la cual viene después del signo de interrogación (?), es pasada como argumentos de línea de comandos al intérprete por la interfaz CGI. Usualmente los intérpretes abren y ejecutan el archivo especificado como primer argumento de la línea de comandos.
Cuando es invocado como un binario CGI, PHP se rehúsa a interpretar los argumentos de la línea de comandos.
Acceso a cualquier documento web en el servidor: http://mi.servidor/cgi-bin/php/zona_secreta/doc.html
El segmento de la URL que sigue al nombre del binario de PHP, que contiene la información sobre la ruta /zona_secreta/doc.html es usada convencionalmente para especificar el nombre de un archivo que ha de ser abierto e interpretado por el programa CGI. Usualmente, algunas directivas de configuración del servidor web (Apache: Action) son usadas para redireccionar peticiones de documentos como http://mi.servidor/zona_secreta/script.php al intérprete de PHP. Bajo este modelo, el servidor web revisa primero los permisos de acceso al directorio /zona_secreta, y después de eso crea la petición de redireccionamiento a http://mi.servidor/cgi-bin/php/zona_secreta/script.php. Desafortunadamente, si la petición se hace originalmente en esta forma, no se realizan chequeos de acceso por parte del servidor web para el archivo /zona_secreta/script.php, únicamente para el archivo /cgi-bin/php. De este modo, cualquier usuario capaz de acceder a /cgi-bin/php es capaz también de acceder a cualquier documento protegido en el servidor web.
En PHP, la configuración de tiempo de compilación --enable-force-cgi-redirect y las directivas de configuración en tiempo de ejecución doc_root y user_dir pueden ser usadas para prevenir este tipo de ataques, si el árbol de documentos del servidor llegara a tener directorio alguno con restricciones de acceso. Consulte las siguientes secciones para una explicación detallada de las diferentes combinaciones.
Si su servidor no tiene contenido alguno que no esté restringido por contraseñas o control de acceso basado en direcciones ip, no hay ninguna necesidad de recurrir a estas opciones de configuración. Si su servidor web no le permite hacer redireccionamientos, o el servidor no tiene una forma de comunicarle al binario PHP que la petición de redireccionamiento es segura, puede especificar la opción --enable-force-cgi-redirect en el script de configuración. Aun así debe asegurarse de que sus scripts PHP no dependan de alguna forma especial de hacer llamados al script, ya sea directamente mediante http://mi.servidor/cgi-bin/php/dir/script.php ni por la redirección http://mi.servidor/dir/script.php.
Los redireccionamientos pueden ser configurados en Apache mediante el uso de directivas AddHandler y Action (vea más adelante).
Esta opción en tiempo de compilación previene que cualquier persona haga llamados a PHP directamente mediante una URL como http://mi.servidor/cgi-bin/php/directorio_secreto/script.php. En lugar de esto, PHP analizará documentos de esta forma únicamente si han pasado por una regla de redirección del servidor web.
Por lo general, el redireccionamiento en la configuración de Apache es realizada con alguna de las siguientes directivas:
Action php-script /cgi-bin/php AddHandler php-script .php |
Esta opción ha sido probada únicamente con el servidor web Apache, y depende de que Apache defina la variable de entorno no-estándar REDIRECT_STATUS a la hora de gestionar peticiones redirigidas. Si su servidor web no dispone de modo alguno de comunicar si la petición es directa o redirigida, no puede usar esta opción y debe recurrir a alguna de las otras formas documentadas aquí de ejecutar la versión CGI.
Incluir contenido activo en los directorios de documentos del servidor web, como scripts y ejecutables, es considerada en ocasiones una práctica insegura. Si, por algún fallo de configuración, los scripts no llegaran a ser ejecutados sino desplegados como documentos HTML normales, esto podría resultar en la revelación de información crítica como trabajos cubiertos por normas de propiedad intelectual o datos de seguridad como contraseñas. Por lo tanto muchos administradores de sistemas preferirán la configuración de otra estructura de directorios para los scripts que sean asequibles únicamente a través del CGI PHP, y por lo tanto deben ser interpretados siempre y no desplegados directamente.
Así mismo, si el método para asegurarse de que las peticiones no son redireccionadas, tal y como se describió en la sección anterior, no está disponible, es necesario entonces configurar un directorio raíz (doc_root) de scripts que sea diferente al directorio raíz de documentos web.
Puede definir el directorio raíz para scripts de PHP mediante la directiva de configuración doc_root en el archivo de configuración, o puede darle un valor a la variable de entorno PHP_DOCUMENT_ROOT. Si ésta está definida, la versión CGI de PHP construirá siempre el nombre del archivo a abrir con este doc_root y la información de la ruta dada en la petición, de modo que puede estar seguro de que ningún script será ejecutado por fuera de este directorio (excepto por aquellos indicados en user_dir, como se verá a continuación).
Otra opción que puede ser usada en este caso es user_dir. Cuando user_dir no está definida, lo único que controla la apretura de archivos es doc_root. Abrir una URL como http://mi.servidor/~usuario/doc.php no resulta en la apertura de un archivo bajo el directorio personal del usuario, sino de un archivo llamado ~usuario/doc.php bajo la ruta doc_root (así es, un directorio cuyo nombre comienza por el caracter de equivalencia [~]).
Si user_dir está definido como, por ejemplo, public_php, una petición como http://mi.servidor/~usuario/doc.php abrirá un archivo llamado doc.php bajo el directorio con el nombre public_php ubicado en el directorio personal del usuario. Si el directorio personal del usuario es /home/usuario, el archivo ejecutado es /home/usuario/public_php/doc.php.
La expansión del valor de user_dir ocurre independientemente del parámetro doc_root, de modo que es posible controlar el directorio raíz de los documentos y el acceso a los directorios de los usuarios en forma separada.
Una opción bastante segura es colocar el intérprete binario de PHP en alguna parte por fuera del árbol de archivos web. En /usr/local/bin, por ejemplo. El único inconveniente real con esta alternativa es que ahora usted tendrá que colocar una línea como esta:
al comienzo de cualquier archivo que contenga etiquetas PHP. También tendrá que hacer cada archivo ejecutable. Esto quiere decir que debe tratarlo exactamente igual a como trataría cualquier otro script CGI escrito en Perl o sh o cualquier otro lenguaje de scripting común que usara el mecanismo de escape-shell #! para el lanzamiento del intérprete.Para lograr que PHP gestione correctamente la información de PATH_INFO y PATH_TRANSLATED con este tipo de configuración, el intérprete PHP debe haber sido compilado con la opción de configuración --enable-discard-path.