8 Kommunikation im Internet – HTTP und CGINachdem Sie Perl in seinen Grundzügen kennen, geht es mit der Verwendung von Perl im Internet weiter. Wie kommt eine Webseite in den Browser und wie gelangen Daten aus Formularen zum Server? Und wieso kann ein Perl-Programm mit den Daten etwas anfangen? Diese und andere Rätsel werden hier gelöst.
8.1 Die Kommunikation im Internet 8.1 Die Kommunikation im InternetDer Surfer zu Hause vor seinem Computer ruft mit seinem Browser Webseiten auf. Diese Seiten liegen auf Webservern. Der Webserver sucht die richtige Seite heraus und sendet sie zurück. Für diese Verständigung wird das HyperText Transfer Protokoll (HTTP) verwendet. Wird eine Anfrage nach einem CGI-Skript gesendet, benötigt der Webserver ein Programm, um die CGI-Anfrage zu verstehen und auszuführen: das Common Gateway Interface, CGI. Diese Schnittstelle ist ein kleines Programm, das dem Serverdienst ermöglicht, Programme auszuführen und die Rückgabewerte der Programme weiterzuverwenden. Die zurückgegebenen Daten werden vom Server als Website wieder an den Nutzer zurückgeschickt. Die HTTP-Anfrage wird Request, die HTTP-Antwort wird Response genannt.
8.2 Installation des Apache-Webservers[ Bitte im Buch weiterlesen :-) ]
8.3 URL: der Uniform Resource LocatorAlle Webseiten, Grafiken der Webseiten, Skripte der Seiten etc. sind als Ressourcen im Internet aufrufbar. Jede Ressource hat eine einmalige Adresse und ist mit dem Uniform Resource Locater, dem URL, ansprechbar. Ein URL hat folgenden Aufbau: http://www.franzis.de/index.php?reihe=2&preihe=1&seite=&kid= Schema| Rechnername | Pfad | Query-String http://www.undine-schrader.de:80/Seite/index.html#seite1 Schema| Rechnername |Port| Pfad |Fragment
8.4 HTTP: Die Sprache zwischen Browser und ServerDie Verständigung zwischen Browser und Server verläuft mittels eines Protokolls: dem HyperText Transfer Protocol, HTTP genannt. Es ist ein Request/Response-Protokoll: Der Browser sendet eine Anfrage (Request) und der Server gibt eine Antwort (Response) zurück. Das Format beider Nachrichtentypen ist:
8.4.1 Der RequestEs gibt verschiedene Request-Methoden. Für uns sind zwei von Interesse: GET und POST. Bei jedem normalen Seitenaufruf wird ein GET-Request gesendet. Das kann mit dem Aufruf einer Seite über die Adresszeile Ihres Browsers geschehen, oder durch das Anklicken eines Links. Möchten Sie Daten mit einem Formular übermitteln, können Sie zwischen den Methoden GET und POST wählen. Die Methode GETGET-Requests haben keinen Nachrichten-Body. Sollen trotzdem Daten übertragen werden, so werden sie mit Name-Wert-Paaren hinter einem Fragezeichen an den Pfad in der Request-Zeile angehängt. Ein URL kann aber nur eine begrenzte Zeichenanzahl enthalten. Die Länge ist abhängig vom Browsertyp und von der Konfiguration des Webservers. Die Methode POSTMit der Methode POST werden alle Daten im Nachrichten-Body übermittelt, ebenfalls in Form von Name-Wert-Paaren. Die Größe des Nachrichten-Bodys ist im Request-Header angegeben und kann unbegrenzt groß sein. Die Request-ZeileIn der Request-Zeile stehen die drei wichtigsten Informationen des Requests: o die Request-Methode, o der Pfad zur Ressource und o die verwendete Version des HTTP-Protokolls.
Methode Pfad zur Ressource HTTP-Version GET /index.html HTTP/1.1 POST /index.html HTTP/1.1 Aufbau eines Request-HeadersEin Header enthält beliebig viele Zeilen in Form von „Name: Wert“-Paaren, z. B. GET /index.html HTTP/1.1 Host: localhost:80 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.1) Gecko/20020826 Accept:text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8, video/xmng,image/png,image/jpeg,image/gif;q=0.2,text/css,*/*;q=0.1 Accept-Language: en-us, en;q=0.50 Accept-Encoding: gzip, deflate, compress;q=0.9 Accept-Charset: ISO-8859-1, utf-8;q=0.66, *;q=0.66 Keep-Alive: 300 Connection: keep-alive Gebräuchliche Header-Felder sind in der folgenden Tabelle aufgeführt:
8.4.2 Der ResponseDer Server gibt als Antwort einen HTTP-Response zurück. StatuszeileIn der Statuszeile werden die wichtigsten Informationen des Requests übermittelt. Sie besteht aus drei Informationsfeldern: o HTTP-Version o Status-Code: dreistelliger ganzzahliger Code, der anzeigt, ob der Request erfüllt werden konnte o optionale Text-Version des Status-Codes
HTTP-Version Status Text HTTP/1.1 200 OK HTTP/1.1 404 nicht gefunden Aufbau eines Response-HeadersEin Header enthält beliebig viele Zeilen in Form von „Name: Wert“-Paaren. HTTP/1.1 200 OK Content-Type: text/html Content-Length: 8452 Date: Mon, 10 Nov 2003 12:12:02 GMT ETag: "4857-2037766483043" Server: Apache /1.3.9 (UNIX) Last-Modified: Fri, 20 Jun 2003 11:20:43 GMT
<!doctype html public "-//w3c//dtd html 4.0 transitional//en"> <html> <body> .... </body> </html> Gebräuchliche Header-Felder sind in der folgenden Tabelle aufgeführt:
8.5 CGI-UmgebungsvariablenDas CGI stellt Variablen zur Verfügung, mit denen Einzelheiten über den Request ausgelesen werden können. Alle zur Verfügung stehenden Variablen können Sie mit dem kleinen Skript cgi_variablen.pl aufrufen. Ihre Testumgebung auf Windows sollte ohne Angabe der Shebang-Zeile das Skript ausführen. Geschieht das nicht, geben Sie in der Shebang-Zeile den absoluten Pfad zum Perl-Interpreter ein. use strict; print "Content-type: text/html\n\n";
print "<h1>Anzahl der Umgebungsvariablen insgesamt: ".scalar keys(%ENV)."</h1>";
foreach(sort (keys (%ENV))) { print "<p><b>$_:</b> $ENV{$_} </p>\n\n"; } þ Speichern Sie das Skript im Verzeichnis cgi-bin oder in einem Ordner im cgi-bin-Verzeichnis. þ Rufen Sie das Skript direkt im Browser auf, der Pfad zum cgi-bin-Verzeichnist lautet: http://localhost/cgi-bin/.
Sie können das Skript auch über einen Link in einer HTML-Seite ansprechen. Hier ist eine HTML-Seite, cgi_variablen.html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html> <head> <title>CGI-Umgebungsvariablen</title> </head>
<body> <a href="http://localhost/cgi-bin/cgi_variablen.pl"> CGI-Umgebungsvariablen</a </body> </html>
Sie erhalten beide Male einen Überblick über die bei Ihnen verfügbaren CGI-Variablen. 8.6 Daten versenden mit HTML-FormularenEine übliche Methode, im Internet Daten zu übermitteln, ist die Abfrage von Eingaben durch Formulare. Ein ganz einfaches HTML-Formular befindet sich in der Datei formular.html. Wichtig ist folgender Codeschnipsel: <h1>Formular mit GET</h1> <form action="http://localhost/cgi-bin/Kap08/daten_lesen.pl" method="get"> <p>Ihr Vorname:<br> <input type="text" name="vorname"></p> <p>Ihr Nachname:<br> <input type="text" name="nachname"></p> <p><input type="radio" name="geschlecht" value="frau">Ich bin weiblich <input type="radio" name="geschlecht" value="mann">Ich bin männlich</p> <input type="submit" value=" Senden mit get "> </form>
<h1>Formular mit POST</h1> <form action="http://localhost/cgi-bin/Kap08/daten_lesen.pl" method="post"> <p>Ihr Vorname:<br> <input type="text" name="vorname"></p> <p>Ihr Nachname:<br> <input type="text" name="nachname"></p> <p><input type="radio" name="geschlecht" value="frau">Ich bin weiblich <input type="radio" name="geschlecht" value="mann">Ich bin männlich</p> <input type="submit" value=" Senden mit post "> </form> Ein Formular wird definiert mit dem Element form <form action="http://localhost/cgi-bin/Kap08/daten_lesen.pl" method="post"> ... </form> Das Attribut action enthält als Wert den URL des Skriptes, dem die Inhalte gesendet werden. Das Attribut method definiert die Request-Methode, also GET oder POST. Ein Eingabefeld wird definiert durch das Element input. Das Attribut type definiert den Typ des Eingabefeldes, z. B. Textfeld, Radiobutton oder Absendebutton. <p>Ihr Vorname:<br> <input type="text" name="vorname"></p> Das Attribut name definiert den name-Parameter des Wertes, der versendet wird. Mit dem Attribut value kann man ein Textfeld vorbelegen oder den Wert eines Radiobuttons definieren. Wird beim Textfeld keine Vorbelegung gewählt, so gilt der eingegebene Text als Wert. Versandt werden die Daten mit einem submit-Button. <input type="submit" value=" Senden mit get "> Es ist ein input-Tag, der mit dem Attribut type="submit" als Button dargestellt wird. Die Schrift auf dem Button kann mit dem Attribut value vorgegeben werden. Geben Sie einen Namen, z. B. Nixe, in das Textfeld Vorname ein. Es wird der Daten-String vorname=Nixe versandt. Alle Namen-Wert-Paare werden mit einem kaufmännischen & als String hintereinander gehängt: vorname=Nixe&nachname=Meerfrau&geschlecht=frau
Wird das Formular mit der Methode GET versendet, werden die Daten mit einem ? an den URL in der Requestzeile angehängt und landen in der CGI-Umgebungsvariablen QUERY_STRING.
Wird die Methode POST benutzt, stehen keine Daten im Adressfeld des Browsers, denn sie werden im Nachrichten-Body des Requests übermittelt.
8.6.1 Auslesen des RequestsMit dem Skript daten_lesen.pl können die Daten aus dem HTML-Formular gelesen werden. # Daten einlesen und einer Variablen zuordnen $daten = <>;
# Content-type der zurückzugebenden Datei angeben print "Content-type: text/plain\n\n";
# Variablen ausgeben print "REQUEST_METHOD: $ENV{REQUEST_METHOD}\n"; print "QUERY_STRING : $ENV{QUERY_STRING}\n"; print "Daten im Request-Body: $daten\n"; GETWird dieses Skript in formular.html als Adresse angeben, erhalten Sie nach dem Absenden mit GET folgende Meldung:
POSTNach dem Absenden mit POST erhalten Sie
8.6.2 Den Datenstrom analysierenSie haben die Daten nun in einem langen String mit Sonderzeichen, beispielsweise das & für die Trennung der Name-Wert-Paare. Und was ist mit den Sonderzeichen der deutschen Sprache? Wie werden ä, Ä, ß usw. übermittelt? Ein Text mit formular_text.html gibt Aufschluss.
Die Formularangaben ergeben den Datenstrom name=Nixe+Meer&text=Ein+Text%2C+nicht+sch%F6n%0D%0Aaber+auf o name und value werden als Name-Wert-Paar durch ein Gleichheitszeichen (=) getrennt. o Formularfelder werden durch ein kaufmännisches und (&) voneinander getrennt. o Leerzeichen zwischen Wörtern werden durch ein Pluszeichen (+) gekennzeichnet. o
Zeichen mit ASCII-Werten 128 bis 255 werden durch Hexadezimalzeichen
umschrieben und mit % maskiert. Die Hexadezimalzeichen sind abhängig vom
verwendeten Zeichensatz. Für ISO-8859-1 beispielsweise finden Sie folgende
Zeichen: o Alle Steuerzeichen und Sonderzeichen wie &, +, =, %, Zeilenumbruch etc. werden ebenfalls hexadezimal umgeschrieben.
Sie können diesen String mithilfe der RA auseinander nehmen, oder Sie nutzen gleich die Möglichkeiten des Moduls CGI.pm – im nächsten Kapitel. 8.7 SicherheitPerl ist ein effektives Werkzeug für viele Aufgaben. Wenn Sie aber CGI-Programme erstellen, dann müssen Sie auch die Sicherheit der Skripte bedenken. Ein CGI-Skript auf einem Webserver ist für jeden zugänglich – das ist der Sinn, aber darin liegt auch die Gefahr. Die Skripte nehmen Eingaben von außen auf und sind damit ein natürliches Sicherheitsloch für Hacker: o Dateien auf dem Server können ausgelesen werden. o Shell-Kommandos können ausgeführt werden und z. B. ganze Verzeichnisse löschen. o Andere Programme können gestartet werden. o Der Server kann durch „Überbelastung“ zum Stillstand gebracht werden.
Als Anfänger ist es schwer, mit einer abstrakten Verhaltensliste umzugehen. Deshalb werden Sie in den nächsten Kapiteln immer darauf hingewiesen, wann und wo eine Sicherheitsvorkehrung zu treffen ist. Die wichtigsten Sicherheitslöcher werden erklärt, so dass Sie zum Schluss auch mit den nicht behandelten Punkten dieses Abschnitts etwas anfangen können. Perl hat einen „Tainted Modus“, der mit –T hinter der Shebang-Zeile aufgerufen wird. Im Tainted Modus werden alle Eingaben von außen wie rohe Eier behandelt. Eingaben, die für sicherheitsrelevante Funktionen verwendet werden, werden als tainted, d. h. „befleckt, verschmutzt“, angesehen und müssen vorher mit RA geprüft werden. Die Variablen können „gereinigt“ werden, wenn sie wie in Abschnitt 6.4 mit RA verglichen und in RA-Variablen gespeichert werden. Der -T-Modus ist gerade am Anfang eine empfehlenswerte Hilfestellung, aber er löst nicht alle Probleme. Leider ist er auch nur auf UNIX/Linux-Umgebungen immer verfügbar. Auf Mac oder auf älteren Betriebssystemen wie Windows 98 oder NT 4.0 gibt es Schwierigkeiten mit der Interpretation der Shebang-Zeile. Bei den folgenden Beispielen lernen Sie schrittweise gefährliche Situationen zu erkennen und einzuschätzen. Danach ist auch die Dokumentation unter perlsec „Perl security“ leichter zu verstehen. o Trauen Sie nicht allen Programmen, die im Internet angeboten werden. OpenSource und kommerzielle Programme haben immer wieder Sicherheitslöcher. Werfen Sie einen Blick auf die Sicherheits-Mailingliste BugTrack http://msgs.securepoint.com/bugtraq/. Dort können Sie gezielt nach Programmen suchen. o Geben Sie so wenig wie möglich Informationen über Ihr Skript nach außen: Vermeiden Sie die Ausgabe von Fehlern und Warnungen in den Browser, wenn das Skript im Einsatz ist. o Alle Funktionen, die mit dem Betriebssystem interagieren und dabei Eingaben von außen verarbeiten, sind mit Vorsicht zu behandeln. Dazu gehören: open(), system(), exec(). Außerdem Vorsicht bei der Verwendung von eval(). o Trauen Sie der Umgebungsvariable PATH nicht blind, auch die Umgebungsvariablen können mit einigem Aufwand gehackt werden. o Ganz grundsätzlich gilt: Traue niemals den Angaben von außen! Überprüfen Sie die Eingaben! Vorsicht auch bei der Erstellung von Dateien mit Eingaben von außen.
Einen umfassenden Überblick zum Thema Sicherheit bekommen Sie in dem Buch "hackerz book" von Thomas Vosseberg aus dem Franzis' Verlag, ISBN 3-7723-6346-6. Das Kapitel Websicherheit ist für Web-Programmierer besonders aufschlussreich. 8.8 Von der Testumgebung auf den ServerNachdem Sie Ihre Skripte entwickelt haben, werden Sie die Programme bei einem Provider auf den Server spielen. Ist dieser Server ein UNIX-Server, müssen Sie Rechte setzen. Als Windows-Nutzer ist das zuerst ungewohnt. In UNIX/Linux-Umgebungen wird durch eine Rechtevergabe geregelt, welche Nutzer was mit den Dateien machen dürfen. Eine Datei kann diese Rechte besitzen:
Es wird unterschieden, wer der Anwender ist. Durch das Einloggen ins System werden die Nutzer zugeordnet; die jeweiligen Gruppen erstellt der Systemadministrator. o user/Eigentümer – derjenige, der die Dateien angelegt hat. o group/Gruppe – diejenigen, die mit ihm in einer Gruppe eingeordnet wurden. o others/alle anderen – auch world oder Welt genannt.
Haben Sie Providers z. B. mit einem SSH-Programm und so direkten Zugriff auf den Rechner Ihres Providers, können Sie mit dem Befehl chmod die Rechte vergeben. Die Angabe kann symbolisch: # wer = User, # wie = erteilen +, entziehen -...,
chmod [-R] [wer]wie[was] Dateiname chmod u+rwx datei.txt; oder numerisch erfolgen: chmode 750 Dateiname FTP-Programme bieten eine komfortable grafische Darstellung an.
Achten Sie auf die numerische Darstellung der Zugriffsrechte: 666. Mit dem An- und Abwählen der Rechte für die einzelnen Nutzer werden die numerischen Werte der Rechte addiert oder subtrahiert. Nicht alle FTP-Programme können die Rechte von einzelnen Dateien ändern, manchmal werden gleich die Rechte eines ganzen Ordners geändert. Nehmen Sie SmartFTP, so haben Sie ein Maximum an Kontrollmöglichkeiten.
8.8.1 Das cgi-bin-VerzeichnisDas cgi-bin-Verzeichnis sollte eigentlich das einzige Verzeichnis sein, in dem Skripte ausführbar sind. Auf einer gemieteten Domain existiert es allerdings selten. Fast immer können Sie Skripte in jedem Ordner Ihrer Domain ausführen. Das hindert Sie aber nicht daran, trotzdem ein cgi-bin-Verzeichnis anzulegen. Einfach, um einen guten Überblick zu behalten. 8.8.2 Rechte setzen für Dateien auf Ihrer DomainWelche Rechte Sie für die Dateien auf Ihrer Domain einstellen müssen, hängt von den Voreinstellungen ab, die Ihr Host eingestellt hat. HTML-Dateien müssen nur lesbar sein, aber manchmal gilt 444, da „other = Internet“ interpretiert wird. Bei anderen Hosts wird die group als Internet interpretiert und es reicht 440. Wenn Sie Ihre Dateien per FTP überspielen, bekommen die Dateien Standardrechte gesetzt. Welche das sind, hängt auch von Ihrem Provider ab. Wichtig ist nur: Setzen Sie Ihre Rechte nicht auf 777 hinauf, erlauben Sie nicht jedem alles. Dateien, die von Ihren Skripten angelegt werden, erhalten ebenfalls automatisch Rechte. Meistens 666, also lesen und schreiben für user, group und other. Bei manchen Providern haben Sie nicht allzu viel Kontrolle über Ihre Dateien. Oft benötigen Sie auch auf UNIX keine Shebang-Zeile zum Interpreterstart. Auch bei renommierten Providern ist es schon vorgekommen, dass Skripte auch ausführbar sind, obwohl Sie ihnen kein Recht dazu gegeben haben. Das sollte nicht sein und hängt von Konfigurationen ab, die Ihr Provider verwaltet. Informieren Sie Ihren Provider darüber, denn das ist eine Sicherheitslücke. Wenn Sie beispielsweise halb fertige Skripte ohne ausführende Rechte über Nacht liegen lassen, dürfen die Skripte auf keinen Fall ausführbar sein. Testen Sie am besten genau, wie Ihre Domain eingestellt ist. Und dran denken: Halb fertige Skripte gehören eigentlich sowieso nicht an die Öffentlichkeit, sondern in Ihre Testumgebung. 8.9 SSI – Dynamische Webseiten ohne Programmierung[ Bitte im Buch weiterlesen :-) ]
|