zwerg: PHP Probleme nach erstmaliger Servereinrichtung

Glück auf!

Ich bin heute mit meiner Homepage online gegangen.
Meine Seite

Wie soll es anders sein: Vieles, was ich lokal mit Xampp getestet
habe, will nicht mehr funktionieren :(

Während ich die Datenbankanbindung noch selbst hingekriegt habe,
hoffe ich bei folgenden Dingen auf eure Hilfe:

1)Vorschaltseite
Hier will der Grafikcounter einfach nicht funktionieren. Die erscheinende Fehlermeldung kann ich leider nicht interpretieren.
Ich vermute, dass es daran liegt, dass auf dem Server die Textdatei
nicht angelegt werden kann, wobei ich nicht weiß, warum.
Weiß hier jmd. Rat?

Ich weiß, dass viele nichts von diesen Vorschaltseiten halten,
aber ich würde die (vorerst) gerne bestehen lassen, bis ich
den Besucherzähler um das Anlegen von Cookies erweitert habe
und auf die Home-Seite einbauen kann.

  1. Fotovorschau
    Die Vorschaubilder lese ich wie folgt aus:

Head:

<?php
// Hier wird der Titel automatisch über "GET" von "fotos.php" übergeben
$titel = $_GET['t'];
// Hier wird der Galerie-Ordner automatisch über "GET" von "fotos.php" übergeben
$ordner = $_GET['o'];
// Hier wird ein Array (Variable "galerie") angelegt
$galerie = array();
//Ordner öffnen
$dir = opendir ("../Bilder/Fotos/Web_klein/$ordner");
//Datei lesen ohne die Verzeichnisse darüber
while ($bild = readdir ($dir)){
 if ($bild != "." && $bild != ".." && $bild != "Thumbs.db")
 array_push($galerie,$bild);
}
closedir($dir);
//Zählen der Einträge in $galerie für das spätere festlegen des Endpunktes für die for-Schleife im body
$x = count($galerie);

?>

Body (für die ersten 5 Bilder, folgende ähnlich):

<?php
// Bestimmen des Startpunktes und des Endpunktes der for-Schleife (Bild 1-5)
for ($i = 0; $i < 5 and $i < $x; $i++){
echo "<a href="vorschau.php?t=" . $titel .  "&o=" . $ordner . "&bn=" . $galerie[$i] . ""><img src="../Bilder/Fotos/Web_klein/" . $ordner . "/" . $galerie[$i] . "" style=" border-width: 3px; border-color: #FFFFFF; "/></a>&nbsp;";
}
?>

Während er lokal und bei allen anderen Fotoalben die Bilder sortiert nach Dateinamen (001.jpg, 002.jpg, ..., 200.jpg) wiedergibt, macht er das bei dem oben verlinkten Album nicht. Weiß jmd. wieso und sagt es mir?
Kann ich hier mit einer Sortierung beim Auslesen Abhilfe schaffen?

Das war es erstmal, ich hoffe ich habe nicht wesentliche Angaben
vergessen oder übermäßig viele unwesentliche gemacht.

Beste Grüße

zwerg Alex

P.S.
Sowohl lokal als auch auf dem Server nutze ich PHP5

  1. echo $begrüßung;

    1)Vorschaltseite
    Hier will der Grafikcounter einfach nicht funktionieren. Die erscheinende Fehlermeldung kann ich leider nicht interpretieren.

    Warning: fopen(Counter/counter.txt) [function.fopen]: failed to open stream: Permission denied in /[...]/grafikcounter.php on line 21

    Der Rest sind Folgefehler. Die Meldung sagt aus, dass die Datei nicht geöffnet werden konnte, weil eine Berechtigung dazu fehlt.

    Ich vermute, dass es daran liegt, dass auf dem Server die Textdatei nicht angelegt werden kann, wobei ich nicht weiß, warum.

    Das kommt drauf an, was in Zeile 21 des Scripts steht. Wenn die Datei gelesen werden soll, hat der Webserver, bzw. der User unter dem das Script läuft, kein Leserecht. Soll die vorhandene Datei zum Schreiben geöffnet werden, braucht der User das Schreibrecht. Soll die Datei angelegt werden, benötigt der User das Recht, in dem Verzeichnis zu schreiben. Aber bitte nicht mit der chmod-777-Kanone auf diesen Spatzen schießen sondern erstmal das Rechtekonzept auf Unix-Maschinen verstehen und dann genau das benötigte Recht vergeben. Bei Fragen bitte nochmal nachfragen.

    // Hier wird der Titel automatisch über "GET" von "fotos.php" übergeben
    $titel = $_GET['t'];

    Das Übergeben des Parameters (vom Webserver zu PHP) hat bereits vor Aufruf deines Scripts stattgefunden. Du muss einfach nur noch die in $_GET bereitgestellten Werte nutzen. $_GET ist ein Array wie jedes andere auch (mit Ausnahme seiner superglobalen Verfügbarkeit). Eine weiteren "Übernahme" ist dabei nicht erforderlich.

    $ordner = $_GET['o'];
    $dir = opendir ("../Bilder/Fotos/Web_klein/$ordner");

    Das ist eine Sicherheitslücke. Wenn jemand als Parameter o statt eines einfachen Ordnernamens etwas wie ../../../ordnername übergibt, kann er auf beliebige Ordner zugreifen, für die der PHP-User das Leserecht hat. Prüfe vorher den Inhalt von $_GET['o'] auf unerlaubte Zeichen (beispielsweise den / ), bzw. dass nur erlaubte Zeichen drin sind (z.B. Buchstaben und Ziffern), oder gegen eine Liste der erlaubten Verzeichnisse.

    if ($bild != "." && $bild != ".." && $bild != "Thumbs.db")

    Die Thumbs.db kannst du löschen. Die benötigt nur dein lokales Bilderanschauprogramm.

    array_push($galerie,$bild);

    Statt array_push() benutzt man im Allgemeinen $array[] = $wert; (siehe dazu auch die Note/Anmerkung auf der Handbuchseite).

    echo "<a href="vorschau.php?t=" . $titel .  "&o=" . $ordner . "&bn=" . $galerie[$i] . ""><img src="../Bilder/Fotos/Web_klein/" . $ordner . "/" . $galerie[$i] . "" style=" border-width: 3px; border-color: #FFFFFF; "/></a>&nbsp;";

    Um nicht die " in mit "" begrenzten Strings maskieren (") zu müssen, kannst du den String in '' einfassen. Die zusätzliche Funktionalität der "" verwendest du ja hier nicht. Auch ist es möglich, Attributwerte in HTML-Code in '' einzufassen.
    &o= ist übrigens kein gültiges HTML. Statt & solltest du dessen Entity &amp; verwenden. (Es wären auch andere Trennzeichen möglich, wie beispielsweise das Semikolon (;). Dieses muss nicht entitisiert werden. Man muss dann aber, arg_separator.input anpassen, damit das Parsen der URL weiterhin funktioniert.)

    Während er lokal und bei allen anderen Fotoalben die Bilder sortiert nach Dateinamen (001.jpg, 002.jpg, ..., 200.jpg) wiedergibt, macht er das bei dem oben verlinkten Album nicht. Weiß jmd. wieso und sagt es mir?

    Die Dateien liegen nicht sortiert im Dateisystem. Bringe sie selbst in die gewünschte Ordnung, indem du das Array mit den Dateinamen wie gewünscht sortierst.

    echo "$verabschiedung $name";

    1. Danke für deine ausführliche und hilfreiche Antwort. Speziell auch
      für die Hinweise, die eigentlich garnicht erfragt hatte. Werde
      versuchen, deinen Hinweisen nachzugehen und mir erstmal alleine
      weiter zu helfen.
      Ansonsten hört ihr wieder von mir *g*

      Was wär ich nur ohne selfhtml - weiter so!

      Gruß
      Alex

    2. $ordner = $_GET['o'];
      $dir = opendir ("../Bilder/Fotos/Web_klein/$ordner");

      Das ist eine Sicherheitslücke. Wenn jemand als Parameter o statt eines einfachen Ordnernamens etwas wie ../../../ordnername übergibt, kann er auf beliebige Ordner zugreifen, für die der PHP-User das Leserecht hat. Prüfe vorher den Inhalt von $_GET['o'] auf unerlaubte Zeichen (beispielsweise den / ), bzw. dass nur erlaubte Zeichen drin sind (z.B. Buchstaben und Ziffern), oder gegen eine Liste der erlaubten Verzeichnisse.

      Kannst du mir das genauer erklären? Ich hab das jetzt mal
      versucht und bei mir hat das nicht geklappt. Also wenn ich
      was anderes eingeben, als erwartet kommt nur ne Fehlermeldung:
      "... failed to open dir: No such file or directory in ..."

      if ($bild != "." && $bild != ".." && $bild != "Thumbs.db")

      Die Thumbs.db kannst du löschen. Die benötigt nur dein lokales Bilderanschauprogramm.

      Hab das mal eingefügt für den Fall, dass ich mal versehentlich
      thumbs.db mitkopiere, weil er die Thumbs in Windoof immer wieder
      anlegt.

      Während er lokal und bei allen anderen Fotoalben die Bilder sortiert nach Dateinamen (001.jpg, 002.jpg, ..., 200.jpg) wiedergibt, macht er das bei dem oben verlinkten Album nicht. Weiß jmd. wieso und sagt es mir?

      Die Dateien liegen nicht sortiert im Dateisystem. Bringe sie selbst in die gewünschte Ordnung, indem du das Array mit den Dateinamen wie gewünscht sortierst.

      Klappt jetzt mit "sort".

      Gruß
      zwerg Alex

      1. echo $begrüßung;

        $ordner = $_GET['o'];
        $dir = opendir ("../Bilder/Fotos/Web_klein/$ordner");
        Das ist eine Sicherheitslücke. Wenn jemand als Parameter o statt eines einfachen Ordnernamens etwas wie ../../../ordnername übergibt, kann er auf beliebige Ordner zugreifen, für die der PHP-User das Leserecht hat. Prüfe vorher den Inhalt von $_GET['o'] auf unerlaubte Zeichen (beispielsweise den / ), bzw. dass nur erlaubte Zeichen drin sind (z.B. Buchstaben und Ziffern), oder gegen eine Liste der erlaubten Verzeichnisse.

        Kannst du mir das genauer erklären? Ich hab das jetzt mal versucht und bei mir hat das nicht geklappt. Also wenn ich was anderes eingeben, als erwartet kommt nur ne Fehlermeldung:
        "... failed to open dir: No such file or directory in ..."

        Wenn sich am Ende ../Bilder/Fotos/Web_klein/../../../irgendwoanders ergibt, jemand also in $_GET['o'] ein ../../../irgendwoanders abgelegt hat, wird effektiv der Inhalt von ../irgendwoanders ausgelesen. Natürlich muss das einen existierenden Pfad ergeben, aber das kann man durch Probieren herausfinden. Wenn der Angreifer dann auch noch die Fehlermeldung und damit den Pfad zum Script angezeigt bekommt, kann er sogar noch das Probieren etwas abkürzen.

        if ($bild != "." && $bild != ".." && $bild != "Thumbs.db")
        Die Thumbs.db kannst du löschen. Die benötigt nur dein lokales Bilderanschauprogramm.
        Hab das mal eingefügt für den Fall, dass ich mal versehentlich
        thumbs.db mitkopiere, weil er die Thumbs in Windoof immer wieder anlegt.

        Eventuell müsstest du noch ein strtolower() oder strtoupper() auf $bild anwenden, um es dann mit einem klein oder groß geschriebenen thumbs.db zu vergleichen, da Unix im Gegensatz zu Windows Unterschiede in der Schreibweise beachtet.

        echo "$verabschiedung $name";

        1. Wenn sich am Ende ../Bilder/Fotos/Web_klein/../../../irgendwoanders ergibt, jemand also in $_GET['o'] ein ../../../irgendwoanders abgelegt hat, wird effektiv der Inhalt von ../irgendwoanders ausgelesen. Natürlich muss das einen existierenden Pfad ergeben, aber das kann man durch Probieren herausfinden. Wenn der Angreifer dann auch noch die Fehlermeldung und damit den Pfad zum Script angezeigt bekommt, kann er sogar noch das Probieren etwas abkürzen.

          Ich muss also ne Funktion finden, die "/" verbietet beim übergeben.
          Richtig?
          Was hat derjenige den im "schlimmsten Fall" davon, dass er
          die Verzeichnisse auslesen kann? Kann er auch die Zugangsdaten
          von MySQL-Datenbanken auslesen, wenn er die Datei findet?
          Homepage besser erstmal wieder offline nehmen oder betroffene
          Seiten per .htaccess schützen?
          Oder "no risk no fun? ;-)

          Eventuell müsstest du noch ein strtolower() oder strtoupper() auf $bild anwenden, um es dann mit einem klein oder groß geschriebenen thumbs.db zu vergleichen, da Unix im Gegensatz zu Windows Unterschiede in der Schreibweise beachtet.

          Da muss ich mich erst wieder einlesen. Aber danke für die Tipps.

          Manno man. Jedesmal, wenn ich denke, ich bin mit irgend
          was fertig kommt wieder irgendwas.

          zwerg Alex

          1. echo $begrüßung;

            Ich muss also ne Funktion finden, die "/" verbietet beim übergeben.

            Es gibt mehrere Möglichkeiten. Eine wäre, die Namen der erlaubten Verzeichnisse gegen eine definierte Liste zu prüfen. Desweiteren könnte man prüfen, ob ein / im Dateinamen vorkommt, z.B. mit strpos(). Beachte dabei die Handbuchseite und den Unterschied zwischen 0 und false beim Rückgabewert der Funktion. Ebensogut könntest du mit einer ctype-Funktion auf erlaubte Zeichen prüfen (beispielsweise ctype_alnum() oder ctype_alpha()). Die ctype-Funktionen stehen aber nicht überall zur Verfügung. Du müsstest das vorher mit phpinfo() auf dem Zielsystem prüfen. Und auch die Verwendung Regulärer Ausdrücke wäre möglich, meist aber erst empfehlenswert, wenn es keine einfachere Lösung gibt.

            Was du im Fall nicht erlaubter Werte machst, ist dir überlassen. Ablehnen mit einer entsprechenden Meldung oder Verwenden eines Default-Wertes wären zwei Vorschläge.

            Was hat derjenige den im "schlimmsten Fall" davon, dass er die Verzeichnisse auslesen kann? Kann er auch die Zugangsdaten von MySQL-Datenbanken auslesen, wenn er die Datei findet?

            Er kann auf alle Dateien zugreifen, auf die du mit deinen Rechten auch zugreifen kannst. Dazu können auch Zugangsdaten und andere Hinweise auf Schwachstellen zählen. Was man mit fremden übernommenen Rechnern alles anstellen kann siehst du beispielsweise täglich in deiner Mailbox.

            Was in deinem konkreten Fall möglich ist, kommt auf den Rest der Scripte an. Wenn du das ermittelte Verzeichnis an ein Bildanzeigescript weitergibst, und du dort prüfst, dass die anzuzeigende Datei auch wirklich ein Bild ist, ist die Wahrscheinlichkeit des Datenausspähens schon wieder gesunken.
            Zum Prüfen, ob es sich bei einer Dati um eine Grafikdatei handelt eignet sich getimagesize(). Die Funktion gibt ein Array mit Informationen zum Bild zurück oder false, falls es kein Bild sein sollte. Bei false könnte man die Anzeige/Ausgabe der Datei verweigern.

            echo "$verabschiedung $name";

  2. Moin,

    1)Vorschaltseite
    Hier will der Grafikcounter einfach nicht funktionieren. Die erscheinende Fehlermeldung kann ich leider nicht interpretieren.
    Ich vermute, dass es daran liegt, dass auf dem Server die Textdatei
    nicht angelegt werden kann, wobei ich nicht weiß, warum.
    Weiß hier jmd. Rat?

    Das sieht so aus, als ob der User unter dem der Webserver (wahrscheinlich Apache) läuft keine Schreibrechte auf das Verzeichnis hat, in das du schreiben willst. Was für ein Server/Webspace ist es genau und hast du event. SSH-Zugang? Event. zeigt auch dein FTP-Programm die Rechte an. Ferne wäre Besitzer und Gruppe des Verzeichnisses in geschrieben werden soll interessant.

    1. »» Während er lokal und bei allen anderen Fotoalben die Bilder sortiert nach Dateinamen (001.jpg, 002.jpg, ..., 200.jpg) wiedergibt, macht er das bei dem oben verlinkten Album nicht. Weiß jmd. wieso und sagt es mir?
      Kann ich hier mit einer Sortierung beim Auslesen Abhilfe schaffen?

    Es gibt eine Funktion, um Arrays zu sortieren: http://www.php.net/manual/en/function.sort.php

    Damit solltest die Bilder im Array sortieren können.

    Gruß

    Stareagle

    1. Das sieht so aus, als ob der User unter dem der Webserver (wahrscheinlich Apache) läuft keine Schreibrechte auf das Verzeichnis hat, in das du schreiben willst.

      Das wird wohl stimmen; daran habe ich bisher nicht gedacht. Weiß
      jetzt in welche Richtung ich nach einer Problemlösung suchen muss.

      Kann ich hier mit einer Sortierung beim Auslesen Abhilfe schaffen?

      Es gibt eine Funktion, um Arrays zu sortieren: http://www.php.net/manual/en/function.sort.php

      Danke für den Link, ich werde mich hier einlesen.
      Ich denke ich komme jetzt - dank deiner Hilfe - erstmal
      alleine zu recht.

      Gruß
      Alex