oxo888oxo: Fehlermeldung bei $visitor_referer = $_SERVER["HTTP_REFERER"];

0 62

Fehlermeldung bei $visitor_referer = $_SERVER["HTTP_REFERER"];

oxo888oxo
  • php
  1. 0
    Matthias Apsel
    1. 0
      oxo888oxo
      1. 0
        Matthias Apsel
        1. 0
          dedlfix
          1. 0
            Auge
            1. 0
              dedlfix
              1. 0

                $_SERVER["SERVER_NAME"], $_SERVER['HTTP_HOST'] und das DNS

                Regina Schaukrug
                • apache
                • php
                • webserver
                1. 0
                  dedlfix
                  1. 0
                    Regina Schaukrug
    2. 0
      Gunnar Bittersmann
      1. 0
        dedlfix
    3. 0
      pl
      1. 0
        dedlfix
  2. 3

    WARNUNG!

    Regina Schaukrug
    • php
    • sicherheit
    1. 0
      Julius
    2. 0
      oxo888oxo
      1. 0
        dedlfix
        1. 0
          Regina Schaukrug
          1. 3
            dedlfix
            1. 0
              Regina Schaukrug
              1. 1
                Auge
                • sicherheit
                • software
        2. 0
          oxo888oxo
    3. 2
      Reiner Makohl
      1. 0

        Verbesserungen

        dedlfix
        1. 0

          Nochmal weiter angepasst

          oxo888oxo
          1. 0
            dedlfix
            1. 0
              oxo888oxo
        2. 0
          oxo888oxo
          1. 0

            Zeilenumbrüche gehen nicht

            oxo888oxo
            1. 0
              Auge
              1. 0
                oxo888oxo
                1. 0
                  Auge
                  1. 0
                    oxo888oxo
          2. 0
            dedlfix
            1. 0
              oxo888oxo
              1. 0

                Wozu diese komplexen Einzeiler?

                Regina Schaukrug
                1. 0
                  oxo888oxo
                  1. 0
                    Regina Schaukrug
              2. 0
                dedlfix
                1. 0
                  oxo888oxo
        3. 0
          Regina Schaukrug
          1. 0
            Regina Schaukrug
      2. 1
        Regina Schaukrug
        1. 3
          Reiner Makohl
          1. 2
            Tabellenkalk
            • sicherheit
            • zu diesem forum
      3. 0
        Julius
  3. 0

    Doch noch ein Fehler: Undefined variable

    oxo888oxo
    1. 0
      dedlfix
      1. 0
        oxo888oxo
  4. 0

    Neue und endgültige Version?

    oxo888oxo
    1. 0
      dedlfix
      1. 0
        oxo888oxo
    2. 0
      Daniel Duden
      1. 1
        Julius
        • php
        • sprache
      2. 0
        oxo888oxo
  5. 0

    Script nun noch weiter reduziert

    oxo888oxo
    1. 0

      Error-Reporting

      oxo888oxo
      1. 0
        dedlfix
    2. 0
      dedlfix
      1. 0
        Regina Schaukrug
        • php
        • sicherheit
        1. 0
          dedlfix

Hallo

Das unten gezeigte Script gibt einen Fehler aus:

PHP Notice:  Undefined index: ...

Das kommt immer dann vor, wenn es keinen Referer gibt. Wie kann ich das denn verhindern.

Ich muss gestehen, dass ich selbst kein PHP beherrsche. Ich habe das Script ergoogelt.

<?php
// error404_mailer.php
// -------------------
// Reiner Makohl - www.stilkunst.de

// 1. Statuscode setzen
header("HTTP/1.0 404 Not Found");
 
// 2. Infos über den Vorgang, der den Fehler ausgelöst hat
$visitor_ipaddress = $_SERVER["REMOTE_ADDR"]; // IP-Adresse
$visitor_server = $_SERVER["SERVER_NAME"]; // Server-Name
$visitor_request = $_SERVER["REQUEST_URI"]; // Angeforderte URI
$visitor_referer = $_SERVER["HTTP_REFERER"]; // HTTP Referer-Link
$visitor_agent = $_SERVER["HTTP_USER_AGENT"]; // User Agent
$visitor_date = date("j.n.Y H:i:s e"); // Datum und Zeit

// 3. E-Mail: Seitenname festlegen
$seitenname = "example.org";  // <== Ihre Website. Anpassen!

// 4. E-Mail Sender und Empfänger festlegen
$mail_from = "mail@example.org";  // <== Sender. Anpassen!
$mail_to = "mail@example.org"; // <== Empfänger: Ihre E-Mail-Adresse!

// 5. E-Mail: Format ist HTML utf8
$mail_extras = "From: Error-Manager <$mail_from>\n";
$mail_extras .= "Content-Type: text/html; charset=utf-8\n";
$mail_extras .= "Content-Transfer-Encoding: 8bit\n";
$mail_extras .= "Content-Language: de\n";

// 6. Betreff-Zeile festlegen
$mail_subject = "Fehler 404 in der Webseite ".$seitenname;

// 7. Text der E-Mail zusammenstellen
$mail_text = "<p>Hallo Webmaster!<br><br></p>";
$mail_text .= "Auf der Seite <b>$seitenname</b> ";
$mail_text .= "ist ein Fehler 404 (Seite nicht gefunden) aufgetreten.<br></p>";
$mail_text .= "<p>Aufgerufene Adresse: ";
$mail_text .= "<b><a href='http://$visitor_server$visitor_request'>http://$visitor_server$visitor_request</a></b></p>";
$mail_text .= "<p>HTTP Referer: <b><a href='$visitor_referer'>$visitor_referer</a></b></p>";
$mail_text .= "<p>Datum: <b>$visitor_date</b></p>";
$mail_text .= "<p>IP-Adresse: <b>$visitor_ipaddress</b></p>";
$mail_text .= "<p>User Agent: <b>$visitor_agent</b></p>";

// 8. E-Mail senden
@mail($mail_to, $mail_subject, $mail_text, $mail_extras);
?>
  1. Hallo oxo888oxo,

    Lege einen default-Wert für deine Variable am Anfang des Skriptes fest.

    $visitor_referer = '';
    

    und ändere den Wert nur, wenn der entsprechende Eintrag im Array existiert.

    if (isset($_SERVER["REQUEST_URI"]) $visitor_referer = $_SERVER["REQUEST_URI"];
    

    Bis demnächst
    Matthias

    --
    Dieses Forum nutzt Markdown. Im Wiki erhalten Sie Hilfe bei der Formatierung Ihrer Beiträge.
    1. Meinst Du das quasi so?

      // 2. Infos über den Vorgang, der den Fehler ausgelöst hat
      $visitor_ipaddress = $_SERVER["REMOTE_ADDR"]; // IP-Adresse
      $visitor_server = $_SERVER["SERVER_NAME"]; // Server-Name
      $visitor_request = $_SERVER["REQUEST_URI"]; // Angeforderte URI
      $visitor_referer = 'Nix';
      $visitor_referer = $_SERVER["HTTP_REFERER"]; // HTTP Referer-Link
      $visitor_agent = $_SERVER["HTTP_USER_AGENT"]; // User Agent
      $visitor_date = date("j.n.Y H:i:s e"); // Datum und Zeit
      
      1. Hallo oxo888oxo,

        Meinst Du das quasi so?

        Ja. Und das kann dir bei allen Einträgen passieren, nicht nur beim Referer.

        Bis demnächst
        Matthias

        --
        Dieses Forum nutzt Markdown. Im Wiki erhalten Sie Hilfe bei der Formatierung Ihrer Beiträge.
        1. Tach!

          $visitor_referer = 'Nix';
          $visitor_referer = $_SERVER["HTTP_REFERER"]; // HTTP Referer-Link
          

          Meinst Du das quasi so?

          Ja.

          ... aber nur quasi. Denn so wie der Code oben steht, ist es sinn- und wirkungslos. Der Zugriff auf das Array-Element in $_SERVER darf ja nur erfolgen, wenn es da ist, wozu aber seine Existenz geprüft werden muss. Und der Code da oben ist wieder nur ein unbedingter Zugriff, so wie er bereits im Code war.

          $mail_text .= "<b><a href='http://$visitor_server$visitor_request'>http://$visitor_server$visitor_request</a></b></p>";
          
          $mail_text .= "<p>HTTP Referer: <b><a href='$visitor_referer'>$visitor_referer</a></b></p>";
          
          $mail_text .= "<p>User Agent: <b>$visitor_agent</b></p>";
          

          Und das sind drei Sicherheitslücken, die beliebigen Code in die Mail einfügen lassen. Referer und User-Agent sind zwei Texte, die nicht nur vom Browser vorgegeben sind, sondern beliebig manipuliert werden können. Bei den anderen Werten müsste man eigentlich adäquat verfahren, aber die sollten eigentlich manipulationssicher sein. Zumindest in der jetzigen Form des Scripts. Wenn du das noch änderst, zum Beispiel dne Absender-Adresse beim Anwender zu erfragen statt einen Wert fest vorzugeben, dann muss da auch noch was getan werden, wenn du keine ausnutzbare Spamschleuder bauen möchtest. So werden die Sicherheitslücken entschärft:

          $mail_text .= '<b><a href="http://' + $visitor_server + urlencode($visitor_request) + '">http://' + $visitor_server + htmlspecialchars($visitor_request) + '</a></b></p>';
          
          $mail_text .= '<p>HTTP Referer: <b><a href="' . htmlspecialchars($visitor_referer) + '">$visitor_referer</a></b></p>';
          
          $mail_text .= '<p>User Agent: <b>' + htmlspecialchars($visitor_agent) + '</b></p>';
          

          dedlfix.

          1. Hallo

            So werden die Sicherheitslücken entschärft:

            $mail_text .= '<b><a href="http://' + $visitor_server + urlencode($visitor_request) + '">http://' + $visitor_server + htmlspecialchars($visitor_request) + '</a></b></p>';
            
            $mail_text .= '<p>HTTP Referer: <b><a href="' . htmlspecialchars($visitor_referer) + '">$visitor_referer</a></b></p>';
            
            $mail_text .= '<p>User Agent: <b>' + htmlspecialchars($visitor_agent) + '</b></p>';
            

            Naja, fast. Die Zeichenkettenverkettung – oder neudeutsch „string concatenation“ – wie auch die kontextgerechte Maskierung [1] sollte in PHP doch bitte durchgängig und durchgängig nach den PHP-Regeln erfolgen. ;-)

            $mail_text .= '<b><a href="http://' . $visitor_server . urlencode($visitor_request) . '">http://' . $visitor_server . htmlspecialchars($visitor_request) . '</a></b></p>';
            
            $mail_text .= '<p>HTTP Referer: <b><a href="' . htmlspecialchars($visitor_referer) . '"> ' . htmlspecialchars($visitor_referer) . '</a></b></p>';
            
            $mail_text .= '<p>User Agent: <b>' . htmlspecialchars($visitor_agent) . '</b></p>';
            

            Tschö, Auge

            --
            Wenn man ausreichende Vorsichtsmaßnahmen trifft, muss man keine Vorsichtsmaßnahmen mehr treffen.
            Toller Dampf voraus von Terry Pratchett

            1. Wo kommt eigentlich die Variable $visitor_server her? Die habe ich, wie sie war, unbehandelt gelassen. ↩︎

            1. Tach!

              So werden die Sicherheitslücken entschärft:

              Naja, fast. Die Zeichenkettenverkettung – oder neudeutsch „string concatenation“ – wie auch die kontextgerechte Maskierung [^1] sollte in PHP doch bitte durchgängig und durchgängig nach den PHP-Regeln erfolgen. ;-)

              Oh ja, das + ist nicht PHP-Syntax, . muss es stattdessen sein.

              Wo kommt eigentlich die Variable $visitor_server her? Die habe ich, wie sie war, unbehandelt gelassen.

              Daher: $visitor_server = $_SERVER["SERVER_NAME"];

              Der Servername kommt aus dem DNS und sollte eigentlich sicher sein. Normalerweise würde ich keine Werte von der Behandlung auslassen, aber hier habe ich Risiko gegen Aufwand geschätzt und nur die mit erhöhtem Risiko erwähnt.

              dedlfix.

              1. Daher: $visitor_server = $_SERVER["SERVER_NAME"];

                Der Servername kommt aus dem DNS und sollte eigentlich sicher sein.

                Das mag landläufige Meinung sein, "landläufig" ist hier aber der "Holzweg".

                $_SERVER['SERVER_NAME'] == Name, welcher in der Serverkonfiguration hinterlegt ist. Kann der beim Start des Apache Webservers nicht in eine IP-Adresse aufgelöst werden sich nur eine Warnung bzw. Notiz im error-log und/oder in der Konsole finden. Das war es dann auch.

                $_SERVER['HTTP_HOST'] == Name, des Servers, wie er vom Client im Request-Header an den Server geschickt wird. Selbst bei einem normalen Client kann der falsch sein, denn ich kann

                192.168.0.111 www.example.com 
                

                in die Hosts-Datei schreiben (oder meinem Client erzählen 192.168.0.111:80 sei der Proxy oder ihm vormachen, dass sei die gecachte IP, ..., oder ich nehme für den Spaß gleich netcat)

                Mit DNS hat das alles nichts zu tun. $_SERVER["SERVER_NAME"] sogar überhaupt nichts. Ob man dem Apache auch völligen Unsinn als HTTP_HOST unterschieben kann habe ich noch nicht getestet. Wozu auch.

                1. Tach!

                  $_SERVER['HTTP_HOST'] == Name, des Servers, wie er vom Client im Request-Header an den Server geschickt wird. Selbst bei einem normalen Client kann der falsch sein, denn ich kann

                  192.168.0.111 www.example.com 
                  

                  in die Hosts-Datei schreiben (oder meinem Client erzählen 192.168.0.111:80 sei der Proxy oder ihm vormachen, dass sei die gecachte IP, ...)

                  Ja, dann landet der Request aber nicht bei unserem PHP-Sript sondern beim Default-VHost oder einem anderen VHost, falls der auf dem Server existiert.

                  HTTP_HOST spielt im vorliegenden Script aber keine Rolle.

                  Mit DNS hat das alles nichts zu tun. $_SERVER["SERVER_NAME"] sogar überhaupt nichts. Ob man dem Apache auch völligen Unsinn als HTTP_HOST unterschieben kann habe ich noch nicht getestet. Wozu auch.

                  Na gut, dann kein DNS sondern Serverkonfiguration, aber auch nicht per Request manipulierbar. Wenn doch, oder wenn da was komisches drinsteht, hat man ein ganz anderes Problem als ein manipulierbares Mailer-Script.

                  dedlfix.

                  1. Ja, dann landet der Request aber nicht bei unserem PHP-Sript sondern beim Default-VHost oder einem anderen VHost, falls der auf dem Server existiert.

                    Ich weiß das. Aber oft haben Leute eigene Server gemietet, die sowas weder brauchen noch verwalten können und warum sollten die etwas anderes als einen Default-Host haben?

                    HTTP_HOST spielt im vorliegenden Script aber keine Rolle.

                    Um den kleinen Unterschied zwischen Bubli und Madli zu erklären muss man den beides zeigen und erläutern. Nicht dass jemand auf die Idee kommt, dann eben $_SERVER['HTTP_HOST'] zu nehmen und zu erwarten dass der dann stimmt...

    2. @@Matthias Apsel

      $visitor_referer = '';
      
      if (isset($_SERVER["REQUEST_URI"]) $visitor_referer = $_SERVER["REQUEST_URI"];
      

      Klammer zu!

      Oder in kurz:

      $visitor_referer = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
      

      Da es in den Strings nichts zu parsen gibt, hab ich die doppelten Anführungszeichen auch gleich mal durch einfache ersetzt.

      BTW, In JavaScript kann man das auch mit ||-Operator machen. In PHP ist das aber ein boolescher Operator.

      LLAP 🖖

      --
      “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
      1. Tach!

        $visitor_referer = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
        

        BTW, In JavaScript kann man das auch mit ||-Operator machen. In PHP ist das aber ein boolescher Operator.

        Der Vergleich hinkt. In Javascript würde man das so schreiben können, in PHP hingegen nicht (ungestraft):

        foo = bar['foo'] || 'defaultwert';
        

        Javascript erzeugt keinen Fehler beim Zugriff auf nicht vorhandenes Array-Element oder eine Objekteigenschaft. Selbst wenn PHP nicht true/false sondern den Wert des einen oder anderen Teilausdrucks zurückgeben würde, würde ein Konstrukt wie dieses immer noch eine "Undefined index"-Notice werfen.

        dedlfix.

    3. Moin,

      if (isset($_SERVER["REQUEST_URI"]) $visitor_referer = $_SERVER["REQUEST_URI"];
      

      Wer öfter mit diesem Array (Serverumgebung) arbeitet, Tipp: Binde es an eine Klasse die sicherstellt, dass jeder lesende Zugriff auf einen Schlüssel einen definierten Wert liefert, z.B. einen Leerstring.

      MfG

      PS: Warnungen ausschalten ist natürlich keine Lösung. Eher sollte jede Warnung eine Exception werfen damit sie gleich bemerkt wird! Und siehe da, im error_log landen nur noch von Gott gewollte Katastrophenmeldungen ;)

      1. Tach!

        if (isset($_SERVER["REQUEST_URI"]) $visitor_referer = $_SERVER["REQUEST_URI"];
        

        Wer öfter mit diesem Array (Serverumgebung) arbeitet, Tipp: Binde es an eine Klasse die sicherstellt, dass jeder lesende Zugriff auf einen Schlüssel einen definierten Wert liefert, z.B. einen Leerstring.

        Beispiel bitte in PHP, wie man diese erwähnte Bindung hinbekommt.

        PS: Warnungen ausschalten ist natürlich keine Lösung. Eher sollte jede Warnung eine Exception werfen damit sie gleich bemerkt wird!

        Erläutere bitte, wie man unter PHP dazu kommt, dass eine Warnung eine Exception wirft.

        dedlfix.

  2. Hallo

    Das unten gezeigte Script gibt einen Fehler aus:

    PHP Notice:  Undefined index: ...
    

    Das kommt immer dann vor, wenn es keinen Referer gibt.

    Das ist klar. Der Browser sendet keinen Referer wenn es keinen gibt, weil die Seite direkt aufgerufen wurde oder der Besitzer das abgeschaltet hat. Dann ist $_SERVER["HTTP_REFERER"] nicht besetzt und PHP wirft Dir eine Notiz vor die Füße. Lösungen sind klassisch:

    if ( isset( $_SERVER["HTTP_REFERER"] ) ) {
        $visitor_referer = $_SERVER["HTTP_REFERER"]; // HTTP Referer-Link
    } else {
        $visitor_referer = false;
    }
    

    weniger klassisch hast Du bereits weiter unten das unschöne hier abgeschrieben:

    @mail($mail_to, $mail_subject, $mail_text, $mail_extras);
    

    Das '@' unterdrückt nämlich Notizen. Das Error-Reporting sollte man anders steuern.

    Was Du machst ist sehr gefährlich:##

    1. Allein schon, dass Du das Mail HTML-formatiert versendest, ist ein grober Fehlgriff, weil unnötig. Und das provoziert weitere Gefahren, die sich auch als ausnutzbar erweisen:

    2. Das hier ist echt gefährlich:

    $mail_text .= "<p>User Agent: <b>$visitor_agent</b></p>"; 
    

    Hier kann ich (und jeder kleine Chinese) Dir wunderbare Skripte oder eine, sogar mehrere beliebige URLs zu "Grafiken" senden. Etwas wie "<img src="http://192.168.1.0/action.cgi?action=setpassword&password=strastwuite"> Da brauchst Du weder Alexa noch ein Kleinkind um mit Deiner Kreditkarte Leistungen zu bezahlen, die Du gar nicht willst. Außerdem wird Dein DSL- oder Kabelrouter dann möglicherweise kostenlos von einem russischen Dienstleister konfiguriert und überwacht, was dazu führt, dass der Webserver Deiner Bank plötzlich in ein merkwürdiges Rechenzentrum umzieht und sich andere Gedanken um Deine Geldanlagen machen.

    Dieses Problem besteht bei allen Daten, welche der User-Agent sendet. Also auch beim Referer, beim HTTP_USER_AGENT, sogar bei der URL.

    Derjenige, der das Skript online gestellt hat, ist Künstler, kein Techniker. Das Skript ist "bad, bad bad"!

    Nochwas: Bei jedem 404er (NOT FOUND) ein Mail zu bekommen nervt. Das ist das beste daran: Den Mist wirst Du schnell wieder abschalten, was die Gefahren mindert.

    1. Hallo Regina Schaukrug,

      Nochwas: Bei jedem 404er (NOT FOUND) ein Mail zu bekommen nervt.

      @oxo888oxo Noch eine kleine Ergänzung: Du brauchst dir dafür keine E-Mails senden, 404er werden normalerweise vom Webserver geloggt, da müsstest du halt mal in die Konfiguration des Webservers schauen, oder bei deinem Hoster nachfragen. Ab und an sollte man halt einen Blick in die Logdateien werfen...

      Gruß
      Julius

    2. Hallo

      Was Du machst ist sehr gefährlich:##

      OK vielen Dank für Deine Warnung und natürlich auch für die Antworten der anderen. Ich habe das Script nun mal weiter angepasst (siehe unten). Ist es so schon besser? Oder sollte ich noch etwas anpassen der Sicherheit wegen?

      <?php
      // error404_mailer.php
      // -------------------
      // Reiner Makohl - www.stilkunst.de
      
      // 1. Statuscode setzen
      // header("HTTP/1.0 404 Not Found");
       
      // 2. Infos über den Vorgang, der den Fehler ausgelöst hat
      $visitor_ipaddress = $_SERVER["REMOTE_ADDR"]; // IP-Adresse
      $visitor_server = $_SERVER["SERVER_NAME"]; // Server-Name
      $visitor_request = $_SERVER["REQUEST_URI"]; // Angeforderte URI
      $visitor_referer = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
      $visitor_agent = $_SERVER["HTTP_USER_AGENT"]; // User Agent
      $visitor_date = date("j.n.Y H:i:s e"); // Datum und Zeit
      
      // 3. E-Mail Sender und Empfänger festlegen
      $mail_from = "mail@example.org";  // <== Sender. Anpassen!
      $mail_to = "mail@example.org"; // <== Empfänger: Ihre E-Mail-Adresse!
      
      // 4. E-Mail: Format ist HTML utf8
      $mail_extras = "From: Error-Manager <$mail_from>\n";
      $mail_extras .= "Content-Type: text/plain; charset=utf-8\n";
      $mail_extras .= "Content-Transfer-Encoding: 8bit\n";
      $mail_extras .= "Content-Language: de\n";
      
      // 5. Betreff-Zeile festlegen
      $mail_subject = "Fehler 404";
      
      // 6. Text der E-Mail zusammenstellen
      $mail_text .= "Auf der Seite https://spaceart.de ist ein Fehler 404 aufgetreten.\n";
      $mail_text .= "Aufgerufene Adresse: http://" . $visitor_server . htmlspecialchars($visitor_request) . "\n";
      $mail_text .= "HTTP Referer: " . htmlspecialchars($visitor_referer) . "\n\n";
      $mail_text .= "Datum: $visitor_date\n";
      $mail_text .= "IP-Adresse: $visitor_ipaddress\n";
      $mail_text .= "User Agent: " . htmlspecialchars($visitor_agent);
      
      // 7. E-Mail senden
      @mail($mail_to, $mail_subject, $mail_text, $mail_extras);
      ?>
      
      1. Tach!

        Ich habe das Script nun mal weiter angepasst (siehe unten). Ist es so schon besser? Oder sollte ich noch etwas anpassen der Sicherheit wegen?

        $mail_extras .= "Content-Type: text/plain; charset=utf-8\n";
        
        $mail_text .= "Aufgerufene Adresse: http://" . $visitor_server . htmlspecialchars($visitor_request) . "\n";
        $mail_text .= "HTTP Referer: " . htmlspecialchars($visitor_referer) . "\n\n";
        $mail_text .= "User Agent: " . htmlspecialchars($visitor_agent);
        

        Wenn du nun auf Plain-Text umgestiegen bist, brauchst du kein htmlspecialchars() mehr. htmlspecialchars() sorgt dafür, dass Daten im HTML-Kontext nicht als HTML-Tags erkannt werden. Plain-Text enthält keinen ausführbaren Code und dafür muss man keine weiteren Sicherheitsmaßnahmen ergreifen - solange man ihn als Plain-Text behandelt.

        dedlfix.

        1. solange man ihn als Plain-Text behandelt.

          Damit haben leider so manche Mailprogramme (mindestens ein paar eines bestimmten Herstellers aus Redmond) Probleme. Die finden <b>Fett</b> und stellen das Mail erst mal als HTML dar.

          1. Tach!

            solange man ihn als Plain-Text behandelt.

            Damit haben leider so manche Mailprogramme (mindestens ein paar eines bestimmten Herstellers aus Redmond) Probleme. Die finden <b>Fett</b> und stellen das Mail erst mal als HTML dar.

            Das kann nicht zum Problem desjenigen gemacht werden, der Plaintext angibt und ihn genauso meint. Ein solches Problem sehe ich auch nicht als lösbar an. Für welchen Kontext soll man denn schreiben, wenn das Ziel nach Gutdünken irgendeinen anderen als den angegebenen interpretiert? Das ist dann auch Aufgabe des Zielsystems da keine Sicherheitslücken einzubauen, wo eigentlich gar keine waren.

            dedlfix.

            1. Das kann nicht zum Problem desjenigen gemacht werden, der Plaintext angibt und ihn genauso meint.

              Soso. Weil nicht sein kann, was nicht sein soll, holen sich Benutzer von $arSchlechteMailclients (die eben trotz content-type: text/plain den Text als HTML interpretieren) die Pest an den Hals.

              Das muss halt in diesem Fall der Empfänger entscheiden. Der installiert ja auch das Skript.

              1. Hallo

                Das kann nicht zum Problem desjenigen gemacht werden, der Plaintext angibt und ihn genauso meint.

                Soso. Weil nicht sein kann, was nicht sein soll, holen sich Benutzer von $arSchlechteMailclients (die eben trotz content-type: text/plain den Text als HTML interpretieren) die Pest an den Hals.

                Ja, was den sonst? Auf wieviele mögliche Fehler in Programmen, die sich vielleicht auch noch gegenteilig auswirken, willst du Rücksicht nehmen? Und wieso „Pest“? Dein Szenario geht von HTML-Tags in einer Plain-Text-Email aus, die diesen Bug triggern. Da es hier um ein, wenn auch nicht vom OP, so doch selbst geschriebenes Skript, mit dem die Email generiert wird, geht, ist das ein vermeidbarer Fehler.

                Dass der Bug in „manche[n] Mailprogramme (mindestens ein paar eines bestimmten Herstellers aus Redmond)“ auch von Emails aus ganz anderen Quellen, auf die man als Benutzer des Emailprogramms keinerlei Einfluss hat, getriggert werden kann, sei mal dahingestellt. Soll man deshalb nun keine Plain-Text-Emails versenden oder annehmen? Oder ist es nicht so, dass der Hersteller der Software – unabhängig von der tatsächlichen Umsetzung – mit der Behebung des Fehlers dran ist?

                Das muss halt in diesem Fall der Empfänger entscheiden. Der installiert ja auch das Skript.

                Nicht nur das Skript, auch das Emailprogramm.

                Tschö, Auge

                --
                Wenn man ausreichende Vorsichtsmaßnahmen trifft, muss man keine Vorsichtsmaßnahmen mehr treffen.
                Toller Dampf voraus von Terry Pratchett
        2. Wenn du nun auf Plain-Text umgestiegen bist, brauchst du kein htmlspecialchars() mehr. htmlspecialchars() sorgt dafür, dass Daten im HTML-Kontext nicht als HTML-Tags erkannt werden. Plain-Text enthält keinen ausführbaren Code und dafür muss man keine weiteren Sicherheitsmaßnahmen ergreifen - solange man ihn als Plain-Text behandelt.

          Ah alles klar. Danke Dir.

    3. Herzlichen Dank für die Kommentare zu diesem Skript, dass von meiner Seite stammt.

      Selbstverständlich freue ich mich über jede konkrete Berichtigung oder Verbesserung des Skripts, vor allem, wenn es darum geht, potentielle Gefahren zu verhindern.

      Gerne übernehme ich dafür den abgewandelten Code mit Hinweis auf den jeweiligen Autor.

      Ein paar Anmerkungen zum praktischen Einsatz, die ggf. für Verbesserungsvorschläge dienlich sind:

      Vorweg: Wie auf der zugehörigen Seite vermerkt, ist das Skript nicht ausgereift, sondern nur ein Gerüst, ein Vorschlag für die Weiterentwicklung, Verbesserung und Anpassung an individuelle Bedürfnisse (was ja hier auch gerade diskutiert wird).

      1. Das Skript ist nicht an ein Formular gekoppelt. Es gibt keine Eingabefelder und keinerlei HTML-Code, der Prozess läuft völlig unsichtbar für den Benutzer.
      2. Es dient in der Praxis dazu, Link-Fehler innerhalb der Site zu entdecken. Dies ist sinnvoll und hilfreich, weil die Site faktisch tausende interner Links enthält (statisch gesetzt und großteils dynamisch erzeugt).
      3. Dazu sind der fehlerhafte Link (URL) und der Referrer als Infos unumgänglich.
      4. Tatsächlich wird der User-Agent nicht gebraucht, ebenso wenig die IP-Adresse (braucht nicht weiter betrachtet werden).
      5. Die Fehlerunterdrückung dient dazu, keinerlei Hinweis im Browser auf die Background-Routine zu liefern (jede bessere Methode wird gern genommen). Der Benutzer erhält ausschließlich (unabhängig vom Skript) wie üblich eine Error-Page (NOT FOUND), wenn der Fehler durch fehlerhaften Aufruf über die Adresseingabe oder durch einen fehlerhaften Link auf einer Seite ausgelöst wurde.
      6. Als Nebeneffekt wird durchaus sichtbar, welche Seiten oder Module gesucht werden, über die offensichtlich Angriffe auf die Site ausgeführt werden sollten.
      7. Sehr viel wichtiger sind allerdings Benachrichtigungen, die fehlerhafte Links innerhalb einer einzelnen Seite melden und für die der Benutzer nicht verantwortlich ist (z. B. Link auf Ressource falsch berechnet, Bild nicht gefunden, etc.).

      In der Praxis erlaubt das (modifizierte) Skript effiziente Wartungsarbeiten. Eine verbesserte Version wäre daher auch für Dritte nützlich, meine ich.

      Solltet Ihr jedoch zu dem Schluss kommen, dass es unrettbar "bad,bad,bad" ist, stellt es kein Problem dar, die Publikation zu löschen, um Mißbrauch oder gar Schäden nicht zu fördern.

      Reiner

      1. Tach!

        Solltet Ihr jedoch zu dem Schluss kommen, dass es unrettbar "bad,bad,bad" ist, stellt es kein Problem dar, die Publikation zu löschen, um Mißbrauch oder gar Schäden nicht zu fördern.

        Also, ich bin nicht dieser Meinung. Man kann alles so umschreiben, dass es den Umständen nach sicher wird. Es sieht jetzt auch nicht grundsätzlich so aus, als ob es weniger Aufwand wäre, es neu zu schreiben, als die Fehler zu beseitigen. Der wichtigste Punkt ist die kontextgerechte Behandlung der Werte. Man muss sich dann auch keine Gedanken machen, was woher kommt, denn sobald man irgendwas in den Zielkontext so einfügt, dass es als Daten interpretiert wird, hat man keine Injection-Lücke mehr.

        Allgemeine Hinweise zur Verbesserung:

        Es ist nicht sinnvoll, Werte aus $_SERVER (oder $_GET oder $_POST) 1:1 in andere Variablen umzukopieren. Man gewinnt dadurch nur wenig (kleiner Komfort beim Einfügen in ""-Strings), hat aber eine Indirektion drin und eine Variable mehr zu pflegen. Wenn man den Wert anschließend nur ein einziges Mal braucht, hat man sogar effektiv mehr Code geschrieben, als wenn man den $_SERVER['irgendwas'] direkt am Ziel notiert hätte.

        Statt vieler Zeilen mit $mail_text .= kann man die Heredoc- oder die Nowdoc-Syntax verwenden (siehe Handbuch zu Strings). Man kann dabei auch Variablen (sowie komplexe Array-Zugriffe) einbauen, allerdings keine Rückgabewerte von Funktionsaufrufen. Diese braucht man aber, wenn man htmlspecialchars() oder eine andere Maskierfunktion für den Ziel-Kontext verwenden muss.

        dedlfix.

        1. Ich habe es nun noch etwas weiter angepasst. Habt Ihr noch weitere Verbesserungsvorschläge?

          <?php
          // error404_mailer.php
          // -------------------
          // Reiner Makohl - www.stilkunst.de
          
          // 1. Statuscode setzen
          // header("HTTP/1.0 404 Not Found");
           
          // 2. Referer ermitteln
          $visitor_referer = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
          
          // 3. E-Mail Sender und Empfänger festlegen
          $mail_from = "mail@example.org";  // <== Sender. Anpassen!
          $mail_to = "mail@example.org"; // <== Empfänger: Ihre E-Mail-Adresse!
          
          // 4. E-Mail: Format ist HTML utf8
          $mail_extras = "From: Error-Manager <$mail_from>\n";
          $mail_extras .= "Content-Type: text/plain; charset=utf-8\n";
          $mail_extras .= "Content-Transfer-Encoding: 8bit\n";
          $mail_extras .= "Content-Language: de\n";
          
          // 5. Betreff-Zeile festlegen
          $mail_subject = "Fehler 404";
          
          // 6. Text der E-Mail zusammenstellen
          $mail_text .= "Aufgerufene Adresse: https://" . $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"] . "\n";
          $mail_text .= "HTTP Referer: $visitor_referer\n\n";
          $mail_text .= "Datum: " . date("j.n.Y H:i:s e") . "\n";
          $mail_text .= "IP-Adresse: " . $_SERVER["REMOTE_ADDR"] . "\n";
          $mail_text .= "User Agent: " . $_SERVER["HTTP_USER_AGENT"];
          
          // 7. E-Mail senden
          @mail($mail_to, $mail_subject, $mail_text, $mail_extras);
          ?>
          
          1. Tach!

            Habt Ihr noch weitere Verbesserungsvorschläge?

            Nichts weiter, außer einem Punkt.

            $mail_text .= "Aufgerufene Adresse: https://" . $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"] . "\n";
            

            Da steht https:// als fester Wert drin, unabhängig davon, wie der Request wirklich kam. Wenn es lediglich darum geht, den angefragten Path/Seitennamen anzuzeigen, braucht es diesen Vorsatz eigentlich nicht. Es sein denn, du willst darauf klicken können, wozu der Mailer das als Adresse erkennen muss, um es als Link zu präsentieren. Wenn du einen anderen Anwendungsfall dafür hast, ist das natürlich auch legitim.

            dedlfix.

            1. Da steht https:// als fester Wert drin, [...] Es sein denn, du willst darauf klicken können, wozu der Mailer das als Adresse erkennen muss, um es als Link zu präsentieren.

              Genau das ist der Grund :-)

        2. Es ist nicht sinnvoll, Werte aus $_SERVER (oder $_GET oder $_POST) 1:1 in andere Variablen umzukopieren. Man gewinnt dadurch nur wenig (kleiner Komfort beim Einfügen in ""-Strings), hat aber eine Indirektion drin und eine Variable mehr zu pflegen. Wenn man den Wert anschließend nur ein einziges Mal braucht, hat man sogar effektiv mehr Code geschrieben, als wenn man den $_SERVER['irgendwas'] direkt am Ziel notiert hätte.

          In unten gezeigter Version habe ich ja noch die $visitor_referer Variable drin. Die möchte ich gerne noch rauswerfen. Aber ich bekomme das leider nicht hin.

          Ich möchte in der Zeile:

          $mail_text .= "HTTP Referer: $visitor_referer\n\n";
          

          nicht die Variable $visitor_referer verwenden, sondern die "Dinger" aus:

          $visitor_referer = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
          

          direkt einfügen.

          Ich habe es so probiert:

          $mail_text .= "HTTP Referer: " . isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '' . "\n\n";
          

          aber dann werden die beiden Zeilenumbrüche am Ende ignoriert.

          Wo ist denn da der Fehler?

          1. Sorry ich meinte natürlich diese Zeile:

            $mail_text .= "HTTP Referer: " . isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '' . "\n\n";
            

            Da werden am En de die beiden Zeilenumbrüche nicht ausgeführt. Und ich verstehe nicht, warum.

            1. Hallo

              $mail_text .= "HTTP Referer: " . isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '' . "\n\n";
              

              Da werden am En de die beiden Zeilenumbrüche nicht ausgeführt. Und ich verstehe nicht, warum.

              Die Zeile funktioniert rechts des Gleicheitszeichens folgendermaßen. Du beginnst mit einem Stück Text ("HTTP Referer: "). Nach dem Verkettungszeichen folgt der ternäre Operator mit der Entscheidung, ob $_SERVER['HTTP_REFERER'] oder eine leere Zeichenkette ausgegeben werden soll (FRAGE ? ANTWORT-JA : ANTWORT-NEIN). Deine beiden Zeilenumbrüche sind nun Bestandteil des Abschnitts mit der abschlägigen Antwort (: '' . "\n\n";). Gibt es keinen Referer, werden auch die zwei Umbrüche eingefügt.

              Du kannst die Umbrüche zum Bestandteil der Ausgabe des Referers machen (? $_SERVER['HTTP_REFERER'] . "\n\n" :), du kannst sie auch in einer eigenen, auf diese Zeile folgenden, Anweisung anfügen. Im Übrigen brauchst du keine Verkettung von nichts (leere Zeichenkette) mit den Umbrüchen.

              // Zeilenumbrüche in beiden möglichen Ausgaben
              $mail_text .= "HTTP Referer: " . isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] . "\n\n" : "\n\n";
              
              // Zeilenumbruch in einer eigenen Anweisung nach dem ternären Operator
              $mail_text .= "HTTP Referer: " . isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
              $mail_text .= "\n\n";
              
              // Auslassung der negativen und leeren Ausgabe
              if (isset($_SERVER['HTTP_REFERER'])) $mail_text .= "HTTP Referer: " . $_SERVER['HTTP_REFERER'];
              $mail_text .= "\n\n";
              

              Das sind ein paar der Möglichkeiten.

              Tschö, Auge

              --
              Wenn man ausreichende Vorsichtsmaßnahmen trifft, muss man keine Vorsichtsmaßnahmen mehr treffen.
              Toller Dampf voraus von Terry Pratchett
              1. Hallo Auge

                Ich hatte es jetzt so gemacht, wie mir vorhin hier jemand geraten hatte:

                $mail_text .= "HTTP Referer: " . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '') . "\n\n";
                

                Und da funktioniert es auch in beiden Fällen mit den Zeilenumbrüchen.

                1. Hallo

                  Ich hatte es jetzt so gemacht, wie mir vorhin hier jemand geraten hatte:

                  Das hatte ich zwar schon gelesen, wollte aber noch einmal auf die Gründe für die fehlenden Umbrüche eingehen.

                  $mail_text .= "HTTP Referer: " . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '') . "\n\n";
                  

                  Und da funktioniert es auch in beiden Fällen mit den Zeilenumbrüchen.

                  Richtig. Nun ist die ganze Operation durch die Klammerung vom umgebenden String entkoppelt. Du hast jetzt also einen String, dann die Operation und erst nach deren Abarbeitung wird, unabhängig von der Operation selbst, der String mit den Umbrüchen wieder aufgenommen.

                  $variable = "String" . (Operation mit Ja- und Nein-Antwort) . "String";
                  

                  Tschö, Auge

                  --
                  Wenn man ausreichende Vorsichtsmaßnahmen trifft, muss man keine Vorsichtsmaßnahmen mehr treffen.
                  Toller Dampf voraus von Terry Pratchett
                  1. Richtig. Nun ist die ganze Operation durch die Klammerung vom umgebenden String entkoppelt. Du hast jetzt also einen String, dann die Operation und erst nach deren Abarbeitung wird, unabhängig von der Operation selbst, der String mit den Umbrüchen wieder aufgenommen.

                    Jo alles klar. Ich habe das nun auch begriffen. Danke Dir für Deine Erklärungen!

          2. Tach!

            In unten gezeigter Version habe ich ja noch die $visitor_referer Variable drin. Die möchte ich gerne noch rauswerfen.

            Die kann man drinlassen, denn da wird ja was berechnet, und dafür eine Variable zu verwenden ist kein schlechter Stil.

            $mail_text .= "HTTP Referer: " . isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '' . "\n\n";
            

            aber dann werden die beiden Zeilenumbrüche am Ende ignoriert.

            Wo ist denn da der Fehler?

            Klammern setzen. Vor isset die öffnende und nach '' die schließende. Ansonsten wirkt die Operator-Rangfolge anders als du möchtest.

            dedlfix.

            1. Klammern setzen. Vor isset die öffnende und nach '' die schließende. Ansonsten wirkt die Operator-Rangfolge anders als du möchtest.

              Ahhhh :-) Habs gemacht nun so:

              $mail_text .= "HTTP Referer: " . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '') . "\n\n";
              

              Nun bekomme ich aber wieder die Ursprüngliche Fehlermeldung:

              PHP Notice:  Undefined index: HTTP_REFERER in ...
              

              Hab ich mir die Zeile mit dem Referer nun irgendwie doch kaputt gebaut?

              1. Hab ich mir die Zeile mit dem Referer nun irgendwie doch kaputt gebaut?

                Männer! Warum denn immer alles in eine Zeile schreiben und dann Probleme mit den Debuggen haben? Es gibt die ENTER-Taste und das Semikolon, welches einen Befehl beendet!

                $mail_text = "HTTP Referer: "
                . ( isset( $_SERVER['HTTP_REFERER'] ) && $_SERVER['HTTP_REFERER'] )
                        ? $_SERVER['HTTP_REFERER']
                        : 'not given'
                . PHP_EOL . PHP_EOL;
                

                kommt die Meldung für die Zeile ? $_SERVER['HTTP_REFERER']

                1. Hallo Regina

                  Meinst Du es so?

                      <?php
                        // E-Mail Sender und Empfänger festlegen
                        $mail_from = "mail@example.org";  // <== Sender. Anpassen!
                        $mail_to = "mail@example.org"; // <== Empfänger: Ihre E-Mail-Adresse!
                  
                        // E-Mail: Format ist HTML utf8
                        $mail_extras = "From: Error-Manager <$mail_from>\n";
                        $mail_extras .= "Content-Type: text/plain; charset=utf-8\n";
                        $mail_extras .= "Content-Transfer-Encoding: 8bit\n";
                        $mail_extras .= "Content-Language: de\n";
                  
                        // Betreff-Zeile festlegen
                        $mail_subject = "Fehler 404";
                  
                        // Text der E-Mail zusammenstellen
                        $mail_text = "Aufgerufene Adresse: https://" . $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"] . "\n";
                        $mail_text = "HTTP Referer: "
                        . ( isset( $_SERVER['HTTP_REFERER'] ) && $_SERVER['HTTP_REFERER'] )
                          ? $_SERVER['HTTP_REFERER']
                          : 'not given'
                        . PHP_EOL . PHP_EOL;
                        $mail_text .= "Datum: " . date("j.n.Y H:i:s e") . "\n";
                        $mail_text .= "IP-Adresse: " . $_SERVER["REMOTE_ADDR"] . "\n";
                        $mail_text .= "User Agent: " . $_SERVER["HTTP_USER_AGENT"];
                  
                        // E-Mail senden
                        @mail($mail_to, $mail_subject, $mail_text, $mail_extras);
                      ?>
                  
                  1. Hallo Regina

                    Meinst Du es so?

                    ...

                    Viel zu kompliziert. Das Skript hat einen engen Anwendungszweck. Da kann man dem Anwender zumuten, das Skript zu testen und, wenn es läuft, eine Zeile nach Anleitung auszukommentieren und - ausnahmsweise - auf das Error-Reporting, ganz besonders aber die Fehleranzeige im HTML verzichten.

              2. Tach!

                $mail_text .= "HTTP Referer: " . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '') . "\n\n";
                

                Nun bekomme ich aber wieder die Ursprüngliche Fehlermeldung:

                PHP Notice:  Undefined index: HTTP_REFERER in ...
                

                Hab ich mir die Zeile mit dem Referer nun irgendwie doch kaputt gebaut?

                Ist es wirklich diese Zeilennummer? Denn die kann den Fehler nicht bringen, so wie sie hier notiert ist.

                dedlfix.

                1. Ist es wirklich diese Zeilennummer? Denn die kann den Fehler nicht bringen, so wie sie hier notiert ist.

                  Ja stimmt. Nun kommt wohl keine Fehlermeldung mehr. Ich hatte mich da vorhin wohl doch vertan, denke ich. Ich werde das aber noch weiter beobachten.

        3. <?php
          error_reporting( 0 ); ini_set( 'display_errors', 0 );
          // Debug: (Nächste Zeile auskommentieren um Fehlermeldungen zu unterdrücken.)
          error_reporting( E_ALL ); ini_set( 'display_errors', 1 );
          
          session_start();
          
          define ( 'MkHtmlSafe', true ) ; // true - Für Mailclients, die Text mutwillig falsch als HTML interpretieren. Das kann man nur testen. Sonst false um die originale Ausgabe zu haben.
          
          // a litte lazy:
          if ( 80 == $_SERVER['SERVER_PORT'] ) {
            $protokoll = 'http://';
          } else {
           $protokoll = 'https://';
          }
          
          
          $output = '
          Aufrufende IP: ' . $_SERVER['REMOTE_IP'] .'
          Aufgerufene Adresse: ' . $protokoll . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] . '
          HTTP Referer: ' . $_SERVER['HTTP_REFERER'] . '
          User Agent:   ' . $_SERVER["HTTP_USER_AGENT"] . '
          Zeitpunkt:    ' . date( 'j.n.Y H:i:s e' ) . '
          --------------------------------------------
          $_GET:        ' . var_export( $_GET, true ) . '
          --------------------------------------------
          $_POST:       ' . var_export( $_POST, true ) . '
          --------------------------------------------
          $_COOKIE:     ' . var_export( $_COOKIE, true ) . '
          --------------------------------------------
          $_SESSION:    ' . var_export( $_SESSION, true ) . '
          --------------------------------------------
          ';
          
          if ( MkHtmlSafe ) { $output = htmlspecialchars( $output ) ; }
          echo $output; # or whatever
          
          1. $_SERVER['REMOTE_IP']

            muss natürlich $_SERVER['REMOTE_ADDR'] sein.

      2. Du hast also die Nachricht über Dein Kontaktformular bekommen.

        Vorweg: Wie auf der zugehörigen Seite vermerkt, ist das Skript nicht ausgereift, sondern nur ein Gerüst, ein Vorschlag für die Weiterentwicklung, Verbesserung und Anpassung an individuelle Bedürfnisse (was ja hier auch gerade diskutiert wird).

        Aber wie wir sehen: "Copy & Paste" durch Unwissende (genau die brauchen solche, eigentlich trivialen Fertigskripte) und schon haben die Hacker wieder einen Server mehr für DDoS-Attacken, Spam-Mails etc.

        1. Das Skript ist nicht an ein Formular gekoppelt.

        Die Chinesen, Koraner, Russen, Ukrainer, Russen, Bulgaren (und ich) brauchen kein Formular um Daten zu senden...

        1. Es dient in der Praxis dazu, Link-Fehler innerhalb der Site zu entdecken.

        Dafür gibt es das error.log. Das kann man mit grep " 404 " schön durchsuchen.

        Solltet Ihr jedoch zu dem Schluss kommen, dass es unrettbar "bad,bad,bad" ist, stellt es kein Problem dar, die Publikation zu löschen, um Mißbrauch oder gar Schäden nicht zu fördern.

        Naja. Es ist wenig nützlich, dafür aber sehr gefährlich. Was sollen wir raten? In der diskutierten Form muss es sofort weg.

        1. Du hast also die Nachricht über Dein Kontaktformular bekommen.

          Ja, Regina, vielen Dank!

          Aber wie wir sehen: "Copy & Paste" durch Unwissende (genau die brauchen solche, eigentlich trivialen Fertigskripte) und schon haben die Hacker wieder einen Server mehr ...

          Ein wirklich gutes Argument! Und gemäß unserer eigenen Policies hinreichend, um die Publikation des Skripts umgehend einzustellen. Ich werde hier weiter lesen und beobachten, um zu sehen, ob es eine neue Version auf unseren Seiten geben wird.

          @all:

          Vielen Dank an alle, die mich auf die Unzulänglichkeiten hingewiesen und Verbesserungen vorgeschlagen haben!

          Reiner

          1. Hallo,

            Vielen Dank an alle, die mich auf die Unzulänglichkeiten hingewiesen und Verbesserungen vorgeschlagen haben!

            Da ich mich da nicht angesprochen fühle, möchte ich dir einfach so herzlich willkommen in unserem Forum sagen. :)

            Gruß
            Kalk

      3. Hallo Reiner,

        Herzlichen Dank für die Kommentare zu diesem Skript, dass von meiner Seite stammt.

        das ≠ dass

        1. Das Skript ist nicht an ein Formular gekoppelt. Es gibt keine Eingabefelder und keinerlei HTML-Code, der Prozess läuft völlig unsichtbar für den Benutzer.

        Allgemein: Security by Obscurity kann funktionieren, muss aber nicht (das ist dann allerdings keine Sicherheit). Aber die Sicherheitsaspekte wurden hier ja bereits besprochen.

        1. Es dient in der Praxis dazu, Link-Fehler innerhalb der Site zu entdecken. Dies ist sinnvoll und hilfreich, weil die Site faktisch tausende interner Links enthält (statisch gesetzt und großteils dynamisch erzeugt).

        Gerade dann ist ein Blick in die Log-Dateien oft besser, weil man die besser als einen E-Mail-Haufen filtern kann, das sollte auch noch als Alternative erwähnt werden. Vielleicht ist diese Funktionalität aber für Leute, die das Log-Datei-Checken verschwitzen, ein nettes Helferlein.

        1. Tatsächlich wird der User-Agent nicht gebraucht, ebenso wenig die IP-Adresse (braucht nicht weiter betrachtet werden).

        Das Loggen der IP-Adresse dürfte in Deutschland meines Wissens zumindest rechtlich bedenklich sein.

        1. Die Fehlerunterdrückung dient dazu, keinerlei Hinweis im Browser auf die Background-Routine zu liefern (jede bessere Methode wird gern genommen). Der Benutzer erhält ausschließlich (unabhängig vom Skript) wie üblich eine Error-Page (NOT FOUND), wenn der Fehler durch fehlerhaften Aufruf über die Adresseingabe oder durch einen fehlerhaften Link auf einer Seite ausgelöst wurde.

        Das Error-Reporting von PHP auf passende Werte stellen (am besten in der php.ini), also die Fehler dem Nutzer generell nicht anzuzeigen (wozu auch, der Website-Betreiber muss ihn letztlich beheben), sondern nur in den Log-Dateien zu speichern, wo sie auch hingehören.

        Solltet Ihr jedoch zu dem Schluss kommen, dass es unrettbar "bad,bad,bad" ist, stellt es kein Problem dar, die Publikation zu löschen, um Mißbrauch oder gar Schäden nicht zu fördern.

        Ich finde es gar nicht schlecht, solche Fertig-Scripte bereitzustellen, am besten mit Erläuterungen – deren Leser werden dadurch vielleicht angeregt, sich mit PHP zu beschäftigen – vor allem dessen Möglichkeiten kennenzulernen – und sich eventuell sogar „anfixen“ lassen
        – Bei mir war es so: Ich habe eines dieser fertigen Datei-Upload-Scripte ausprobiert, bin im Verlauf des Experimentierens (aber nicht des Einsatzes) auf Probleme (Dateigröße...) und Sicherheitsbedenken (Login via BasicAuth (.htaccess) davor geschaltet) gestoßen und habe mich dann letztlich mit PHP beschäftigt, um die Hintergründe zu verstehen.

        Gruß
        Julius

  3. Mit unten gezeigter Version bekomme ich nun eine Fehlermeldung:

    PHP Notice:  Undefined variable: mail_text in
    

    Und als auslösende Zeile wir diese angegeben:

    @mail($mail_to, $mail_subject, $mail_text, $mail_extras);
    
    <?php
    // Referer ermitteln
    $visitor_referer = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
    
    // E-Mail Sender und Empfänger festlegen
    $mail_from = "mail@example.org";  // <== Sender. Anpassen!
    $mail_to = "mail@example.org"; // <== Empfänger: Ihre E-Mail-Adresse!
    
    // E-Mail: Format ist HTML utf8
    $mail_extras = "From: Error-Manager <$mail_from>\n";
    $mail_extras .= "Content-Type: text/plain; charset=utf-8\n";
    $mail_extras .= "Content-Transfer-Encoding: 8bit\n";
    $mail_extras .= "Content-Language: de\n";
    
    // Betreff-Zeile festlegen
    $mail_subject = "Fehler 404";
    
    // Text der E-Mail zusammenstellen
    $mail_text .= "Aufgerufene Adresse: https://" . $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"] . "\n";
    $mail_text .= "HTTP Referer: $visitor_referer\n\n";
    $mail_text .= "Datum: " . date("j.n.Y H:i:s e") . "\n";
    $mail_text .= "IP-Adresse: " . $_SERVER["REMOTE_ADDR"] . "\n";
    $mail_text .= "User Agent: " . $_SERVER["HTTP_USER_AGENT"];
    
    // E-Mail senden
    @mail($mail_to, $mail_subject, $mail_text, $mail_extras);
    ?>
    
    1. Tach!

      PHP Notice: Undefined variable: mail_text in

      $mail_text .= "...";
      

      Der Operator .= liest zunächst die Variable auf der linken Seite ... und wenn die bisher noch nicht vorher schreibend angesprochen und dabei angelegt wurde, gibts diesen Fehler. Der erste Zugriff sollte mit = eine Nur-Zuweisung sein, so wie bei $mail_extras.

      dedlfix.

      1. Der Operator .= liest zunächst die Variable auf der linken Seite ... und wenn die bisher noch nicht vorher schreibend angesprochen und dabei angelegt wurde, gibts diesen Fehler. Der erste Zugriff sollte mit = eine Nur-Zuweisung sein, so wie bei $mail_extras.

        Ah alles klar. Dankeschön!

  4. Hallo an Euch alle hier.

    Ich danke Euch sehr für Eure liebe und tolle Hilfe. Ich habe versucht, alle Eure Ratschläge umzusetzen. Dabei ist nun die folgende Variante des Scripts herausgekommen:

        <?php
          // E-Mail Sender und Empfänger festlegen
          $mail_from = "mail@example.org";  // <== Sender. Anpassen!
          $mail_to = "mail@example.org"; // <== Empfänger: Ihre E-Mail-Adresse!
    
          // E-Mail: Format ist HTML utf8
          $mail_extras = "From: Error-Manager <$mail_from>\n";
          $mail_extras .= "Content-Type: text/plain; charset=utf-8\n";
          $mail_extras .= "Content-Transfer-Encoding: 8bit\n";
          $mail_extras .= "Content-Language: de\n";
    
          // Betreff-Zeile festlegen
          $mail_subject = "Fehler 404";
    
          // Text der E-Mail zusammenstellen
          $mail_text = "Aufgerufene Adresse: https://" . $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"] . "\n";
          $mail_text .= "HTTP Referer: " . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '') . "\n\n";
          $mail_text .= "Datum: " . date("j.n.Y H:i:s e") . "\n";
          $mail_text .= "IP-Adresse: " . $_SERVER["REMOTE_ADDR"] . "\n";
          $mail_text .= "User Agent: " . $_SERVER["HTTP_USER_AGENT"];
    
          // E-Mail senden
          @mail($mail_to, $mail_subject, $mail_text, $mail_extras);
        ?>
    

    Ist das nun in Sachen Sicherheit besser? Oder sollte ich noch was ändern?

    Gruß Ingo

    1. Tach!

      Ist das nun in Sachen Sicherheit besser? Oder sollte ich noch was ändern?

      Ich kann dir keine Absolution geben, nur sagen, dass mir nichts weiter auffällt.

      dedlfix.

      1. Moin

        Ich kann dir keine Absolution geben, nur sagen, dass mir nichts weiter auffällt.

        Geilomat :-)

        Gruß Ingo

    2.   // E-Mail: Format ist HTML utf8
        $mail_extras = "From: Error-Manager <$mail_from>\n";
        $mail_extras .= "Content-Type: text/plain; charset=utf-8\n";
        $mail_extras .= "Content-Transfer-Encoding: 8bit\n";
        $mail_extras .= "Content-Language: de\n";
      

      Content-Language dürfte von keinem E-Mail-Programm ausgewertet werden und ich wäre mir nicht so sicher, dass deine Daten utf-8-kodiert sind.

        $mail_text .= "HTTP Referer: " 
      

      Das Ding heisst "referrer".

        $mail_text .= "Datum: " . date("j.n.Y H:i:s e") . "\n";
      

      Das "e" kannst du dir sparen, es sei denn, du brauchst es, um dich an den Wechsel zwischen Sommer- und Winterzeit zu erinnern. Oder du hast deinen Server in einem Luftschiff untergebracht, das um die Welt gondelt.

        // E-Mail senden
      

      Wozu ständig von geschwätzigen Mail belästigt werden, wenn man doch so schön einmal am Tag ins Fehlerprotokoll gucken kann? Aber gut, das ist Geschmackssache.
      Ich hoffe nur, dass du keine Weiterleitung auf das Skript angelegt, sondern es als Fehlerdokument korrekt eingetragen hast. Leute, die, absichtlich oder unabsichtlich, ihre Server mit 301 statt 404 antworten lassen, gibt's en masse.

      1. Hallo Daniel Duden,

          $mail_text .= "HTTP Referer: " 
        

        Das Ding heisst "referrer".

        Im Prinzip ja, aber manchmal auch nicht.

        Gruß
        Julius

      2. Hallo Daniel

        Content-Language dürfte von keinem E-Mail-Programm ausgewertet werden und ich wäre mir nicht so sicher, dass deine Daten utf-8-kodiert sind.

        OK ich verstehe. Glaube ich zumindest :-) Ich soll es also lieber so machen?

        // E-Mail
          $mail_extras = "From: Error-Manager <$mail_from>\n";
          $mail_extras .= "Content-Type: text/plain\n";
          $mail_extras .= "Content-Transfer-Encoding: 8bit\n";
        

        Das "e" kannst du dir sparen, es sei denn, du brauchst es, um dich an den Wechsel zwischen Sommer- und Winterzeit zu erinnern. Oder du hast deinen Server in einem Luftschiff untergebracht, das um die Welt gondelt.

        OK, also einfach weg mit dem e?

         $mail_text .= "Datum: " . date("j.n.Y H:i:s") . "\n";
        

        Ich hoffe nur, dass du keine Weiterleitung auf das Skript angelegt, sondern es als Fehlerdokument korrekt eingetragen hast. Leute, die, absichtlich oder unabsichtlich, ihre Server mit 301 statt 404 antworten lassen, gibt's en masse.

        Das Script befindet sich in meiner 4040-Fehlerseite. Diese ist korrekt in der .htaccess eingetragen und liefert auch den Statuscode 404 zurück. Ist es das, was Du gemeint hast?

        Gruß Ingo

  5. Hallo

    Ich habe das Script nun noch weiter aufs Wesentliche reduziert. Was sagt Ihr dazu? Ist es so eigentlich immer noch als Spamschleuder für böse Buben (oder Damen) nutzbar?

        <?php
          $mail_text = "\nAdresse: https://" . $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"] . "\n";
          $mail_text .= "Referer: " . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '') . "\n\n";
          @mail("mail@example.org", "Fehler 404", $mail_text, "From: Fehler 404 <mail@example.org>\n");
        ?>
    
    1. Hall

      Einige von Euch hatten mich ja auch auf das Abschalten der Fehlermeldungen angesprochen. Ich habe es bei mir auf der Website generell so eingerichtet, dass alle PHP Fahler nicht im Browser angezeigt werden. Die laufen bei mir alle in eine log-Datei, in die ich ab und zu mal hineinschaue und hoffe, dass sie weiterhin leer ist.

      Das ist doch sinnvoll so, oder?

      Gruß Ingo

      1. Tach!

        Ich habe es bei mir auf der Website generell so eingerichtet, dass alle PHP Fahler nicht im Browser angezeigt werden. Die laufen bei mir alle in eine log-Datei, in die ich ab und zu mal hineinschaue und hoffe, dass sie weiterhin leer ist.

        Das ist doch sinnvoll so, oder?

        Ja. Eine allgemein sinnvolle Vorgehensweise ist, das error_reporting auf E_ALL stehen zu haben und in der Entwicklungsumgebung display_errors auf on zu haben, in der Produktivumgebung hingegen auf off. Dort sollte außerdem log_errors auf on stehen und error_log auf eine regelmäßig überprüfte Datei zeigen. Oder man schaut da nach, wo es per Default hingeleitet wird.

        Natürlich ist das nur eine allgemeine Empfehlung. Im Individualfall kann man auch was anderes einstellen, beispielsweise wenn man Fremdanbietersoftware verwendet, die ständig Notice-Fehler produziert, und man das nicht beseitigen (lassen) kann oder will.

        Eine weitere Möglichkeit (statt error_log) ist, einen eigenen Errorhandler zu schreiben, der alle Fehler nach den eigenen Vorlieben verarbeitet (Mail senden oder Datenbankeintrag oder wasauchimmer.

        dedlfix.

    2. Tach!

      Ist es so eigentlich immer noch als Spamschleuder für böse Buben (oder Damen) nutzbar?

            @mail("mail@example.org", "Fehler 404", $mail_text, "From: Fehler 404 <mail@example.org>\n");
      

      Eine Spamschleuder baut man, indem man die Möglichkeit schafft, dass der Anwender beliebige Headerzeilen oder anderweitig beliebige Empfänger angeben und möglichst noch eine selbstverfasste Nachricht eingeben kann. Letzteres zum Beispiel bei einem simplen Kontaktformular.

      Das ist in deinem Fall nicht gegeben, weil sowohl der Empfänger als auch der Parameter für die additional headers mit festen Werten versorgt werden. Ein Fehler wäre, wenn etwas in die additional Header eingefügt wird, ohne dass man die Abwesenheit von Zeilenumbruchszeichen sicherstellt.

      dedlfix.

      1. Eine Spamschleuder baut man, indem man die Möglichkeit schafft, dass der Anwender beliebige Headerzeilen oder anderweitig beliebige Empfänger angeben und möglichst noch eine selbstverfasste Nachricht eingeben kann. Letzteres zum Beispiel bei einem simplen Kontaktformular.

        Das ist nur die unmittelbare Sicht. Indirekt wird der Webserver auch zur Spamschleuder

        • wenn man eine Möglichkeit für einen nicht vorgesehenen Dateiuplaod (z.B. einer Webshell) schafft,
        • oder wenn man die Möglichkeit einer nicht vorgesehenen Rechtemanipulation als Voraussetzung weiteren Vorgehens schafft,
        • oder, oder, oder...

        Es kommt dann nur noch auf die Nutzungsart an.

        1. Tach!

          Eine Spamschleuder baut man, indem man die Möglichkeit schafft, dass der Anwender beliebige Headerzeilen oder anderweitig beliebige Empfänger angeben und möglichst noch eine selbstverfasste Nachricht eingeben kann. Letzteres zum Beispiel bei einem simplen Kontaktformular.

          Das ist nur die unmittelbare Sicht. Indirekt wird der Webserver auch zur Spamschleuder

          Ja, das war lediglich auf die konkrete Frage beschränkt. Natürlich gibt es noch viele weitere Möglichkeiten, seinen Server ungewollt fremdnutzen zu lassen.

          dedlfix.