Die <If> -Bedingung mit HTTP_HOST in htaccess unterbricht PHP

Sep 20 2020

Ich möchte meinen gemeinsam genutzten Hosting-Webspace härten, um zu verhindern, dass PHP mit gefälschten Dateinamen wie foo.php.wrong gerendert wird, wie in den TYPO3-Sicherheitsrichtlinien vorgeschlagen . Details siehe auchhttps://stackoverflow.com/a/61760273/3946047

Da ich keinen Zugriff auf die Apache-Konfiguration habe, möchte ich die Konfiguration zu meiner .htaccessDatei hinzufügen . Damit die .htaccessDatei sowohl in meiner lokalen Entwicklungsumgebung als auch in der Produktion funktioniert , muss der Code mit einer <If>Bedingung versehen werden, die zwischen der Produktion und allen anderen Umgebungen unterscheidet.

Sobald ich die Bedingung hinzufüge, schlägt das PHP-Rendering für alle PHP-Dateien fehl. Stattdessen wird der Quellcode angezeigt. Um zu überprüfen, ob es sich bei meiner riesigen .htaccessDatei nicht um ein Problem handelt , habe ich eine neue Subdomain mit einem leeren Verzeichnis erstellt und diese in die .htaccessDatei eingefügt:

<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>

Dies funktioniert so lange, wie die Bedingung auskommentiert ist. Wenn ich die Bedingung aktiviere, zeigen selbst gültige PHP-Dateien wie index.php nur den Quellcode an, anstatt gerendert zu werden.

Der spezielle Typ application/x-httpd-php73wird benötigt, da mein Provider mehrere PHP-Versionen anbietet.

Mein Problem ist also nicht die Konfiguration selbst, sondern der Zustand. Irgendwelche Ideen, wie ich das beheben kann?

Antworten

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>

Dies "schlägt fehl", weil der innere <FilesMatch>Abschnitt (innerhalb des <If>Abschnitts), der den PHP-Handler wieder aktiviert, niemals tatsächlich verarbeitet wird. Dies hängt mit der Reihenfolge zusammen, in der Abschnitte zusammengeführt werden .

Das Umgeben der Anweisungen in einem <If>Block ändert die Reihenfolge der Verarbeitung. Der Inhalt des <If>Abschnitts wird sehr spät zusammengeführt, nachdem <Files> (und <FilesMatch>) Abschnitte zusammengeführt wurden. Es scheint also, dass es zum Zeitpunkt der <If>Verarbeitung des Abschnitts zu spät ist, um untergeordnete <Files>(oder <FilesMatch>) Container zu verarbeiten (da alle zu verarbeitenden <Files>Container bereits verarbeitet wurden). Obwohl dies zugegebenermaßen sehr kontraintuitiv ist und es, soweit ich sehen kann, in den Apache-Dokumenten keine "Warnung" dafür zu geben scheint.

Dies kann anhand eines einfachen Beispiels demonstriert werden (das für alle Anforderungen und alle Dateien gilt):

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

Ohne die <If>Wrapper, beide IF_OUTERund IF_INNER_FILESUmwelt vars sind gesetzt. Jedoch mit der <If>Hülle (den Block verursacht spät zusammengeführt werden), das IF_INNER_FILESist env var nicht gesetzt. Es spielt keine Rolle, welche Anweisungen verwendet werden: mod_setenvif, mod_rewrite usw. Der innere <Files>Block innerhalb des <If>Abschnitts wird niemals verarbeitet.


Sie können jedoch eine alternative Methode verwenden, die mod_rewrite verwendet, um böswillige Anforderungen des Formulars zu blockieren foo.php.wrong. Zum Beispiel:

RewriteEngine on    

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

Jede Anfrage an example.com(genau genommen jeden Hostnamen, der mit endet example.com), die .php.im URL-Pfad enthalten ist, gibt einfach eine 404 zurück.

Möglicherweise müssen Sie dies jedoch in einem anderen Teil Ihrer .htaccessDatei ablegen. Am besten in der Nähe der Spitze. Sie müssen die RewriteEngineAnweisung nicht wiederholen, wenn sie bereits vorhanden ist.


Es kann auch andere Möglichkeiten geben, Ihren Entwicklungsserver (oder besser gesagt den "Live-Server") zu identifizieren. z.B. Sie könnten Defineeine Variable in der Entwicklung Serverkonfiguration und die Prüfung für das Fehlen dieser Verwendung <IfDefine>in .htaccessstatt.

Zum Beispiel in Ihrer Entwicklungsserverkonfiguration:

Define DEVELOPMENT_SERVER

.htaccessÜberprüfen Sie dann , ob dies nicht definiert ist, um den Live-Server zu identifizieren:

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