Sicherheit für Scripte und Formulare

in Zeiten, in denen Spammern sich vermehrt um Mail-Formulare und dergleichen versammeln, kann es nicht verkehrt sein, Scripte und Formulare etwas sicherer zu gestalten.
Im folgenden sind daher einige sicherheitsrelevante Maßnahmen aufgezählt und kurz erklärt.

1. ungewollte Script-Aufrufe verhindern

Gerne werden Dateien und Scripte namentlich header.inc.php, footer.inc.php, kontakt.php per include() in eine Webseite eingebunden. Will man verhindern, das diese, zum einbinden bestimmten Dateien direkt im Browsers aufgerufen werden können, notiert man zum einem in die aufrufende Webseite:

 <?php  define('in_page', '1');  ?>

und zum anderen in das entsprechende Script:

<?php if(!defined('in_page'))die 
    ('Zugriff verweigert!');?>

Das define() gibt einen Wert (hier in_page) vor, der vom includierten Script geprüft wird.
Wird das Script ohne den vordefinierten Wert aufgerufen, zum Beispiel durch direkte Eingabe in die Adressleiste, bricht der Vorgang sofort ab und gibt "Zugriff verweigert!" an den Browser aus.

2. sicheres Datei-Include

Variablen aus einem Link oder Formular, die mit GET versendet werden, können leicht über die Adressleiste des Browsers ausgelesen werden. Dient ein übergebener Wert dazu, dass eine bestimmte Datei includiert wird, besteht die Gefahr, dass fremde Inhalte untergeschoben werden. Der folgende Codeschnipsel überprüft, ob sich die zu includierende Datei in einem bestimmten Ordner des Webservers befindet. Ist dies der Fall, wird die Datei eingebunden. Wenn nicht, wird eine alternative Datei includiert.

<?php
$include_array =array('newsletter.inc.php',
	'impressum.inc.php');
$inc_dir=opendir ("./service");
while ($inc = readdir ($inc_dir)) {
if($inc != "." && $inc != "..") {
$short_inc = str_replace(".inc.php", "", $inc);
array_push ($include_array, $short_inc);
} }
closedir($inc_dir);
if (isset($_GET['id']) && in_array($_GET['id'], 
	$include_array) ) {
include("./service/".$_GET['id'].".inc.php");
}
else { include("./service/start.inc.php"); }
?>

Im $include_array befinden sich die Dateien, die eingebunden werden dürfen. Im Beispiel sind dies newsletter.inc.php und impressum.inc.php. Beide befinden sich in einem Ordner mit Namen "service". Wird versucht mit der Variablen $id z:b. ein Script mit dem Namen hacker.inc.php zu übergeben, kann diese im Ordner "service" nicht gefunden werden, folglich wird die Alternative, start.inc.php includiert.

4. Variabeln sicher einlesen

In manchen Fällen ist bereits klar, welchen Wert eine Variable annehmen kann bzw. soll.
Erwartet man ausschlieslich Zahlen, notiert man (int). Das stellt sicher, dass der übergebene Wert tatsächlich vom Typ Zahl (Integer) ist.

(int)$_GET['lottozahl'] 

Oder man überprüft, ob die übergebene Variable Teil eines Arrays ist, mit in_array()

$werte = array ('blume','kugel','taube');
if ( in_array($_GET['id'], $werte) )

Emailadressen können, zumindest formal, auf Richtigkeit geprüft werden:

if ($email!="" && ereg("^([a-zA-Z0-9\.\_\-]+)@
    ([a-zA-Z0-9\.\-]+\.[A-Za-z][A-Za-z]+)$", 
    $email))

Das heißt, ein @ Zeichen ist vorhanden, etwas steht davor, etwas danach und das, was danach steht, enthält zwischendurch noch einen Punkt.

Die Variabeln sollten grundsätzlich nie ungeprüft durch ein Script düsen. Jede Validierung sollte daher strip_tags() nutzen.

strip_tags();        entfernt html-Tags aus 
                     dem String
	
htmlspecialchars();  wandelt Sonderzeichen in 
                     HTML-Codes um

trim();              entfernt Leerzeichen vor 
                     und nach dem String

substr($wert,0,40);  kürzt einen Text auf 40 Zeichen

5. Passwörtern mit md5 oder sha1 "verschlüsseln"

Weder MD5 noch SHA1 sind Verschlüsselungen, sondern Hashes (bzw. Prüfsummen).
Das eingegebene Passwort wird in einen Hash umgewandelt und in die Datenbank oder eine Textdatei geschrieben. Um beim Login dann das Passwort zu überprüfen, muss wieder ein Hash erzeugt und mit dem ursprünglich generierten Hash verglichen werden.
Der Hash ist nicht zurückwandelbar. Allerdings ist es möglich aus zwei unterschiedlichen Wörtern denselben Hash zu bilden, was wiederum bedeutet, das durch ausprobieren ein Passwort geknackt werden könnte. In Anbetracht dieser Tatsache ist es sehr zweckmäßig, eine Anzahl an Zeichen für das Passwort vorzuschreiben, noch besser ist die Verwendung von Zahlen UND Buchstaben.

$passwort ="hunde45kuchen";
$pw = md5($passwort); 

ergibt: aba0bc1e4cfe07e8d2b58acf94e4c92a

$passwort ="hunde45kuchen";
$pw = sha1($passwort); 

ergibt: d85b0afd58b6b6897c5bb3e687991bae09dc458b

6.1 Formulare - Spamscripte und das automatische Ausfüllen von Formularen

Nichts ist schöner für einen Spammer als eine automatische Füllroutine für Formulare zu nutzen, spart man sich doch so das manuelle Ausfüllen. Der Automat liest die Namen der Formularelemente aus und füllt diese. Was er nicht beachtet: Ein Feld des Formulars ist mit der Stylesheet-Anweisung display:none; für Besucher unsichtbar gemacht, und folglich von Menschenhand auch nicht gefüllt.. Das empfangende Script prüft den Wert des unsichtbaren Formularelementes, ist es nicht leer, war ein Spamscript am Werk. Besonders bei vielen Eingabefeldern dürfte auf den ersten und vielleicht zweiten Blick gar nicht auffallen, das ein Feld des Formulars versteckt ist.

6.2 Formulare - das Attribut maxlength

Als zusätzliche kleine Hürde sollte das Attribut maxlength im Formular-Textfeld

<input type="text" maxlength="10"  name="email"> 

nicht fehlen. Im Beispiel begrenzt der Wert "10" die Zahl eintippbarer
Ziffern auf 10.

6.3 Formulare - am besten mit POST

Desweiteren sollten Formulare am besten mit POST abgeschickt werden. Ein potentieller Angreifer ist dann gezwungen einen HTTP POST-REQUEST zu schreiben, was aufwändiger ist, als Angriffe per GET zu starten.

7. automatisches Auslesen der Emailadresse im Quelltext verhindern

Sammelroboter, die sogenannten Spambots, durchsuchen den Quellcode von Webseiten nach Emailadressen. Bislang sind jedoch fast alle Roboter nicht in der Lage, ASCII-Code zu entziffern. Da Browser den ASCII-Code in Klarschrift anzeigen, liegt es auf der Hand, die Emailadressen im Quelltext einfach in ASCII-Zeichen zu schreiben.
Die Verschlüsselung kann manuell mit einer Übersetzungstabelle vorgenommen werden oder automatisch mit dem Email to ASCII Generator

8. Einträge in der php.ini

wenn es der Provider zulässt oder man einen eigener Server konfiguriert, sollte die php.ini modfiziert werden.

register_globals= Off erschwert es einem Angreifer Variablen in php-Code einzuschleusen.
Die übergebenen Variablen müssen dann wie folgt angesprochen werden:

$_GET['email']
$_POST['telefon']
$_COOKIE['name']

deaktivieren von allow_url_fopen verhindert, dass eine Datei auf einem anderen Webserver geöffnet und verarbeitet wird.

9. Die Adreßbasis einer Html-Datei

Mit base href="" wird die Adreßbasis einer Html-Datei bestimmt.

<head>

  <base href="http://www.blablablabla.com/">
</head>

Ist im Quelltext ein Bild referenziert, <img src="xyz.jpg"> ermittelt der Browser daraus eine absolute Adresse: <img src=" http://www.blablablabla.com/xyz.jpg">

Zusammen mit der Angabe der Adreßbasis, lädt der Browser immer das angegebene Bild von der URL-Adresse. Wird die Html-Datei lokal abgespeichert, muss bei Aufrufen derselbigen will der Browser immer erst eine Verbindung zum Internet herstellen, um die Grafik anzuzeigen.

Die aufgezählten Maßnahmen geben natürlich keinen 100% Schutz. Auch kann keine Garantie auf Vollständigkeit gegeben werden. Dennoch muss ein Angreifer oder Spammer ersteinmal diese Hindernisse überwinden, wenn er erfolgreich sein will.

Weitere Artikel in der Rubrik Computer und Technik