Home
Navigation
Impressum
Coder Welten - Programmierung und Optimierung
Coder Welten
 
 

 

 

Sicherheit von PHP-Scripts und Applikationen - Teil II

Sicherheit von Webapplikationen

Ein kleines PHP-Listing oder ein PHP-Script-Schnipsel ist schnell geschrieben und lässt sich leicht in einem bereits bestehenden HTML-Dokument einbinden, zum Beispiel um die durch ein Formular versendeten Daten auszugeben. Handelt es sich dabei um einen Test, so spielt das Thema erst einmal eine untergeordnete Rolle, da Testseiten in der Regel der Öffentlichkeit nicht zugänglich sind. Problematisch kann es hingegen werden, wenn ein Einsteiger den Empfang von per GET oder POST übermittelten Daten mit einem einfachen Script-Schnipsel testet, dass Listing dann aber ohne zusätzliche Sicherung als Webapplikation einsetzt.
Es sei angemerkt, nicht nur die ungesicherter Auswertung von per GET oder POST übermittelten Daten birgt ein Risiko in sich, da es jedoch die gebräuchlichsten Request-Methoden sind, sollten diese beiden Request-Methoden zur Veran-schaulichung erst einmal reichen.

In den Beispielen auf dieser Seite wurde PHP-Code in eine HTML-Seite eingebettet, um mit Hilfe der superglobalen $_GET Variable die vom Formular versendeten Daten in Empfang zu nehmen. Die superglobale Variable $_GET enthält dabei ein assoziatives Array mit allen Variablen und deren Werten, die von einem Formular als QueryString versendet und vom Script empfangen wurden. Beim QueryString handelt es sich um den Teil einer URL, der hinter dem Fragezeichen beginnt und die einzelnen Variablen als Parameter enthält. Wer möchte, kann sich mit Hilfe von print_r() oder var_dump() den Inhalt des in $_GET enthaltenen Arrays anzeigen lassen.

Erstes Beispiel: In das Eingabefeld vom Formular wurde der String "Hallo Welt" eingegeben und versendet:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">
<html>

<head>
  <title>Einstieg in PHP</title>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  <meta http-equiv="Content-Style-Type" content="text/css">
</head>

<body>
<div style="width: 400px; text-align: center; margin: auto">

<?php

print_r($_GET);    // Ausgabe: Array ( [Name] => Hallo Welt ) 

?>

<form name="Eingaben" action="einstieg.php" method="get">
  <input type="text" name="Name" value="" size="30">
  <input type="submit" value="Senden">
</form>

</div>
</body>
</html>

Um die von einem Formular versendeten und mit einem QueryString übermittelten Werte nicht nur als im Array enthaltene Schlüssel und Werte anzuzeigen, sondern weiter zu verarbeiten oder formatiert auszugeben, kann auf die einzelnen Werte wie folgt zugegriffen werden.

Zweites Beispiel: Formatierte Ausgabe von Werten. Nur für erste Tests geeignet, da Weiterverarbeitung und Ausgabe ungesichert erfolgt!

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">
<html>

<head>
  <title>Einstieg in PHP</title>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  <meta http-equiv="Content-Style-Type" content="text/css">
</head>

<body>
<div style="width: 400px; text-align: center; margin: auto">

<?php

$einstieg = $_GET["Name"];

echo "<h1>".$einstieg."</h1>\n";

?>

<form name="Eingaben" action="einstieg.php" method="get">
  <input type="text" name="Name" value="" size="30">
  <input type="submit" value="Senden">
</form>

</div>
</body>
</html>

Für einen einfachen Test mag das letzte Listing bereits völlig ausreichen, von der Verwendung im Web wird hingegen dringlich abgeraten, da gleich mehrere Schwachstellen enthalten sind.
Die erste Unzulänglichkeit besteht darin, dass vom Script nicht kontrolliert wird, ob ein QueryString mit Parametern und Werten übergeben wurde. PHP würde, je nach Einstellungen in der php.ini, mit einer E_NOTICE antworten, insofern keine Werteübergabe erfolgte.
Eine E_NOTICE ist noch kein Fehler, könnte aber einen Hinweis auf mögliche Fehler enthalten. Vor der ersten Benutzung des Formulars und beim ersten Aufruf der Seite kann ja noch kein übergebener Wert vorhanden sein und somit wäre eine E_NOTICE erst nach der ersten Benutzung des Sende-Buttons berechtigt. Besser ist es hingegen, mit isset() abzufragen, ob ein Parameter übermittelt wurde und mit empty() zu kontrollieren, ob dem Parameter ein Wert zugeordnet wurde und falls nicht einen eigenen Hinweis auszugeben. Nebenbei bemerkt, mit dem Ausrufezeichen vor empty erfolgt eine Negierung, womit nichts anderes gemeint ist, als dass der übermittelte Parameter keinen leeren Wert String oder Null-Wert enthalten darf. Für die Abfrage von isset() und empty() wird ein if-Statement verwendet, dessen Aufbau sich in den vorgestellten Script- und Programmier-sprachen gleicht:

if (Bedingung) {                   // oder mehrere Bedingungen

           gewünschte Anweisung;   // z.B. Ausgabe

} else {alternative Mitteilung oder alternative Anweisung;}

Eine E_NOTICE kann noch relativ harmlos sein und in der Mehrheit der Fälle sind sie es auch, doch, wie im obigen Beispiel, Werte ungeprüft zu übernehmen und auszugeben, kommt schon sträflichen Leichtsinn gleich. Theoretisch könnte jeder beliebige Bösewicht den Wert austauschen und stattdessen Name => Schadcode übergeben. Um die Einschleusung von Schadcode zu erschweren, sollte der übergebene Wert kontrolliert und gefiltert werden.
Im nächsten Beispiel hilft dabei die PHP-Funktion preg_replace(), die mit Hilfe eines regulären Ausdrucks nach allen Zeichen sucht, die keinem Buchstaben und keiner Zahl entsprechen und diese Zeichen entfernt. Wird nun die Ausgabe zusätzlich noch mit htmlentities() abgesichert, so ist das Listing bereits recht sicher.

Drittes Beispiel: Mit preg_replace und htmlentities abgesichertes Listing.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">
<html>

<head>
  <title>Einstieg in PHP</title>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  <meta http-equiv="Content-Style-Type" content="text/css">
</head>

<body>
<div style="width: 400px; text-align: center; margin: auto">

<?php

if (isset($_GET["Name"]) and !empty($_GET["Name"])) {

    $einstieg = trim($_GET["Name"]);
    $einstieg = preg_replace("/[^a-zA-ZäöüÄÖÜß0-9]/"," ",$einstieg);

    echo "<h1>".htmlentities($einstieg, ENT_QUOTES)."</h1>\n";
}
else {
    echo  "Null Nachrichten!\n";
}
?>

<form name="Eingaben" action="einstieg.php" method="get">
  <input type="text" name="Name" value="" size="30">
  <input type="submit" value="Senden">
</form>

</div>
</body>
</html>

Es sei angemerkt, eine absolute Sicherheit gibt es nicht und ein Angreifer, der auf einen Weg nicht weiter kommt, wird sich gegebenenfalls nach einem anderen Weg umsehen. Mehr zum Thema Syntax und Sicherheit gegebenenfalls zu einem späteren Zeitpunkt.

Syntax und Sicherheit – Teil I « zurück

 

Copyright © Verlag Horst Müller - Stendal - 2006 - Impressum - Datenschutz - Nutzungsbedingungen