¿Cómo uso suEXEC?

Generalidades

suEXEC (que significa "ejecución de cambio de usuario") proporciona a los usuarios de Apache la capacidad de ejecutar programas CGI y SSI con ID de usuario diferentes al ID de usuario del servidor web que realiza la llamada. Normalmente, cuando se ejecuta un programa CGI o SSI, se ejecuta como el mismo usuario que ejecuta el servidor web.

Como medida de seguridad, suEXEC REQUIERE que todos los scripts CGI y los directorios en los que residen no sean modificables por nadie más que por el usuario propietario. suEXEC realiza comprobaciones en el CGI ejecutado para garantizar la seguridad del servidor. Tiene una comprobación de permisos estricta que da como resultado un "500 Internal Server Error" si los permisos del script no están configurados correctamente. También limpia el entorno pasando únicamente por aquellas variables de entorno que se consideran seguras.

Cuando se usa correctamente, esta función puede reducir considerablemente los riesgos de seguridad que implica permitir a los usuarios desarrollar y ejecutar programas CGI o SSI privados.

Permisos de Script

Debido a la forma en que suEXEC maneja la seguridad, el directorio en el que reside tu script CGI y el script en sí no deben ser modificables por nadie más que por el usuario. Si se puede escribir, aparece "500 Internal Server Error". El script también debe ser ejecutable y la forma más sencilla de establecer permisos es con chmod:

[server]$  chmod 755 script.cgi

Modulo de Apache mod_env

Debido a que suEXEC limpia el entorno eliminando todas las variables de entorno, excepto aquellas consideradas seguras por la configuración del servidor, las directivas proporcionadas por mod_env como SetEnv, PassEnv y SetEnvIf no funcionan como se esperaba.

Digamos que tienes foobar.cgi instalado en ambos /home/username/example.com y /home/username/example2.com:

#!/usr/bin/perl

use strict;
use CGI;

$ENV{FOOBAR} ||= 'default';
my $q = CGI->new;
print $q->header();
print $ENV{FOOBAR};

En el directorio de tu primer dominio, agrega un .htaccess con la directiva:

SetEnv FOOBAR foo

y en el directorio de tu segundo dominio, agrega lo siguiente:

SetEnv FOOBAR bar

Cuando visitas example.com/foobar.cgi en tu navegador, esperarás que imprima foo, y cuando visites example2.com/foobar.cgi, esperarás bar. En su lugar, el valor predeterminado se imprime en ambas ocasiones.

Al principio, puedes asumir que mod_env no está instalado o que la directiva SetEnv no es permitida desde el .htaccess. De hecho, SetEnv está funcionando bien. Establece la variable de entorno; suEXEC simplemente no lo pasa a tu script CGI.

Por un lado, si estás desarrollando tu propia aplicación, puedes tener esto en cuenta mientras la desarrollas y no diseñar tu aplicación para utilizar variables ambientales no estándar. Si, por otro lado, estás utilizando una aplicación de terceros y modificar el código fuente sería prohibitivamente difícil y/o consumirías mucho tiempo (o si solo necesitas tener esas variables de entorno personalizadas en la aplicación que estás desarrollando tu mismo), hay algunas soluciones que se describen en la siguiente sección.

Soluciones alternativas

Solución alternativa A: Anteponer HTTP_ al nombre de la variable

La forma en que DreamHost configura suEXEC, permite cualquier variable de entorno que comience con HTTP_ through. Entonces, si cambias tu .htaccess a:

SetEnv HTTP_FOOBAR foobar 

y usas:

$ENV{HTTP_FOOBAR} 

en tu script CGI, funciona como se esperaba.

Esta solución alternativa probablemente sea la más adecuada para las aplicaciones que estás desarrollando tu mismo. Examinar el código fuente de aplicaciones de terceros (especialmente aplicaciones grandes, que pueden tener cientos de miles de líneas) y cambiar cada instancia de $ENV{FOOBAR} a $ENV{HTTP_FOOBAR} sería prohibitivamente complejo y consumiría mucho tiempo, sin mencionar que tendrías que rehacer todo ese trabajo cada vez que actualice la aplicación. Esta solución es un poco hacky, pero funciona.

Solución alternativa B: Editando el script CGI para configurar la propia variable

Puedes colocar $ENV{FOOBAR} = 'foo'; en la parte superior de tu guión. Al igual que la Solución alternativa A, esta solución se adapta mejor a las aplicaciones que estás desarrollando tu mismo. Sin embargo, su utilidad es limitada: el propósito de usar variables de entorno es alterar el comportamiento de tu script en función del contexto (o entorno) desde el que se ejecuta. Si configuras la variable desde el propio script, el comportamiento del script es el mismo independientemente del contexto desde el que se ejecuta.

Solución alternativa C: Crear un script de envoltura o wrapper

Crea wrapper.cgi:

#!/bin/sh

export FOOBAR=foo
exec /home/username/example.com$SCRIPT_URL
  • Si solo tienes un script CGI para el que deseas establecer una variable de entorno, puedes cambiar la última línea de la envoltura a:
exec /home/exampleuser/example.com/foobar.cgi
  • Si necesitas establecer una variable de entorno para docenas o incluso cientos de archivos de una aplicación de terceros, $SCRIPT_URL te permite determinar qué script se solicitó y establecer la variable de entorno para ese script.

Luego, usa un .htaccess para redirigir las solicitudes del script a wrapper.cgi:

RewriteEngine On
RewriteRule ^application/.*\.cgi /wrapper.cgi
  • application es el directorio donde se encuentra tu aplicación (desarrollada por terceros o internamente).
  • Si solo estás configurando una variable de entorno para uno (o algunos) scripts CGI, puedes especificar el script en RewriteRule (por ejemplo, RewriteRule ^script.cgi/wrapper.cgi). Simplemente agrega RewriteRules adicionales para scripts adicionales.
  • Como puedes imaginar, simplemente continuar agregando RewriteRules más allá de algunos scripts se vuelve difícil de manejar. En cambio, es mejor hacer coincidir todos los archivos que terminan con una extensión de archivo específica. Al hacer coincidir solo los archivos que terminan en .cgi, .pl, .py, .rb, etc., los archivos estáticos como documentos e imágenes HTML no se ven afectados.
  • Si tu secuencia de comandos de envoltura está en el mismo directorio que las secuencias de comandos que deseas envolver y estás haciendo coincidir por patrón (esto no importa si estás haciendo coincidir un nombre de archivo específico), tu envoltura debe tener una extensión de archivo diferente a tus secuencias de comandos. Por ejemplo, si tu envoltura termina en .cgi, es posible que desees utilizar .pl (RewriteRule .*\.pl wrapper.cgi) o .py (RewriteRule .*\.py wrapper.cgi) para tus scripts.
  • wrapper.cgi puede llamar a un script fuera del directorio de tu dominio. Esto es realmente lo que probablemente quiera hacer, ya que la envoltura en /home/exampleuser/example.com/ y /home/exampleuser/example2.com puede hacer referencia a los mismos scripts en /home/shared.

La solución alternativa C es complicada, pero es adecuada para una gama mucho más amplia de casos que la solución alternativa A o la solución B. A diferencia de la solución alternativa A, puedes establecer una variable de entorno para cientos (o miles) de archivos editando solo dos archivos (wrapper.cgi y .htaccess). Y, cuando estableces una variable de entorno para una aplicación de terceros, no tienes que modificar ningún archivo cuando actualizas la aplicación. Puedes tener varios scripts de envoltura, por lo que, a diferencia de la Solución B, el contexto (o el entorno) puede alterar el comportamiento de los scripts. Simplemente copia wrapper.cgi y .htaccess de example.com a example2.com, edita wrapper.cgi, y luego cambia export FOOBAR=foo a export FOOBAR=bar, y has terminado.

Ver también

¿Este artículo ha respondido sus preguntas?

Última actualización el PST.

¿Aún no encuentra lo que busca?