<Si> condición con HTTP_HOST en htaccess rompe PHP

Sep 20 2020

Me gustaría fortalecer mi espacio web de alojamiento compartido para evitar que procese PHP con nombres de archivo falsos como foo.php.wrong como se sugiere en las Pautas de seguridad de TYPO3 . Para obtener más detalles, consulte tambiénhttps://stackoverflow.com/a/61760273/3946047

Como no tengo acceso a la configuración de Apache, me gustaría agregar la configuración a mi .htaccessarchivo. Pero para que el .htaccessarchivo funcione tanto en mi entorno de desarrollo local como en producción, necesito envolver el código con una <If>condición para distinguir entre producción y todos los demás entornos.

Pero tan pronto como agrego la condición, la representación de PHP falla para todos los archivos PHP. En su lugar, se muestra el código fuente. Para verificar que no es un problema de mi .htaccessarchivo enorme , creé un nuevo subdominio con un directorio vacío y puse esto en el .htaccessarchivo:

<IfModule mod_mime.c>
    RemoveType .html .htm
    <FilesMatch ".+\.html?$"> AddType text/html .html AddType text/html .htm </FilesMatch> RemoveType .svg .svgz <FilesMatch ".+\.svgz?$">
        AddType image/svg+xml .svg
        AddType image/svg+xml .svgz
    </FilesMatch>

    #<If "%{HTTP_HOST} =~ /^(.+)example\.com$/"> RemoveType .php <FilesMatch ".+\.php$">
        AddType application/x-httpd-php73 .php
        SetHandler application/x-httpd-php73
    </FilesMatch>
    #</If>
</IfModule>

Esto funciona siempre que se comente la condición. Cuando activo la condición, incluso los archivos PHP válidos como index.php solo muestran el código fuente en lugar de ser renderizados.

El tipo especial application/x-httpd-php73es necesario porque mi proveedor ofrece varias versiones de PHP.

Entonces mi problema no es la configuración en sí, sino la condición. ¿Alguna idea de cómo puedo solucionar esto?

Respuestas

MrWhite Sep 20 2020 at 07:47
#<If "%{HTTP_HOST} =~ /^(.+)example\.com$/"> RemoveType .php <FilesMatch ".+\.php$">
    AddType application/x-httpd-php73 .php
    SetHandler application/x-httpd-php73
</FilesMatch>
#</If>

Esto "falla" porque la <FilesMatch>sección interna (dentro de la <If>sección), que vuelve a habilitar el controlador PHP, nunca se procesa realmente. Esto tiene que ver con el orden en el que se fusionan las secciones .

Rodear las directivas en un <If>bloque cambia el orden de procesamiento. El contenido de la <If>sección se fusiona muy tarde, después de fusionar <Files>(y <FilesMatch>) las secciones. Entonces, parece que en el momento en que <If>se procesa la sección, es demasiado tarde para que se procese cualquier contenedor secundario <Files>(o <FilesMatch>) (ya que cualquier <Files>contenedor, que debe procesarse, ya ha sido procesado). Aunque es cierto que esto es muy contrario a la intuición, y no parece haber ninguna "advertencia" de esto, por lo que puedo ver, en los documentos de Apache.

Esto se puede demostrar con un ejemplo simple (que se aplica a todas las solicitudes y todos los archivos):

<If true>
    SetEnv IF_OUTER 1
    <Files *>
        SetEnv IF_INNER_FILES 1
    </Files>
</If>

Sin el <If>contenedor, se establecen las variables de entorno IF_OUTERy de IF_INNER_FILESentorno. Sin embargo, con el <If>contenedor (que hace que el bloque se fusione tarde), la IF_INNER_FILESvar env no se establece. No importa qué directivas se utilicen: mod_setenvif, mod_rewrite, etc., el <Files>bloque interno dentro de la <If>sección nunca se procesa.


Sin embargo, puede usar un método alternativo usando mod_rewrite para bloquear solicitudes maliciosas del formulario foo.php.wrong. Por ejemplo:

RewriteEngine on    

RewriteCond %{HTTP_HOST} example\.com$
RewriteRule \.php\. - [R=404]

Cualquier solicitud a example.com(estrictamente hablando, cualquier nombre de host que termine con example.com) que contenga .php.en la ruta URL simplemente devolverá un 404.

Sin embargo, es posible que deba colocarlo en una parte diferente de su .htaccessarchivo. Preferiblemente cerca de la parte superior. No es necesario que repita la RewriteEnginedirectiva si ya está presente.


También puede haber otras formas de identificar su servidor de desarrollo (o más bien, el "servidor en vivo"). p.ej. Puede usar Defineuna variable en la configuración de su servidor de desarrollo y verificar la ausencia de esto usando <IfDefine>en su .htaccesslugar.

Por ejemplo, en la configuración de su servidor de desarrollo:

Define DEVELOPMENT_SERVER

Entonces en.htaccess , verifique que esto no esté definido para identificar el servidor en vivo:

<IfDefine !DEVELOPMENT_SERVER>
    # Processed only on live server...
</IfDefine>