Gästebuch absichern

Gefahr erkannt, Gefahr gebannt

Warum ist ein so einfaches Script gefährlich? Dafür gibt es zahlreiche Gründe. Fangen wir damit an, dass erfahrene Nutzer uns HTML (und schlimmeres) unterjubeln können. Die harmlosen Dinge sind, dass dann Texte fett ("<b>") und/oder farbig dargestellt werden. Auf die weniger harmlosen gehe ich weiter unten ein.

Wir müssen sicherstellen, dass das, was der Benutzer eingibt, auch wirklich nur Text ist. Wir lassen also alle Variablen durch eine Waschanlage, die unerwünschte Dinge herausfiltert. Dies ist relativ einfach. Nähere Informationen finden Sie in diesem Kurs unter: http://www.php-kurs.com/uebergebene-variablen-bereinigen.htm

Für das Reinemachen rufen wir am Anfang des „gaestebuch-eintrag.php“ folgende 3 Zeilen auf. Darin werden dann übergebene Variablen durch eine Funktion geschleust und kommen mit 60 Grad gewaschen, gebügelt und von Ungeziefer befreit wieder heraus.

Bevor Sie aber diese Zeilen an den Anfang packen, geben Sie im Gästebucheintrag folgenden Text ein:

HTML-Code in Gästebuch einschleusen
Hallo <h1>altes Haus</h1><br />
ich <pre>zerbrösel nun dein Layout,
weil ich meine HTML-Befehle in deine
Seite packte ? ätsch =;)
Angriff auf Gästebuch durch HTML Injection Angriffe
Angriff auf Gästebuch durch HTML Injection Angriffe

Und nun aber das Vollwaschmittel an den Anfang packen:

PHP-Quellcode
array_walk ( $_POST,    'eingabebereinigen' );
array_walk ( $_GET,     'eingabebereinigen' );
array_walk ( $_REQUEST, 'eingabebereinigen' );
 
function eingabebereinigen(&$value, $key)
{
  // keine HTML-Tags erlaubt, außer p und br
  $value = strip_tags($value, '<p><br /><b><strong>');
 
  // HTML-Tags maskieren
  $value = htmlspecialchars($value, ENT_QUOTES);
 
  // Leerzeichen am Anfang und Ende beseitigen
  $value = trim($value);
}

Löschen Sie diesen Datensatz aus der Datenbank, um wieder eine normale Anzeige zu bekommen. Dann probieren Sie es nochmals mit dem HTML-Eintrag. Nun aber sollte es wie folgt aussehen:

HTML Injection Angriffe abgewendet
HTML Injection Angriffe abgewendet

Ohne Schutz kann auch JavaScript eingeschleust werden (z.B. <script>alert('gehackt :) ')</script> ) oder sonstiges.

2. Problemzone: Anführungsstriche

Dieses Bereinigen schaut auch nach eingegebenen einfachen und doppelten Anführungsstrichen. Werden diese ungefiltert übernommen, ist genau an diesem Zeichen dann Ihr SQL-Befehl beendet und Sie bekommen eine Fehlermeldung um die Ohren geklatscht (bzw. der Gästebucheintrager). Das wäre dann noch der bessere Fall. Im Extremfall kann so jemand Ihre Datenbank „hacken“ und relativ flott viele unangenehme Dinge durchziehen (z.B. löschen).

Daher: niemals den Eingaben von Benutzern trauen, da diese im Internet nicht bekannt sind.

3. Problemzone: E-Mail-Adresse

Sie können zwar die E-Mail-Adresse erfassen, sollte diese aber tunlichst nicht als Text ausgeben. Ansonsten haben Sie Ihrem Gästebucheintrager einen Bärendienst erwiesen. Geben Sie die Adresse im Klartext aus, freuen sich alle Spam-Sammler (die automatisiert sind) und der Gästebuchnutzer bekommt auf einmal mehr Spam als früher (und weiß in der Regel gar nicht warum). Wenn unbedingt die E-Mail-Adresse angezeigt werden soll, dann z.B. als Grafik http://www.php-kurs.com/grafiken-erstellen-mit-php.htm

4. Problemzone: URL

Klar macht es Spaß, dass andere ihre URL der eigenen Website angeben können. Allerdings ist auch das ein Grund, warum viele ungebetene Gäste im Gästebuch einen Eintrag hinterlassen, um dort dann für Ihre Pxxxno-Seite zu werben (was dann im Endeffekt Ihre Website macht).

Es kann auch der Fall sein, dass Leute nur zum Sammeln von Backlinks einen Eintrag schreiben. Denn je mehr Backlinks, desto besser steht man i.d.R. bei Suchmaschinen da.

5. Problemzone: Inhalt

So – auf die Gefahr hin, einem das Gästebuch vollends zu vermiesen. Sie sind nach deutschen Recht verantwortlich was auf Ihrer Seite steht (auch für das, was andere schreiben). Soll heißen, wenn jemand mit wilden Beleidigungen und Diffamierungen um sich wirft und man sich auf „Meinungsfreiheit“ beruft, hat man wenig Spaß vor Gericht. Daher sollten Sie die Gästebucheinträge prüfen und gegebenenfalls löschen. Ich habe schon Gästebucheinträge gesehen, die aus 1000 Links nach außen bestanden, wo man sich nicht sicher war, welcher am unappetitlichsten war. Diese wurden dann teilweise versucht zu verstecken, indem die Schriftgröße extrem verkleinert wurde, damit nur Suchmaschinen diese Links finden.

Nach soviel Problem auch Lösung

Wir wollen die Gästebucheinträge erst nach Sichtkontrolle freischalten (big brother is watching you :)

Wir fügen also ein weiteres Feld in der Datenbank ein, das wir „aktiviert“ nennen. Das geht am schnellsten über phpMyAdmin im Punkt „Struktur“ unten „Feld hinzufügen“. Als MySQL-Befehl:

MySQL-Anweisung
ALTER TABLE `gaestebuch` ADD `aktiviert` CHAR( 1 ) NOT NULL ;

Das Feld hat die Länge von "1" und ist ein Char. Sobald der Eintrag angezeigt werden darf, wird hier eine 1 gesetzt.

Aufgabe

Um nun das so komfortabel zu machen als möglich, lassen wir uns nach dem Eintrag durch den Nutzer automatisch eine E-Mail senden: siehe: http://www.php-kurs.com/email-per-php.htm

In dieser E-Mail gibt es neben dem Text, den der Besucher eingetragen hat, dann noch einen Link für uns zum freischalten: Dort steht dann

http://www.php-kurs.com/gaestebuch-freischalten.php?id=$id

Dieser Link muss natürlich auf die URL Ihrer Website angepasst werden. Weiterhin sollte auch der Dateinamen variiert werden, sonst kann jeder, den Link kennt, den Eintrag theoretisch freischalten.

In dieser Freischalten-Anwendung steht dann:

PHP-Quellcode: gaestebuch-freischalten.php
<?php
$sql = " UPDATE gaestebuch ";
$sql .= " SET aktiviert='1' ";
$sql .= " WHERE id='". $_GET['id'] ."' ";
 
echo "<hr>SQL: $sql<hr>";
 
define ( 'MYSQL_HOST', 'localhost' );
define ( 'MYSQL_BENUTZER', 'root' );
define ( 'MYSQL_KENNWORT', '' );
define ( 'MYSQL_DATENBANK', 'homepageanwendungen' );
 
$db_link = @mysqli_connect (MYSQL_HOST,
                            MYSQL_BENUTZER,
                            MYSQL_KENNWORT,
                            MYSQL_DATENBANK);
 
if ( ! $db_link )
{
    // hier sollte dann später dem Programmierer eine
    // E-Mail mit dem Problem zukommen gelassen werden
    // die Fehlermeldung für den Programmierer sollte
    // das Problem ausgeben mit: mysql_error()
    die('keine Verbindung zur Zeit möglich -
         später probieren ');
}
 
// ausführen des mysql-Befehls
$db_erg = mysqli_query( $db_link, $sql );
if ( ! $db_erg )
{
    die('Ungültige Abfrage: ' . mysql_error());
}
 
echo "<h2>Eintrag ". $_GET['id'] ." freigeschaltet</h2>";
echo '<p><a href="gaestebuch.php">Gästebuch anzeigen</a></p>';
?>

Im Script "gaestebuch.php" wird die SQL-Abfrage erweitert, so dass nur noch freigeschaltet Einträge angezeigt werden:

PHP-Quellcode: erweiterung MySQL-Anweisung im Gästebuch
// SQL-Befehl für den Zugriff
$sql = "
    SELECT
        *
    FROM gaestebuch
    WHERE aktiviert='1'
    ORDER BY datum
";