Probleme mit open_basedir und Symlink

  • Hallo zusammen,


    ich entwickle gerade eine Webseite mit Laravel. Für einen Test wollte ich meinen aktuellen Stand bei Netcup hochladen.

    Leider scheint dies nicht zu klappen.


    mit display_errors=on sehe ich:

    Code
    Warning: file_exists(): open_basedir restriction in effect. 
    File(/var/www/vhosts/hosting123.abc123.netcup.net/project_xy/20211106214144/public/../storage/framework/maintenance.php) 
    is not within the allowed path(s): (/var/www/vhosts/hosting123.abc123.netcup.net/:/tmp/:/var/lib/php/sessions) 
    in /var/www/vhosts/hosting123.abc123.netcup.net/project_xy/20211106214144/public/index.php on line 19

    open_basedir für die Domain ist im WCP wie folgt gesetzt: {WEBSPACEROOT}{/}{:}{TMP}{/}{:}{/}var{/}lib{/}php{/}sessions

    Damit müsste die Datei (eigentlich?) auch erreichbar sein.


    Meine Ordnerstruktur:

    Code
    /project_xy/storage/ <= symlink: ln -s /project_xy/storage /project_xy/20211106214144/storage
    /project_xy/20211106214144/storage/
    /project_xy/20211106214144/storage/framework/
    /project_xy/20211106214144/storage/framework/maintenance.php
    /project_xy/20211106214144/public/ <= als document_root im WCP für die Domain eingestellt
    /project_xy/20211106214144/public/index.php

    "storage" liegt also Außerhalb des aktuellen Deployments und wird per Symlink in den Ordner gesetzt (ln -s /project_xy/storage /project_xy/20211106214144/storage)

    Verzichte ich auf diesen Symlink und lege stattdessen den "storage"-Ordner direkt in das entsprechende Verzeichnis, funktioniert es.


    Unter "Einstellungen für Apache & nginx" habe ich

    Fähigkeit, symbolischen Verknüpfungen zu folgen, einschränken Wählen Sie diese Option aus, um Benutzer daran zu hindern, die Anweisung FollowSymLink in .htaccess zu verwenden und um so die Serversicherheit zu verbessern. deaktiviert


    Zur Sicherheit noch eine weitere Übersicht der Struktur:

    Code
    bash-4.4$ ls -la /project_xy/20211106214144
    lrwxrwxrwx  1 hosting123 psacln   15 Nov  7 12:04 storage -> /project_xy/storage
    
    bash-4.4$ ls -la /project_xy/
    total 4672
    drwxr-xr-x  9 hosting123 psacln     4096 Nov  7 12:02 .
    drwx--x--- 18 hosting123 psaserv    4096 Nov  6 19:03 ..
    drwxr-xr-x 10 hosting123 psacln     4096 Nov  7 12:04 20211106214144
    drwxr-xr-x  5 hosting123 psacln     4096 Oct 31 00:47 storage

    Hat jemand von Euch eine Idee warum es nicht klappt?


    Vielen Dank.

  • Danke für Deine Antwort.


    Ist FollowSymLinks oder SymlinkIfOwnerMatch auch gesetzt (.htaccess, falls Apache überhaupt verwendet wird)

    Ist gesetzt:

    Apache Configuration
    <IfModule mod_rewrite.c>
        Options +FollowSymLinks
        RewriteEngine On
    </IfModule>


    Ich konnte das Problem sogar weiter Reduzieren:


    Also

    • ohne Laravel etc.
    • Obige .htaccess und folgende Index.php
    • DocumentRoot = /project_xy/20211106214144/public

    unterer Test liefert

    Code
    is not within the allowed path(s): (/var/www/vhosts/hosting123.abc123.netcup.net/:/tmp/:/var/lib/php/sessions)

    Sowohl vendor als auch storage sind aber innerhalb von /var/www/vhosts/hosting123.abc123.netcup.net/

    nämlich:

    Code
    vendor: /var/www/vhosts/hosting123.abc123.netcup.net/project_xy/20211106214144/vendor
    storage: /var/www/vhosts/hosting123.abc123.netcup.net/project_xy/20211106214144/storage

    Der einzige Unterschied: storage ist ein Symlink ln -s /project_xy/storage /project_xy/20211106214144/storage

  • Hallo zusammen,


    ich habe noch ein paar Tests gemacht und nun als Grafik zusammenfasst.

    Damit sieht man auf einen Blick was geht und was nicht:


    netcup.png



    Und wie führst du die index.php aus? Aufruf über den Browser?

    Korrekt, über den Browser.

    Nur um das auch noch auszuschließen: Ändert sich am Verhalten etwas, wenn der Symlink über den Webserver (PHP) erstellt wird? Oder taucht der Fehler da schon beim Erstellen mittels symlink() auf?

    Gerade getestet. Der Fehler tritt auch hier auf.


    Skript

    Code
    $result = symlink('/../../storage', __DIR__ . '/../storage');
    if ($result) { echo "symlink OK"; } 
    else { echo "error"; }

    Ergebnis

    Code
    Warning: symlink(): open_basedir restriction in effect. File(/storage) is not within the allowed path(s): (/var/www/vhosts/hosting123.abc123.netcup.net/:/tmp/:/var/lib/php/sessions) in
  • Zusätzlich zu dem, was tab über mir bereits völlig korrekt angemerkt hat…


    Hat der Ordner project_xy die gleichen Rechte bzw. den gleichen Besitzer/Gruppe wie httpdocs?


    Falls nicht: Wiederhole den Test nochmals mit dem Docroot innerhalb von httpdocs.

    project_xy hat 755, httpdocs hat 750

    Code
    drwxr-xr-x  5 hosting123 psacln  4096 Nov  7 15:06 project_xy
    drwxr-x---  2 hosting123 psaserv 4096 Nov  7 15:39 httpdocs

    tab und KB19

    Und wenn du den '/' am Anfang weglässt? Ansonsten wird das Ziel ja ein absoluter Pfad, der so natürlich nicht innerhalb von irgendwas liegen kann.

    hier habe ich ein Verständnisproblem.

    die(__DIR__)liefert mir /var/www/vhosts/hosting123.abc123.netcup.net/project_xy/20211106214144/public

    und diesen Ordner bzw. alles unterhalb WEBSPACEROOT (=/var/www/vhosts/hosting123.abc123.netcup.net) kann ich problemlos auslesen wenn es kein Ziel von einem Symlink ist.


    Hier nochmal ein Update meiner Grafik:

    netcup2.png


    Euch beiden und auch allen anderen danke für die Hilfe! :)

  • Ich weiss nicht, ob sich open_basedir überhaupt mit symlinks austricksen lässt:


    "When a script tries to access the filesystem, for example using include, or fopen(), the location of the file is checked. When the file is outside the specified directory-tree, PHP will refuse to access it. All symbolic links are resolved, so it's not possible to avoid this restriction with a symlink."


    Quelle: https://www.php.net/manual/en/ini.core.php#ini.open-basedir

  • Hallo,


    ich habe eine Rainloop-Instanz unter mehreren Domains laufen und so verlinkt:


    hosting111111@a2f6c:/$ ls -l $(find httpdocs/ -type l )

    ...

    lrwxrwxrwx 1 hosting111111 psacln 28 Okt 29 05:40 httpdocs/domain.de/webmail/data -> ../../../local/rainloop/data

    lrwxrwxrwx 1 hosting111111 psacln 33 Okt 29 05:40 httpdocs/domain.de/webmail/index.php -> ../../../local/rainloop/index.php

    lrwxrwxrwx 1 hosting111111 psacln 32 Okt 29 05:40 httpdocs/domain.de/webmail/rainloop -> ../../../local/rainloop/rainloop

    ...


    Versuchs also mal mit

    cd /project_xy/202111106214144

    ln -s ../storage storage


    Diese relativen Links sind sowohl an der ssh-Konsole und im Webserver-Kontext korrekt.


    BTW: open_basedir kenne ich jetzt nicht, aber

    ln -s /project_xy/storage /project_xy/20211106214144/storage

    sieht für mich nicht gesund aus.


    VG

    Produkte bei Netcup: Neues Webhosting (2018) / VPS G7, Debian Bullseye

  • Ich weiss nicht, ob sich open_basedir überhaupt mit symlinks austricksen lässt:


    "When a script tries to access the filesystem, for example using include, or fopen(), the location of the file is checked. When the file is outside the specified directory-tree, PHP will refuse to access it. All symbolic links are resolved, so it's not possible to avoid this restriction with a symlink."


    Quelle: https://www.php.net/manual/en/ini.core.php#ini.open-basedir

    Vielleicht verstehe ich die Aussage falsch, aber /var/www/vhosts/hosting123.abc123.netcup.net/project_xy/20211106214144/storage (der Symlink) ist ja innerhalb von open_basedir


    Versuchs also mal mit

    cd /project_xy/202111106214144

    ln -s ../storage storage


    Perfekt. Das hat funktioniert! Vielen vielen Dank!


    Jetzt frage ich mich aber, warum hat mein Ansatz nicht funktioniert?

    Quote

    BTW: open_basedir kenne ich jetzt nicht, aber

    ln -s /project_xy/storage /project_xy/20211106214144/storage

    sieht für mich nicht gesund aus.

    Weil ich absolute Pfade verwende?

  • Ich weiss nicht, ob sich open_basedir überhaupt mit symlinks austricksen lässt:


    "When a script tries to access the filesystem, for example using include, or fopen(), the location of the file is checked. When the file is outside the specified directory-tree, PHP will refuse to access it. All symbolic links are resolved, so it's not possible to avoid this restriction with a symlink."


    Quelle: https://www.php.net/manual/en/ini.core.php#ini.open-basedir

    Nein, es lässt sich nicht durch Symlinks austricksen. Aber das Besondere hier ist ja, dass open_basedir das komplette Webhosting freigibt. Damit können prinzipiell Dateien aus dem gesamten Webspace gezielt mit Hilfe von Symlinks vom Apache ausgeliefert werden. Im Gegensatz zum Webserver ist PHP von vornherein nur durch open_basedir und Unix-Dateirechte begrenzt, braucht also eigentlich keine Symlinks um Zugriff zu Dateien außerhalb der document root zu bekommen. Es geht hier also eigentlich nur darum, das gewünschte reale Verzeichnis durch den Symlink unter einem anderen Pfad zugreifbar zu machen. Also auf ein Verzeichnis zuzugreifen, das nicht zum aktuellen Projekt gehört, indem im aktuellen Projekt ein Symlink auf das Verzeichnis erzeugt wird. Der Webserver selbst kann mit oder ohne Symlink auf keins der beiden Verzeichnisse (wenn man also den Symlink durch ein gleichnamiges Verzeichnis ersetzen würde) zugreifen, weil beide außerhalb der document root liegen.


    Ich bin kein PHP-Programmierer und lese auch nur das PHP Manual. Ob da bei Funktionen wie scandir() grundsätzlich überhaupt das Verzeichnis durch einen Symlink ersetzt werden kann, das weiss ich nicht - zumindest nicht ohne es auszuprobieren. FollowSymlinks oder SymlinkIfOwnerMatch sind Einstellungen für den Webserver, ob die überhaupt einen Einfluss auf das Verhalten von PHP haben weiss ich nicht, schätze aber eher, dass das auf PHP-Ebene entweder immer oder gar ncht funktioniert, unabhängig von diesen Einstellungen. Es mag aber auch auf die Spezifikation und Implementierung der konkreten PHP-Funktion, hier scandir(), ankommen. Keine Ahnung, bisher reine Spekulation meinerseits.


    Edit: Ich sehe, es klappt jetzt wohl mit dem relativen Symlink.

  • Jetzt frage ich mich aber, warum hat mein Ansatz nicht funktioniert?

    Weil ich absolute Pfade verwende?

    Weil der absolute Pfad zwar im chroot des ssh korrekt ist, nicht aber im Webserver-Kontext.

    Denn /var/www/vhosts/hosting123.abc123.netcup.net/project_xy/storage != /project_xy/storage im Webserver-Kontext, in dem PHP läuft.


    Der symbolische Link muss im Webserver-Kontext nach /var/www/vhosts/hosting123.abc123.netcup.net/project_xy/storage auflösen.

    Es wäre also vermutlich auch möglich mit

    cd /project_xy/202111106214144

    ln -s /var/www/vhosts/hosting123.abc123.netcup.net/project_xy/storage storage

    aber dann wäre der Link im chroot des ssh nicht gültig


    VG

    Produkte bei Netcup: Neues Webhosting (2018) / VPS G7, Debian Bullseye