micholee: Warum verlangen manche Software (Forum, Shop) 777'er Rechte

Hallo Leute,
ich frage mich, warum einige PHP Foren oder Shops bei der Installation bei manchen Ordnern die Rechte 777 verlangen? (Manche Webspace-Provider verbieten das ja mittlerweile)

Reicht denn bei Webscripten 700 nicht aus, da es sich beim Script selber ja eigentlich um den Besitzer des Ordners oder der Datei handelt?

Wenn ein User oder Admin nun über die Webseite etwas aufruft, dann ruft er es ja über das Webscript, sprich die PHP Datei auf, welches ja der Besitzer ist und nicht Gruppe bzw. Other?

Grüße

  1. Hi,

    ich frage mich, warum einige PHP Foren oder Shops bei der Installation bei manchen Ordnern die Rechte 777 verlangen? (Manche Webspace-Provider verbieten das ja mittlerweile)

    Weil insb. im Bereich Massenhosting das Rechtemanagement oftmals mangelhaft ist.

    Reicht denn bei Webscripten 700 nicht aus, da es sich beim Script selber ja eigentlich um den Besitzer des Ordners oder der Datei handelt?

    Idealerweise schon.
    Aber nicht, wenn bspw. FTP-Nutzer, der das Script hochlädt, und der Nutzer, unter dem PHP dann läuft, nicht identisch sind.

    MfG ChrisB

    --
    RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
    1. Danke,

      Weil insb. im Bereich Massenhosting das Rechtemanagement oftmals mangelhaft ist.

      jetzt bin ich doch etwas beruhigt, dass ich doch nicht so verkehrt gedacht habe.

      Reicht denn bei Webscripten 700 nicht aus, da es sich beim Script selber ja eigentlich um den Besitzer des Ordners oder der Datei handelt?

      Idealerweise schon.
      Aber nicht, wenn bspw. FTP-Nutzer, der das Script hochlädt, und der Nutzer, unter dem PHP dann läuft, nicht identisch sind.

      Ich habe bei xt:Commerce eines Freundes festgestellt, dass dieser ein paar Ordner (speziell im Admin-Bereich) auf 777 gesetzt haben will. Im Admin-Bereich war dann wiederum ein Bereich eines anderen Hersteller (Gambio) Bereiche für Bezahlung (Paypal), Analyse, Warenwirtschaft(?) usw.
      Dann habe ich mir das irgendwie versucht herzuleiten, ob das doch irgendwie Sinn machen würde, wenn da noch Drittanbieter im Spiel sind. Da ist mir aber nicht wirklich was eingefallen, bzgl. der Dateirechte.

      Grüße

  2. Moin Moin!

    Siehe auch diese Diskussion

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
    1. Hi,

      Siehe auch diese Diskussion

      danke, habe ich durchgelesen. bei 777 könnten ja wie bereits erwähnt auch other (also jeder von worldwide einfach in dem verzeichnis dateien speichern/ändern usw. ne?)

      nur, wie würde das dann aussehen?

      1. Moin Moin!

        bei 777 könnten ja wie bereits erwähnt auch other (also jeder von worldwide einfach in dem verzeichnis dateien speichern/ändern usw. ne?)

        nur, wie würde das dann aussehen?

        Mißverständnis: die letzte oktale Stelle des Mode ist nicht "world", schon gar nicht "worldwide", sondern "others". Also lokale(!) User, die weder Dateieigentümer noch Mitglied in der der Datei zugeordneten Gruppe sind.

        ls -l
        -rw-r-----  1 victim users        42 2010-06-12 16:11 example.txt
        -rwxrwxrwx  1 victim users      5599 2011-01-05 17:14 storage.xml

        Die Datei example.txt hat den Mode 640 (oktal), das bedeutet, dass nur der User victim sie schreiben kann, der User joe und alle Mitglieder der Gruppe users können sie lesen, der Rest kann weder schreiben noch lesen noch ausführen. (Mit Ausnahme des allmächtigen root, für den die Berechtigungen nicht gelten, weil er sich ohnehin alle Rechte verschaffen kann, die er haben will.)

        Die Datei storage.xml hat den Mode 777 (oktal), jeder kann lesen, schreiben und sogar ausführen, was bei XML typischerweise völliger Mumpitz ist. Der User evil aus der Gruppe badboys kann also den Inhalt von storage.xml beliebig ändern, auch wenn victim das eigentlich gar nicht will.

        Das heißt aber noch lange nicht, dass jeder Mensch auf der Welt die storage.xml sehen oder ändern kann, denn man braucht minimal einen Account auf dem System, oder einen von außen steuerbaren Prozess, sei es ein NFS-Daemon, Samba, FTP, oder schlicht PHP oder ein CGI unter dem Account des Webservers.

        So, und nun zu Massen-Hostern. Fangen wir mit einem gar nicht so massigen Hoster an, der hat exakt zwei Kunden victim und evil. Damit die beiden sich möglichst nicht gegenseitig in die Quere kommen, legt er für jeden der beiden eine eigene Gruppe an, wie das bei vielen Linuxen üblich ist. Beide können CGIs laufen lassen, können sich aber nicht auf dem Server einloggen (außer per FTP). Der Webserver läuft ebenfalls unter einem eigenen User wwwrun, mit der Gruppe wwwrun.

        ls -l
        -rwxr-xr-x  1 victim victim       42 2010-06-12 16:11 example.cgi
        -rwxrwxrwx  1 victim victim     5599 2011-01-05 17:14 storage.xml
        -rw-rw-rw-  1 victim victim      876 2011-01-06 00:05 secrets.xml
        -rw-r-----  1 victim victim   118765 2011-02-03 09:43 data.db
        -rw-------  1 victim victim       63 2011-01-04 13:15 geheim.txt

        evil kommt nun irgendwie an dieses Verzeichnislisting, sei es, weil der Hoster die Verzeichnisrechte nicht weit genug eingeschränkt hat oder weil das die dokumentierte Standard-Einstellung von example.cgi ist.

        Und weil der Webhoster nicht der cleverste ist ("wir machen das seit 1990 so!"), laufen *alle* CGIs unter dem Account des Webservers, wwwrun. (Ob CGI oder PHP ist völlig egal, ich nehme einfach mal CGIs an.)

        evil lädt nun ein eigenes CGI hoch, dass den Namen des Verzeichnisses von victim rät (/etc/passwd lesen, stumpf /home/$username/public_html annehmen, ...) und -- innerhalb der Grenzen, die die Unix-Dateirechte setzen -- Dateien manipulieren kann. Alle Aktionen von evil laufen dann "über Bande" unter dem Account des Webservers, wwwrun, einfach weil evil sein CGI in seinem Webbrowser aufruft.

        example.cgi mit Mode 755 ist erst einmal relativ sicher, evil alias wwwrun kann zwar den Source Code bzw. den Inhalt des Binärfiles auslesen, aber nicht ändern, dafür fehlt das w-Bit für others. Damit kann evil schon einmal das gesamte CGI auf Lücken abklopfen.

        secrets.xml mit Mode 666 ist ein leichtes Opfer, wwwrun ist weder Eigentümer noch in der victim-Gruppe, aber die Datei erlaubt ja auch für alle anderen User Lesen und Schreiben. evil hat damit volle Kontrolle über diese Datei.

        storage.xml mit Mode 777 ist ein genauso leichtes Opfer. Und um es noch schlimmer zu machen, ist die Datei ausführbar, ein ausreichend schlecht konfigurierter Webserver würde die Datei tatsächlich als CGI ausführen. Ob die Datei-Extension nun .xml, .rhababerquark oder .cgi ist, ist dem Unix-Derivat vollkommen egal, Dateien mit einem x-Bit werden ausgeführt.

        geheim.txt ist tatsächlich für evil nicht zu erreichen, weil wirklich nur victim und root Zugriff auf diese Datei haben. Auch wwwrun, der Webserver, kann nichts mit der Datei anfangen.

        data.db ist ebenso wenig erreichbar, aus den gleichen Gründen.

        Die Lösung dieses "Spiels über Bande" ist, Programmcode jedes Users unter dessen Account ausführen, und nicht unter einem Sammel-Account wie wwwrun, Stichwort suEXEC.

        Dann sieht die Situation etwas anders aus, denn der von evil hochgeladene Programmcode läuft nicht mehr als wwwrun, sondern als evil. Der von victim hochgeladene Programmcode läuft analog als victim, nicht mehr als wwwrun.

        example.cgi ist immer noch für evil les- und damit analysierbar. Besser wäre Mode 0700 (-rwx------).

        secrets.xml ist immer noch für evil kontrollierbar.

        storage.xml ebenso. Und was noch schlimmer ist: Es ist ausführbar. Eine Lücke in example.cgi, die dazu führt, dass storage.xml als externes Programm ausgeführt statt nur gelesen wird, sorgt dafür, dass evil beliebigen Programmcode unter dem Account von victim ausführen kann.

        geheim.txt ist nicht länger sicher vor dem Webserver, denn example.cgi läuft unter dem Account victim und hat damit Lese- und Schreibrechte auf diese Datei. Allerdings hat evil ohne Lücken in example.cgi keine Chance, auf diese Datei zuzugreifen, weil seine CGIs unter dem Account evil laufen, der fällt in die Kategorie others und hat keinerlei Rechte an dieser Datei.

        Für data.db gilt das gleiche.

        Was, wenn nun alle User in einer users-Gruppe stecken, statt in individuellen Gruppen?

        Keine großartigen Unterschiede für example.cgi, secrets.xml, storage.xml, geheim.txt.

        Aber data.db ist plötzlich für alle User lesbar, auch für evil, selbst wenn sein CGI unter dem Benutzer-Account evil läuft.

        Welcher Mode ist also der richtige?

        Für Dateien:

        644 (-rw-r--r--) für Dateien, die die ganze Welt sehen darf. HTML-Dateien, Bilder, Texte.
        444 (-r--r--r--) analog, jedoch mit Schutz gegen versehentliches Überschreiben
        600 (-rw-------) für "geheime" Dateien, z.B. Konfigurationsdatei mit dem Passwort zur Datenbank, oder auch für eine Flat-File-Datenbank.
        400 (-rw-------) analog, jedoch mit Schutz gegen versehentliches Überschreiben

        Ungerade Ziffern (das x-Bit) haben bei Dateien nichts verloren!

        Für Programme:

        755 (-rwxr-xr-x) für Programme, die die ganze Welt sehen darf. Das sind eigentlich nur die "ab Werk" installierten Programme des Betriebssystems.
        711 (-rwx--x--x) für Programme, deren Innenleben nicht jeder sehen soll. Haken: Das funktioniert nicht für Scripte, denn sobald der Script-Interpreter läuft, muß er das Programm lesen können. Für Scripte also zähneknirschend 755.
        700 (-rwx------) für Programme, die wirklich nur der Eigentümer ausführen können soll -- und der Webserver, wenn suEXEC im Spiel ist
        Analog 555, 511 und 500 für einen Schutz gegen versehentliches Überschreiben

        Gerade Ziffern (fehlendes x-Bit) haben bei Programmen nichts verloren.

        Für Verzeichnisse:

        Hier meint "x" nicht ausführen, sondern "cross", sprich: betreten

        755 ist der Normalfall, jeder darf den Verzeichnisinhalt lesen, jeder darf ins Verzeichnis hinein.
        700 verrammelt das Verzeichnis, nur der Eigentümer darf lesen/schreiben und überhaupt hinein
        711 ist die etwas lockerere Variante von 700: Hinein darf jeder, aber das Verzeichnislisting darf nur der Eigentümer sehen.

        Gerade Ziffern (fehlendes x-Bit) haben auch bei Verzeichnissen nichts verloren.

        Diese Modi funktionieren nicht wie erwartet, wenn der Hoster nicht fein säuberlich die Programme der Benutzer unter deren Account laufen läßt, sondern mit einem Sammelaccount arbeitet. Das ist aber IMHO ein Grund, den Hoster zu wechseln, denn unter einem Sammelaccount kann man einfach nicht sicher hosten.

        Dann gibt es auch noch wilde Konstrukte, bei denen zwar CGIs mit suEXEC laufen, PHP aber gnadenlos für alle User den selben Sammelaccount benutzt. Auch das ist IMHO ein Grund, den Hoster zu wechseln. PHP funktioniert nur auf einem getrennten Server (virtuell, managed oder Root) innerhalb des Webservers, ansonsten muß man sich damit behelfen, PHP per suEXEC als CGI laufen zu lassen, und das bremst ganz fürchterlich. Alles Gefrickel innerhalb von PHP, die Unix-Rechteverwaltung nachzubauen, funktioniert nicht.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
        1. Hi,

          perfekt erklärt, danke schön.

          Michi

        2. Hi!

          Noch ein paar Ergänzungen:

          example.cgi mit Mode 755 ist erst einmal relativ sicher, evil alias wwwrun kann zwar den Source Code bzw. den Inhalt des Binärfiles auslesen, aber nicht ändern, dafür fehlt das w-Bit für others. Damit kann evil schon einmal das gesamte CGI auf Lücken abklopfen.

          Wenn er für das Verzeichnis ein w-Bit hat, kann er sich die Dateirechte verschaffen. Dateirechte ändern ist nämlich eine Schreiboperation im Verzeichnis. Man muss also nicht nur die Dateirechte und Besitzverhältnisse betrachten, sondern auch die des Verzeichnisses, in dem etwas liegt. Eigentlich sogar bis hoch zur Wurzel, denn von übergeordnet nach weiter unten durchgehend kann man sich ja auch die Rechte verschaffen.

          storage.xml mit Mode 777 ist ein genauso leichtes Opfer. Und um es noch schlimmer zu machen, ist die Datei ausführbar, ein ausreichend schlecht konfigurierter Webserver würde die Datei tatsächlich als CGI ausführen. Ob die Datei-Extension nun .xml, .rhababerquark oder .cgi ist, ist dem Unix-Derivat vollkommen egal, Dateien mit einem x-Bit werden ausgeführt.

          Der Apache führt sie aber nur dann aus, wenn sie im CGI-Verzeichnis liegen. Das ist ein normales Verzeichnis, das mit Konfigurationsdirektiven (ScriptAlias) für die CGI-Ausführung freigegeben ist. Allerdings ist der Apache nicht der einzige, der sich für das x-Bit interessiert. Über das Betriebssystem gestartet ist es egal, in welchen Verzeichnis die x-Bit-Datei liegt. Deshalb ist das x-Bit auch außerhalb des ScriptAlias nicht ungefährlich. PHP-Scripte sind aber nicht unbedingt mit CGI-Scripten gleichzusetzen, aber dazu komme ich gleich noch.

          Welcher Mode ist also der richtige?
          Für Dateien:
          [...]
          600 (-rw-------) für "geheime" Dateien, z.B. Konfigurationsdatei mit dem Passwort zur Datenbank, oder auch für eine Flat-File-Datenbank.
          400 (-rw-------) analog, jedoch mit Schutz gegen versehentliches Überschreiben

          Tippfehler, in der 400er Zeile muss das -r-------- heißen.

          Ungerade Ziffern (das x-Bit) haben bei Dateien nichts verloren!
          Für Programme:
          711 (-rwx--x--x) für Programme, deren Innenleben nicht jeder sehen soll. Haken: Das funktioniert nicht für Scripte, denn sobald der Script-Interpreter läuft, muß er das Programm lesen können. Für Scripte also zähneknirschend 755.

          Wenn der Script-Interpreter PHP heißt, dann braucht der kein x-Bit. Ausnahme sind Scripts, die mit einer Shebang-Zeile beginnen und direkt über ihren Dateinamen aufgerufen werden. In der Shebang-Zeile steht dann der Pfad zum zu verwendenden Script-Interpreter.

          Auch andere nicht direkt aufgerufenen Scripts benötigen kein x-Bit, also alles was à la

          php script.php

          aufgerufen wird, muss vom Script-Interpreter (hier die CLI-Version von php) nur gelesen werden können.

          Gerade Ziffern (fehlendes x-Bit) haben bei Programmen nichts verloren.
          Gerade Ziffern (fehlendes x-Bit) haben auch bei Verzeichnissen nichts verloren.

          Verloren würde ich das nicht unbedingt bezeichnen. Es schadet nichts, nur die Funktionalität ist dann nicht da.

          Diese Modi funktionieren nicht wie erwartet, wenn der Hoster nicht fein säuberlich die Programme der Benutzer unter deren Account laufen läßt, sondern mit einem Sammelaccount arbeitet. Das ist aber IMHO ein Grund, den Hoster zu wechseln, denn unter einem Sammelaccount kann man einfach nicht sicher hosten.

          Dagegen hatte man bei PHP den Safe Mode erfunden, der das Problem der nicht erfolgten Trennung seitens des Systembetreibers lösen sollte. Doch das war aus Sicherheitssicht nicht der richtige Ansatz und machte mehr Probleme als er löste. Der Safe Mode ist aber im Grunde genommen Geschichte. Er existiert noch in der freien Wildbahn, wenn er jedoch angetroffen wird, zeugt das nur davon, dass der Administrator entweder ein Geizhals war (Apache-Modul mit vielen Usern ist performanter als jedes Script unter eigener Benutzerkennung separat zu starten) oder von Sicherheit nicht die allerbeste Ahnung hatte.

          Alles Gefrickel innerhalb von PHP, die Unix-Rechteverwaltung nachzubauen, funktioniert nicht.

          Genau, damit meintest du den Safe Mode.

          Lo!

          1. Hallo,

            Wenn er für das Verzeichnis ein w-Bit hat, kann er sich die Dateirechte verschaffen. Dateirechte ändern ist nämlich eine Schreiboperation im Verzeichnis.

            nein, das ist nicht wahr. chmod darf nur der Besitzer einer Datei ausführen.

            Gruß,
            Andreas.

            1. Hi!

              Wenn er für das Verzeichnis ein w-Bit hat, kann er sich die Dateirechte verschaffen. Dateirechte ändern ist nämlich eine Schreiboperation im Verzeichnis.
              nein, das ist nicht wahr. chmod darf nur der Besitzer einer Datei ausführen.

              Scheint so, als ob du Recht hast. Da hab ich wohl unzulässig verallgemeinert. Eine Datei löschen, die einem nicht gehört, aber in einem Verzeichnis steht, das man beschreiben darf, geht. Dass ein chmod aber nicht geht, hatte ich nicht angenommen. Danke für die Korrektur.

              Lo!

              1. Hi!

                Wenn er für das Verzeichnis ein w-Bit hat, kann er sich die Dateirechte verschaffen. Dateirechte ändern ist nämlich eine Schreiboperation im Verzeichnis.
                nein, das ist nicht wahr. chmod darf nur der Besitzer einer Datei ausführen.
                [...] Eine Datei löschen, die einem nicht gehört, aber in einem Verzeichnis steht, das man beschreiben darf, geht. [...]

                Da fällt mir doch grad ein, dass man in dem Fall die Datei zumindest löschen und neu erstellen kann, womit man im Allgemeinen ja auch das Ziel erreicht hat. Es stimmen zwar dann die Besitzverhältnisse nicht mehr, doch muss ein verwendendes Programm schon sehr auf Sicherheit bedacht sein, um das zu prüfen. Die meisten wollen ja einfach nur lesen/ausführen können.

                Lo!

          2. Moin Moin!

            Noch ein paar Ergänzungen:

            [...]

            storage.xml mit Mode 777 ist ein genauso leichtes Opfer. Und um es noch schlimmer zu machen, ist die Datei ausführbar, ein ausreichend schlecht konfigurierter Webserver würde die Datei tatsächlich als CGI ausführen. Ob die Datei-Extension nun .xml, .rhababerquark oder .cgi ist, ist dem Unix-Derivat vollkommen egal, Dateien mit einem x-Bit werden ausgeführt.

            Der Apache führt sie aber nur dann aus, wenn sie im CGI-Verzeichnis liegen. Das ist ein normales Verzeichnis, das mit Konfigurationsdirektiven (ScriptAlias) für die CGI-Ausführung freigegeben ist.

            Das stimmt leider nur teilweise.

            Ein geeignet konfigurierter Apache führt CGIs auch außerhalb des CGI-Verzeichnisses aus, wenn z.B. in der Konfiguration AddHandler cgi-script .cgi steht (auch bei Apache 2.0, 2.2, 2.3). Hier ist dann einzig die Datei-Extension entscheidend.

            Die SetHandler-Direktive (ebenfalls mindestens seit Apache 1.3 bis einschließlich 2.3 vorhanden) kann sogar für ALLE Dateien in einem Verzeichnis durch den cgi-script-Handler jagen, damit werden ALLE ausführbaren Dateien zu CGIs.

            Allerdings ist der Apache nicht der einzige, der sich für das x-Bit interessiert.

            Nö, aber der Apache hat noch eine Stelle, an der das x-Bit benutzt wird: XBitHack. Der Apache sieht eine HTML-Datei, die per x-Bit für die Server Side Include Engine ausgewählt wird. So weit, so harmlos. Nur sieht das Betriebssystem diese Datei als ausführbares Programm an. Und dann ist es gar nicht mehr harmlos.

            In diesem Zusammenhang sei angemerkt, dass ein Script nicht zwingend eine Shebang-Zeile ("#!/usr/local/bin/interpreter") braucht. Wenn der Kernel keine bessere Idee hat (sprich: das Dateiformat nicht erkennt), übergibt er das Script stumpf an /bin/sh. Das ist eine Altlast aus grauer Vorzeit, bevor der Shebang-Mechanismus ins Unix eingebaut wurde. Und /bin/sh arbeitet sich durch den Text, auch wenn der Text eigentlich HTML ist. HTML und ein Shell-Script zu mischen sollte durchaus möglich sein, die große Kunst ist eigentlich nur, den HTML-Shell-Hybriden dann auch noch valide zu halten.

            Als Tag-Suppe funktioniert z.B. folgendes:

              
            <!doctype html # ><html><head><title>HTML oder Shell?</title></head><body><!--  
            echo -en "Content-Type: text/plain\r\n\r\n"  
            # --><h1>HTML oder Shell?</h1><pre>  
            echo "Bin ich nun ein Shell Script oder doch HTML?"  
            echo "Vielleicht bin ich ja auch ein CGI?"  
            exit 0  
            </pre></body></html>  
            
            

            Raus kommt als Shell-Script:

              
            ./foo.html: line 1: !doctype: No such file or directory  
            Content-Type: text/plain  
              
            Bin ich nun ein Shell Script oder doch HTML?  
            Vielleicht bin ich ja auch ein CGI?  
            
            

            Und das ist ein komplett legaler CGI-Header, gefolgt von einem text/plain-Dokument. Nicht zu sehen: die erste Zeile mit der Fehlermeldung wird nach STDERR geschrieben, der Rest nach STDOUT. Beim Aufruf als CGI landet die erste Zeile somit im Webserver-Logfile, der Rest wird vom Webserver als CGI-Antwort verarbeitet.

            Der eigentliche Witz ist, das Bourne-Shells I/O-Redirection nicht nur hinter, sondern auch vor(!) dem Programm akzeptieren.

            foo < bar

            und

            < bar foo

            ... sind gleichwertig, die Leerzeichen rund um "<" sind auch noch optional. Die Shell liest die Doctype-Deklaration also als Aufruf des Programms "html" mit der Datei "!doctype" als STDIN.

            Über das Betriebssystem gestartet ist es egal, in welchen Verzeichnis die x-Bit-Datei liegt. Deshalb ist das x-Bit auch außerhalb des ScriptAlias nicht ungefährlich.

            Genau.

            PHP-Scripte sind aber nicht unbedingt mit CGI-Scripten gleichzusetzen, aber dazu komme ich gleich noch.

            Welcher Mode ist also der richtige?
            Für Dateien:
            [...]
            600 (-rw-------) für "geheime" Dateien, z.B. Konfigurationsdatei mit dem Passwort zur Datenbank, oder auch für eine Flat-File-Datenbank.
            400 (-rw-------) analog, jedoch mit Schutz gegen versehentliches Überschreiben

            Tippfehler, in der 400er Zeile muss das -r-------- heißen.

            Richtig!

            Ungerade Ziffern (das x-Bit) haben bei Dateien nichts verloren!
            Für Programme:
            711 (-rwx--x--x) für Programme, deren Innenleben nicht jeder sehen soll. Haken: Das funktioniert nicht für Scripte, denn sobald der Script-Interpreter läuft, muß er das Programm lesen können. Für Scripte also zähneknirschend 755.

            Wenn der Script-Interpreter PHP heißt, dann braucht der kein x-Bit.

            Doch, wenn PHP vom Betriebssystem via Shebang als Interpreter für ein Script geladen werden soll, muß das x-Bit gesetzt sein, sonst bekommt man errno=EPERM (Permission denied), unabhängig davon, ob es um PHP oder irgendeine andere interpretierte Sprache geht.

            Wenn der Webserver (egal welcher) aufgrund seiner Konfiguration beschließt, dass eine angeforderte Datei ein PHP-Script ist, das durch einen PHP-Interpreter laufen soll, ist das x-Bit nicht zwingend notwendig (es sei denn, der Webserver besteht darauf). Auch das ist unabhängig von PHP für alle möglichen Sprachen gültig.

            Der feine Unterschied ist, dass bei vielen Hostern und vielen Linux-Distributionen PHP gleich automatisch per mod_php in den Apachen eingebunden ist, während andere Sprachen via CGI oder seltener FastCGI angebunden werden. Deswegen scheint auf den ersten Blick PHP ein Sonderfall zu sein. Ist es aber nicht.

            Ausnahme sind Scripts, die mit einer Shebang-Zeile beginnen und direkt über ihren Dateinamen aufgerufen werden. In der Shebang-Zeile steht dann der Pfad zum zu verwendenden Script-Interpreter.

            Nö, keine Ausnahme, Regelfall. Siehe oben.

            Der dahinterstehende Mechanismus steckt seit Urzeiten in jedem Unix, irgendwo tief in der Implementierung vom exec()-Systemcall sieht sich der Kernel die ersten zwei Bytes der auszuführenden Datei an. Stehen dort die "magischen" Zeichen "#" und "!", so wird evtl. folgender Whitespace übersprungen, alles bis zum nächsten Whitespace als Interpreter-Programm angenommen, und alles nach dem Whitespace bis zum Zeilenende (LF-Byte) als Optionsstring für den Interpreter. Das jeweilige Unix-Derivat bastelt sich dann die Kommandozeilen-Argumente um, schiebt den Interpreter und den Optionsstring vor die eigentlichen Argumente, und unternimmt einen neuen Anlauf, exec() mit den veränderten Argumenten auszuführen. Siehe z.B. exec.c und insbesondere binfmt_script.c in Linux.

            Auch andere nicht direkt aufgerufenen Scripts benötigen kein x-Bit, also alles was à la

            php script.php

            aufgerufen wird, muss vom Script-Interpreter (hier die CLI-Version von php) nur gelesen werden können.

            Richtig, und für jeden Interpreter richtig.

            sh script.sh
            perl script.pl
            lua script.lua

            oder

            php script.sh
            sh script.pl
            perl script.lua
            lua script.php

            oder auch

            php script.exe
            sh script.cgi
            perl script.dll
            lua script.html
            python script.bat

            usw. funktionieren, so lange das Script für den aktuellen Benutzer lesbar ist. Wenn der Interpreter setuid root installiert ist, müßte es auch ohne Leserechte für den aktuellen Benutzer funktionieren.

            Letztlich ist das genau das, was der Kernel intern macht, wenn ein Script mit einer Shebang-Zeile anfängt. Ob der Interpreter das Script mit einer "ungewohnten" Dateiendung ausführen möchte, steht auf einem anderen Blatt, in einer Unix-artigen Umgebung stören sich allerdings die wenigsten Interpreter an ungewöhnlichen Dateiendungen.

            Bei binären Dateiformaten (ELF, a.out, ...) muß ein ausführbares Programm für den aktuellen Benutzer übrigens NICHT zwingend lesbar sein, es reicht, wenn der Kernel die Datei lesen (bei Netzwerk-Dateisystemen kann auch der Kernel nicht jede Datei lesen) und verstehen kann.

            Gerade Ziffern (fehlendes x-Bit) haben bei Programmen nichts verloren.
            Gerade Ziffern (fehlendes x-Bit) haben auch bei Verzeichnissen nichts verloren.

            Verloren würde ich das nicht unbedingt bezeichnen. Es schadet nichts, nur die Funktionalität ist dann nicht da.

            Klar, es schadet nicht, wenn ein Programm nicht ausführbar ist. chmod a-x /sbin/init && reboot, danach sprechen wir uns wieder ... ;-)

            Die 0 als Ausnahme von der Regel habe ich vergessen, Mode 700 und 750 kann für einige Programme bzw. Verzeichnisse durchaus sinnvoll sein.

            Diese Modi funktionieren nicht wie erwartet, wenn der Hoster nicht fein säuberlich die Programme der Benutzer unter deren Account laufen läßt, sondern mit einem Sammelaccount arbeitet. [...]

            Dagegen hatte man bei PHP den Safe Mode erfunden, der das Problem der nicht erfolgten Trennung seitens des Systembetreibers lösen sollte. Doch das war aus Sicherheitssicht nicht der richtige Ansatz und machte mehr Probleme als er löste. [...]

            Alles Gefrickel innerhalb von PHP, die Unix-Rechteverwaltung nachzubauen, funktioniert nicht.

            Genau, damit meintest du den Safe Mode.

            Exakt.

            Es ist schon schwierig genug, ein Programm außerhalb des Webservers in einem eigenen Prozess sicher unter einem anderen User-Account laufen zu lassen, siehe suEXEC.

            Innerhalb des Webserver-Prozesses (bzw. innerhalb eines Interpreters) ist das fast unmöglich, wenn man nicht für wirklich jede Funktion einen Wrapper zwischen Prozess und Kernel bastelt und damit größere Teile des Betriebssystems nachbaut. Und damit das innerhalb des Webserver-Prozesses funktioniert, muß der Webserver-Prozess mit root-Rechten laufen. Das will man in der Regel nicht, weil Angriffe auf den eigentlichen Webserver dann viel größeren Schaden anrichten können als wenn der Webserver brav unter einem unpriviligierten Account in einer abgeschotteten Umgebung (chroot, jails) läuft.

            Alexander

            --
            Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
            1. Hi!

              Der Apache führt sie aber nur dann aus, wenn sie im CGI-Verzeichnis liegen. Das ist ein normales Verzeichnis, das mit Konfigurationsdirektiven (ScriptAlias) für die CGI-Ausführung freigegeben ist.
              Das stimmt leider nur teilweise.
              [andere Möglichkeiten]

              Die setzen aber voraus, dass die irgendwer wissentlich oder versehentlich aktiviert. Ein (PHP-)Hoster wird das sicherlich nicht für die DocumentRoots der Kunden gemacht haben - davon war ich für diesen Einwand ausgegangen. Wenn man davon ausgeht, können die x-Bits im Apachen nicht wirken. Wer sie allerdings für irgendwelche Zwecke aktiviert hat, sollte sich fragen, ob das wirklich im DocumentRoot notwendig muss.

              HTML und ein Shell-Script zu mischen sollte durchaus möglich sein, die große Kunst ist eigentlich nur, den HTML-Shell-Hybriden dann auch noch valide zu halten.

              HTML-Validität wäre mir als Angreifer egal, Hauptsache ich bekomme die Syntax so hin, dass sie meinen Wunsch ausführt. Du meintest vermutlich syntaktische Validität.

              Ungerade Ziffern (das x-Bit) haben bei Dateien nichts verloren!
              Für Programme:
              711 (-rwx--x--x) für Programme, deren Innenleben nicht jeder sehen soll. Haken: Das funktioniert nicht für Scripte, denn sobald der Script-Interpreter läuft, muß er das Programm lesen können. Für Scripte also zähneknirschend 755.

              Wenn der Script-Interpreter PHP heißt, dann braucht der kein x-Bit.

              Doch, wenn PHP vom Betriebssystem via Shebang als Interpreter für ein Script geladen werden soll, muß das x-Bit gesetzt sein, sonst bekommt man errno=EPERM (Permission denied), unabhängig davon, ob es um PHP oder irgendeine andere interpretierte Sprache geht.

              Da das das haupsächliche Einsatzgebiet von PHP-Scripten ist, ging ich an dieser Stelle von vom Apachen/Webserver gestarteten Scripten aus. Dafür sind keine x-Bits notwendig.

              Der feine Unterschied ist, dass bei vielen Hostern und vielen Linux-Distributionen PHP gleich automatisch per mod_php in den Apachen eingebunden ist, während andere Sprachen via CGI oder seltener FastCGI angebunden werden. Deswegen scheint auf den ersten Blick PHP ein Sonderfall zu sein. Ist es aber nicht.

              Auch vom Apachen via (F)CGI gestartete PHP-Scripte benötigen kein x-Bit, da der Apache das Script nicht via Shell sondern den PHP-Interpreter startet, der das Script als Parameter übergeben bekommt und dann nur noch das r-Bit braucht.

              Ausnahme sind Scripts, die mit einer Shebang-Zeile beginnen und direkt über ihren Dateinamen aufgerufen werden. In der Shebang-Zeile steht dann der Pfad zum zu verwendenden Script-Interpreter.
              Nö, keine Ausnahme, Regelfall. Siehe oben.

              Mit Ausnahme meinte ich die anderen PHP-Einsatzfälle, also CLI-Aufrufe.

              Klar, es schadet nicht, wenn ein Programm nicht ausführbar ist. chmod a-x /sbin/init && reboot, danach sprechen wir uns wieder ... ;-)

              Wenn die Funktionalität benötigt wird, dann muss selbstverfreilich das x-Bit vorhanden sein. Das heißt jedoch nicht, dass alle Programme immer und zwingend das x-Bit brauchen, wenn sie nur mal eben irgendwo rumliegen sollen. Sowas soll ja auch gelegentlich vorkommen, dass man einen Teil des Dateisystems als Ablage und nicht als Ort zum Starten von Programmen verwendet. Beispielsweise, wenn man ein Programm uneingepackt (warum auch immer) zum Download anbietet, ist es nicht nötig, dass es aus dem Download-Verzeichnis heraus gestartet werden können muss.

              Lo!

              1. Moin Moin!

                Der Apache führt sie aber nur dann aus, wenn sie im CGI-Verzeichnis liegen. Das ist ein normales Verzeichnis, das mit Konfigurationsdirektiven (ScriptAlias) für die CGI-Ausführung freigegeben ist.
                Das stimmt leider nur teilweise.
                [andere Möglichkeiten]

                Die setzen aber voraus, dass die irgendwer wissentlich oder versehentlich aktiviert. Ein (PHP-)Hoster wird das sicherlich nicht für die DocumentRoots der Kunden gemacht haben

                Das sollte man jedenfalls hoffen.

                Bleibt also Social Engeneering, sprich: evil bringe den technisch nicht so versierten User victim mit viel Text dazu, irgendwo eine passende .htaccess-Datei hinzupacken, x-Bits zu setzen, oder sich sonst irgendwie einen vorkonfigurierten Webserver zu verkonfigurieren. Das ist dann aber schon wesentlich gezielter als einfach auf dem Shared Hosting Webserver mit dem eigenen Account in der Verzeichnis-Nachbarschaft herumzuschnüffeln.

                • davon war ich für diesen Einwand ausgegangen. Wenn man davon ausgeht, können die x-Bits im Apachen nicht wirken. Wer sie allerdings für irgendwelche Zwecke aktiviert hat, sollte sich fragen, ob das wirklich im DocumentRoot notwendig muss.

                Vollkommen richtig.

                HTML und ein Shell-Script zu mischen sollte durchaus möglich sein, die große Kunst ist eigentlich nur, den HTML-Shell-Hybriden dann auch noch valide zu halten.

                HTML-Validität wäre mir als Angreifer egal, Hauptsache ich bekomme die Syntax so hin, dass sie meinen Wunsch ausführt. Du meintest vermutlich syntaktische Validität.

                Nö, ich meinte als Bonus oben drauf auch noch valides HTML, idealerweise sogar so, dass das Dokument auf den ersten Blick auch nicht nach einem Shell-Script aussieht. Technisch ist das natürlich nicht notwendig, gängige Browser akzeptieren meine primitive Demonstration ohne Murren.

                Wenn der Script-Interpreter PHP heißt, dann braucht der kein x-Bit.

                Doch, wenn PHP vom Betriebssystem via Shebang als Interpreter für ein Script geladen werden soll, muß das x-Bit gesetzt sein, sonst bekommt man errno=EPERM (Permission denied), unabhängig davon, ob es um PHP oder irgendeine andere interpretierte Sprache geht.

                Da das das haupsächliche Einsatzgebiet von PHP-Scripten ist, ging ich an dieser Stelle von vom Apachen/Webserver gestarteten Scripten aus. Dafür sind keine x-Bits notwendig.

                Der feine Unterschied ist, dass bei vielen Hostern und vielen Linux-Distributionen PHP gleich automatisch per mod_php in den Apachen eingebunden ist, während andere Sprachen via CGI oder seltener FastCGI angebunden werden. Deswegen scheint auf den ersten Blick PHP ein Sonderfall zu sein. Ist es aber nicht.

                Auch vom Apachen via (F)CGI gestartete PHP-Scripte benötigen kein x-Bit, da der Apache das Script nicht via Shell sondern den PHP-Interpreter startet, der das Script als Parameter übergeben bekommt und dann nur noch das r-Bit braucht.

                Fast richtig. Die Shell hat mit der ganzen Geschichte nichts zu tun, es sei denn, der Programmierer hatte einen sehr faulen Tag und noch nie etwas von Injection gehört.

                Entweder hat der Webserver auf irgendeine Art Zugang zu einem dauerlaufenden Interpreter (mod_php, PHP als FastCGI), dann kann er über einen privaten Kanal (Funkionsaufruf, FastCGI-Request) den Interpreter anweisen, eine Datei zu laden. Dann reicht das r-Bit.

                Oder der Webserver hat keinen solchen privaten Kanal und keinen dauerlaufenden Interpreter, oder kann/darf/will den Dauerläufer nicht nutzen, dann muß er ein CGI-Programm oder einen FastCGI-Server via exec() starten, und in beiden Fällen ist das x-Bit notwendig. Ist das CGI-Programm bzw. der FastCGI-Server ein Script, ist außerdem das r-Bit notwendig.

                Klar, es schadet nicht, wenn ein Programm nicht ausführbar ist. chmod a-x /sbin/init && reboot, danach sprechen wir uns wieder ... ;-)

                Wenn die Funktionalität benötigt wird, dann muss selbstverfreilich das x-Bit vorhanden sein. Das heißt jedoch nicht, dass alle Programme immer und zwingend das x-Bit brauchen, wenn sie nur mal eben irgendwo rumliegen sollen. Sowas soll ja auch gelegentlich vorkommen, dass man einen Teil des Dateisystems als Ablage und nicht als Ort zum Starten von Programmen verwendet. Beispielsweise, wenn man ein Programm uneingepackt (warum auch immer) zum Download anbietet, ist es nicht nötig, dass es aus dem Download-Verzeichnis heraus gestartet werden können muss.

                Richtig. Dafür gibt es mount -o noexec, dann scheitert exec() trotz gesetzten x-Bits mit EPERM (Permission denied). Das verhindert allerdings nicht, dass man ein dort gelagertes Script per /usr/local/bin/interpreter /mnt/noexec/script gestartet wird. Binaries lassen sich aus einem mit noexec gemountetem Verzeichnis nicht starten.

                Alexander

                --
                Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
                1. Hi!

                  Oder der Webserver hat keinen solchen privaten Kanal und keinen dauerlaufenden Interpreter, oder kann/darf/will den Dauerläufer nicht nutzen, dann muß er ein CGI-Programm oder einen FastCGI-Server via exec() starten, und in beiden Fällen ist das x-Bit notwendig.

                  Ja, aber nicht für das (PHP-)Script, sondern nur für das php-cgi (die php.exe sozusagen). Das PHP-Script selbst muss dann nur noch von php-cgi gelesen werden können (r ohne x). Das CGI-Programm ist der PHP-Interpreter, nicht das PHP-Script.

                  Lo!