Tom Meister: Sichere Uploads

Hallo!

Was muss ich für sichere Uploads mit PHP aus einem Formular heraus beachten?

Geprüft wird der MIME-Typ. Zusätzlich ist das Uploadverzeichnis durch eine htaccess geschützt, die den Zugriff von überall verbietet. Nun konnte man trotzdem PHP-Skripts und schlimmer noch eine htaccess hochladen, weil text/plain erlaubt ist. Meine Lösung: An das Ende der hochgeladenen Datei wird eine weitere Dateiendung angehängt.

Ist das sicher genug, oder habe ich irgend was vergessen? Sollte der komplette Name der Datei umbenannt werden, damit ein Angreifer nicht weiß, wie die Datei nach dem Upload heißt? Kann ich noch was mit Verzeichnisrechten sichern, oder ist es sogar sinnvoll, den Uploadordner oberhalb des Doc-Root-Verzeichnisses zu legen?

  1. Hello,

    Was muss ich für sichere Uploads mit PHP aus einem Formular heraus beachten?

    Geprüft wird der MIME-Typ.

    Wie prüfst Du den?

    Zusätzlich ist das Uploadverzeichnis durch eine htaccess geschützt, die den Zugriff von überall verbietet.

    Es ist außerdem noch wichtig, dass auch das Upload-Temp-Dir geschützt ist. Es sollte auf jeden Fall mit dem Sticky-Bit belegt sein und es sollten auch nur die Eigentümer Zugriff auf die Datei haben (gilt für Linux).

    Nun konnte man trotzdem PHP-Skripts und schlimmer noch eine htaccess hochladen, weil text/plain erlaubt ist. Meine Lösung: An das Ende der hochgeladenen Datei wird eine weitere Dateiendung angehängt.

    Du kannst auf einem eigenen Server das Verzeichnis in eine noexec-Partition legen
    Du kannst für das Verzeichnis jedwede Ausführung / Übergabe der Dateien an Interpreter oder Shells unterbinden.

    Das Ablageverzeichnis für die Files sollte möglichst außerhalb der DocumentRoot liegen.

    Liebe Grüße aus Syburg bei Dortmund

    Tom vom Berg

    --
    Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de
    1. Hallo!

      Geprüft wird der MIME-Typ.

      Wie prüfst Du den?

      Mit mime_content_type() und einer Tabelle der zulässigen Typen.

      Zusätzlich ist das Uploadverzeichnis durch eine htaccess geschützt, die den Zugriff von überall verbietet.

      Es ist außerdem noch wichtig, dass auch das Upload-Temp-Dir geschützt ist. Es sollte auf jeden Fall mit dem Sticky-Bit belegt sein und es sollten auch nur die Eigentümer Zugriff auf die Datei haben (gilt für Linux).

      Sticky-Bit sagt mir jetzt nicht viel. Das Upload-Dir ist ja erst mal von PHP vorgegeben? Wo stelle ich das ein? In der php.ini? Und dann das Verzeichnis bearbeiten? Woher soll ein Angreifer wissen, wo das temp. Verzeichnis liegt?

      Ich habe jetzt allen außer dem Eigentümer alle Rechte entzogen. Das Uploadverz. liegt noch unterhalb Document-Root. Zuvor wurden hochgeladene Dateien trotz Anhängen einer Endung (z. B. boese.php.meineEndung) ausgeführt, solange die htaccess deaktiviert war.

      Nun konnte man trotzdem PHP-Skripts und schlimmer noch eine htaccess hochladen, weil text/plain erlaubt ist. Meine Lösung: An das Ende der hochgeladenen Datei wird eine weitere Dateiendung angehängt.

      Du kannst auf einem eigenen Server das Verzeichnis in eine noexec-Partition legen
      Du kannst für das Verzeichnis jedwede Ausführung / Übergabe der Dateien an Interpreter oder Shells unterbinden.

      Wie?

      Das Ablageverzeichnis für die Files sollte möglichst außerhalb der DocumentRoot liegen.

      Reicht es wirklich nicht, wenn

      a) eine eigene Endung angehängt wird
      b) eine htaccess im Verzeichnis liegt
      c) keine Lese- und Ausführrechte für alle außer dem Eigentümer (FTP) vorhanden sind? Eigentlich müsste doch b) langen, solange es einem Angreifer nicht gelingt, sie durch eine eigene zu ersetzen, oder?

      1. Hello,

        Geprüft wird der MIME-Typ.

        Wie prüfst Du den?

        Mit mime_content_type() und einer Tabelle der zulässigen Typen.

        Sticky-Bit sagt mir jetzt nicht viel. Das Upload-Dir ist ja erst mal von PHP vorgegeben?

        Das kann durch eine Einstellung in der php.ini oder im virt-host ... eingestellt werden und da wird dann gerne vergessen, das Sticky-Bit zu setzen (chmod o+t). Das ist aber auch nur dann relevant, wenn noch mehrere Domains auf das Verzeichnis zugreifen können.

        Wo stelle ich das ein? In der php.ini? Und dann das Verzeichnis bearbeiten? Woher soll ein Angreifer wissen, wo das temp. Verzeichnis liegt?

        Solche Angreifer kommen meistens von innen, sind also Mitnutzer des Hosts.
        Das Upload-Temp-Dir sollte daher aus dem Verzeichnis "/tmp/" entfernt werden.

        Liebe Grüße aus Syburg bei Dortmund

        Tom vom Berg

        --
        Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Hallo,

          Das kann durch eine Einstellung in der php.ini oder im virt-host ... eingestellt werden und da wird dann gerne vergessen, das Sticky-Bit zu setzen (chmod o+t). Das ist aber auch nur dann relevant, wenn noch mehrere Domains auf das Verzeichnis zugreifen können.

          Ich habe mal geguckt, in phpinfo steht für upload_tmp_dir no value. Heißt das, es wird in der httpd.conf eingestellt?

          1. Hello,

            Ich habe mal geguckt, in phpinfo steht für upload_tmp_dir no value. Heißt das, es wird in der httpd.conf eingestellt?

            Das bedeutet, dass der Default-Wert benutzt wird. Der ist dann i.d.R. /tmp, was auf Windows-Systemen anfänglich immer Probleme gemacht hat, da es dort nur /temp gibt/gab.

            Aber das ist ja ein anderes Problem und sollte außerdem auch inzwischen geklärt sein.

            Gerade in der Verwendung des Default-Verzeichnisses für alle auf dem Server gehosteten Dateien beinhaltet ein Risiko. Das gilt übrigens auch für die Session-Dateien.

            Liebe Grüße aus Syburg bei Dortmund

            Tom vom Berg

            --
            Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
            1. Hello,

              Gerade in der Verwendung des Default-Verzeichnisses für alle auf dem Server gehosteten

              Domains

              beinhaltet ein Risiko. Das gilt übrigens auch für die Session-Dateien.

              Liebe Grüße aus Syburg bei Dortmund

              Tom vom Berg

              --
              Nur selber lernen macht schlau
              http://bergpost.annerschbarrich.de
              1. Hello,

                Gerade in der Verwendung des Default-Verzeichnisses für alle auf dem Server gehosteten
                Domains

                Du hast recht, es ist /tmp, habe nachgeschaut. Es ist zwar nur ein VS, aber es sollte doch kein anderer Zugriff außer mir auf das /tmp-Verzeichnis haben!? Die Domains gehören alle mir.

                Wie müsste man denn vorgehen, wenn es unterschiedliche Domain-Eigentümer wären? Je Domain ein eigenes temp. Upload- bzw. Verzeichnis für Sessions für PHP über php_admin_value einstellen?

                1. Hello,

                  Wie müsste man denn vorgehen, wenn es unterschiedliche Domain-Eigentümer wären? Je Domain ein eigenes temp. Upload- bzw. Verzeichnis für Sessions für PHP über php_admin_value einstellen?

                  Liebe Grüße aus Syburg bei Dortmund

                  Ja, das wäre eine Möglichkeit. Getrennt für Sessions und Temporäre Dateien.
                  Und wenn man den Usern die Logfiles zur Verfügung stellen will, die auch noch ein eigenes Verzeichnis, das innerhalb open_basedir liegt. Allerdings das so einrichten, dass das Verzeichnis und die Logdateien immer root:root gehören, nicht dem Apache-User. Dann können die User nur gucken, aber nichts ändrn an den Logs. Sonst müsstest Du sie doppelt führen.

                  Tom vom Berg

                  --
                  Nur selber lernen macht schlau
                  http://bergpost.annerschbarrich.de
                  1. Hallo,

                    Ja, das wäre eine Möglichkeit. Getrennt für Sessions und Temporäre Dateien.
                    Und wenn man den Usern die Logfiles zur Verfügung stellen will, die auch noch ein eigenes Verzeichnis, das innerhalb open_basedir liegt. Allerdings das so einrichten, dass das Verzeichnis und die Logdateien immer root:root gehören, nicht dem Apache-User. Dann können die User nur gucken, aber nichts ändrn an den Logs. Sonst müsstest Du sie doppelt führen.

                    Das /tmp-Verzeichnis gehört ja root/root. Alle haben zwar Zugriff, aber das Sticky-Bit ist gesetzt. Wenn ich das mit dem Sticky-Bit richtig verstehe, kann ein Eigentümer einer Domain die tmp-Daten eines anderen Domain-Eigentümers zwar lesen, aber nicht verändern. Ist das richtig?

                    Ich frage mich noch immer, wie weit man den Aufwand treiben muss. Wichtig ist (in meinem Fall sowieso), dass nichts Schadhaftes von außen hochgeladen wird. Dessen ungeachtet, wie sollte ein Domaineigentümer auf dem gleichen VS schadhafte Dateien in das /tmp-Verzeichnis schieben, die anschließend auch noch vom Uploadskript geschluckt werden und in das Zielverzeichnis finden, und v. a. wieso?

                    Im Moment tendiere ich dazu, dass die Lösung mit htaccess und Rechte des Zielverzeichnisses ausschließlich für den Eigentümer reichen, selbst auf einem Server, wo man keinen Rootzugriff hat und geteilten Speicherplatz verwendet. Ich bin aber nicht so der Linux-Kenner. Im letzten Fall hat man ja auch keine viel weitergehenden Optionen.

                    1. Hello,

                      Das /tmp-Verzeichnis gehört ja root/root. Alle haben zwar Zugriff, aber das Sticky-Bit ist gesetzt. Wenn ich das mit dem Sticky-Bit richtig verstehe, kann ein Eigentümer einer Domain die tmp-Daten eines anderen Domain-Eigentümers zwar lesen, aber nicht verändern. Ist das richtig?

                      Im /tmp-Verzeichnis darf jedermann erstmal alles (rwx), sonst hätte es keinen Nutzen.
                      Damit dann aber doch nur der Eigentümer seine Datei löschen darf, gibt es das Sticky-Bit.

                      drwxrwxrwt    Durch das kleine t bei others wird das angezeigt. Man setzt es mit einer +1000, also einer gesetzten 1 in der ersten Stelle der vierstelligen Rechte

                      sstrwxrwxrwx   => 7777  anstelle von 0777
                          421421421421
                          |||
                          ||+- Sticky-Bit     Gesetzt aufs Verzeichnis: Nur der Eigentümer der enthalt. Datei darf löschen
                          |+-- Group-ID-Bit   Gesetzt aufs Verzeichnis: Angelegte Dateien bekommen die Gruppe des Verz.
                          +--- User-ID-Bit    Gesetzt auf eine Binary-Datei: Die Datei wird mit den Rechten des Eigentümers
                                              ausgeführt, nicht mit den Rechten des Aufrufers.

                      Liebe Grüße aus Syburg bei Dortmund

                      Tom vom Berg

                      --
                      Nur selber lernen macht schlau
                      http://bergpost.annerschbarrich.de
                      1. Hallo,

                        Im /tmp-Verzeichnis darf jedermann erstmal alles (rwx), sonst hätte es keinen Nutzen.
                        Damit dann aber doch nur der Eigentümer seine Datei löschen darf, gibt es das Sticky-Bit.

                        drwxrwxrwt    Durch das kleine t bei others wird das angezeigt. Man setzt es mit einer +1000, also einer gesetzten 1 in der ersten Stelle der vierstelligen Rechte

                        sstrwxrwxrwx   => 7777  anstelle von 0777
                            421421421421
                            |||
                            ||+- Sticky-Bit     Gesetzt aufs Verzeichnis: Nur der Eigentümer der enthalt. Datei darf löschen
                            |+-- Group-ID-Bit   Gesetzt aufs Verzeichnis: Angelegte Dateien bekommen die Gruppe des Verz.
                            +--- User-ID-Bit    Gesetzt auf eine Binary-Datei: Die Datei wird mit den Rechten des Eigentümers
                                                ausgeführt, nicht mit den Rechten des Aufrufers.

                        Danke, bei den letzten zwei Werten habe ich mich auch schon gefragt, was sie bedeuten. Bei gesetztem Sticky-Bit auf ein Verzeichnis dürfen andere als der Eigentümer den Inhalt enthaltener Dateien ändern!?

                        1. Hello,

                          Danke, bei den letzten zwei Werten habe ich mich auch schon gefragt, was sie bedeuten. Bei gesetztem Sticky-Bit auf ein Verzeichnis dürfen andere als der Eigentümer den Inhalt enthaltener Dateien ändern!?

                          Das hängt nur von den auf die Datei gesetzen Rechte ab. WEnn die normal übliche Maske (umask = 022) gesetzt ist, ergibt sich für Dateien das effektive Recht 644. Das bedeutet: Gruppe und Jeder dürfen lesen, aber nicht schreiben, Eigentümer darf lesen und schreiben.

                          Da die Datei aber im Verzeichnis verankert ist, gelten für das Löschen und Anlegen die Rechte des Verzeichnisses. Daher ist das "Klebebit" schon ganz hilfreich.

                          Liebe Grüße aus Syburg bei Dortmund

                          Tom vom Berg

                          --
                          Nur selber lernen macht schlau
                          http://bergpost.annerschbarrich.de