What is a Common Getaway Interface (CGI)?

Common Gateway Interface (CGI) ist ein Schnittstellenprotokoll, das es Webservern ermöglicht, eine externe Anwendung auszuführen, häufig zur Bearbeitung von Benutzeranfragen.

Solche Anwendungen sind in der Regel in einer Skriptsprache geschrieben, die als CGI-Skripte bezeichnet wird, können aber auch aus kompilierten Programmen bestehen.

Ein typisches Beispiel ist, wenn ein Webnutzer ein Webformular auf einer CGI-fähigen Webseite absendet. Die Daten aus dem Formular werden als Teil einer HTTP-Anfrage mit einer URL, die ein CGI-Skript identifiziert, an den Webserver gesendet. Der Webserver startet dann das CGI-Skript in einem neuen Prozess und übergibt die Formulardaten. Das CGI-Skript sendet die Ausgabe, typischerweise im HTML-Format, an den Webserver zurück, der sie dann an den Browser übermittelt, um dessen Anfrage zu beantworten.

CGI, das Anfang der 1990er Jahre entwickelt wurde, war der erste weltweit eingesetzte Ansatz, um Webseiten interaktiv zu gestalten. Obwohl es immer noch verwendet wird, ist CGI im Vergleich zu neueren Technologien ineffizient, was der Grund für seine Ablösung ist.


Wann wurde es erfunden?


In der Mailingliste „www-talk“ legte 1993 ein Team des National Center for Supercomputing Applications (NCSA) den Standard für den Aufruf von Befehlszeilenprogrammen fest. Andere Webserver-Entwickler fanden schnell Akzeptanz dafür, und seitdem ist es ein Standard für Webserver geblieben. Im November 1997 leitete Ken Coar eine Arbeitsgruppe, um die NCSA-Definition von CGI zu formalisieren. Diese Arbeit mündete in RFC 3875, der CGI Version 1.1 definiert. Der RFC nennt ausdrücklich die folgenden Mitwirkenden:

• Rob McCool (Autor des NCSA HTTPd-Webservers) • John Franks (Autor des GN-Webservers) • Ari Luotonen (Entwickler des CERN httpd-Webservers) • Tony Sanders (Autor des Plexus-Webservers) • George Phillips (Betreuer des Webservers der University of British Columbia)

Früher, als CGI-Programme entwickelt wurden, geschah dies in der Regel in der Programmiersprache C. RFC 3875, „The Common Gateway Interface (CGI)“, besagt, dass auf Umgebungsvariablen „über die C-Bibliotheksprozedur getenv() oder die Variable environ zugegriffen wird“.

CGI stammt aus den Anfängen des Internets, als Webmaster den Wunsch hatten, bestehende Informationssysteme wie Datenbanken mit ihren Webservern zu verknüpfen. Der Server war derjenige, auf dem die CGI-Software lief, die als „Brücke“ zwischen dem Webserver und dem bestehenden Informationssystem diente.


Zweck der CGI-Spezifikation


Jeder Webserver verwendet HTTP-Software, die auf Anfragen von Webbrowsern reagiert. Der HTTP-Server verfügt oft über ein Verzeichnis (Ordner), das als Dokumentensammlung dient – Elemente, die an mit diesem Server verbundene Webbrowser übertragen werden können. Wenn beispielsweise der Domainname des Webservers example.com lautet und seine Dokumentensammlung im lokalen Dateisystem unter /usr/local/apache/htdocs/ gespeichert ist, antwortet der Server auf Anfragen nach http://example.com/index.html, indem er die (vorab geschriebene) Datei /usr/local/apache/htdocs/index.html an den Browser überträgt.

Bei dynamischen Seiten leitet die Serversoftware Anfragen möglicherweise an verschiedene Programme weiter und sendet die Ergebnisse an den anfragenden Client zurück (meistens ein Webbrowser, der die Seite für den Endnutzer anzeigt). Skripte waren in den Anfängen des Internets beliebt, da sie kompakt waren und in einer Skriptsprache geschrieben wurden.

In der Regel erfordern solche Programme das Hinzufügen zusätzlicher Daten zur Anfrage. Wenn beispielsweise der CooliceHost-Kundenbereich als Skript geschrieben wäre, müsste das Skript wissen, ob der Benutzer angemeldet ist und, falls ja, unter welchem Benutzernamen. Diese Informationen dienen dazu, den Inhalt am Anfang einer CooliceHost-Kundenseite zu bestimmen.

HTTP ermöglicht es Browsern, dem Webserver auf verschiedene Weise Informationen zu übermitteln, beispielsweise durch die Verwendung eines Teils der URL. Diese Informationen müssen dann von der Server-Software auf irgendeine Weise an das Skript weitergeleitet werden. Im Gegensatz dazu muss das Skript bei der Rückgabe alle Informationen bereitstellen, die HTTP für die Beantwortung von Anfragen benötigt: den HTTP-Status der Anfrage, den Dokumentinhalt (falls verfügbar), den Dokumenttyp (z. B. PDF, HTML oder reiner Text) und so weiter.

Früher übertrugen verschiedene Server-Softwareprogramme diese Daten mit Skripten auf unterschiedliche Weise. Selbst wenn die übertragenen Informationen identisch waren, war es daher unmöglich, Skripte zu entwickeln, die für verschiedene Server-Software unverändert funktionierten. Daher wurde beschlossen, eine Methode zur Übertragung dieser Daten festzulegen: CGI (Common Gateway Interface, da es eine einheitliche Schnittstelle zwischen Server-Software und Skripten definiert). CGI-Skripte sind Programme zur Erstellung von Webseiten, die von Server-Software aufgerufen werden und gemäß der CGI-Spezifikation funktionieren.

Diese Spezifikation wurde bald akzeptiert und wird von allen gängigen Server-Softwareprogrammen unterstützt, darunter IIS, Apache und (mit einer Erweiterung) node.js-basierte Server.

CGI-Programme wurden ursprünglich zur Verarbeitung von Formularen eingesetzt. HTML-Formulare enthielten ein „action“-Element und eine Schaltfläche mit der Bezeichnung „submit“ am Anfang des HTML-Codes. Wenn die „submit“-Schaltfläche gedrückt wird, wird die in der „action“-Eigenschaft definierte URI zusammen mit den Formulardaten als Abfragezeichenfolge an den Server übermittelt. Wenn die „action“ ein CGI-Skript angibt, wird dieses ausgeführt und eine HTML-Seite erzeugt.


Verwendung von CGI-Skripten


Der Betreiber eines Webservers kann festlegen, welche CGI-Skripte welche URLs verarbeiten sollen.

Dies wird in der Regel dadurch erreicht, dass ein separates Verzeichnis innerhalb der Dokumentensammlung als Speicherort für CGI-Skripte festgelegt wird – der Name dieses Ordners lautet häufig cgi-bin. Auf dem Webserver könnte beispielsweise /usr/local/apache/htdocs/cgi-bin ein CGI-Verzeichnis sein. Wenn ein Browser eine URL anfordert, die auf ein Dokument im CGI-Ordner verweist (z. B. http://example.com/cgi-bin/printenv.pl/with/additional/path?and=a&query=string), führt der HTTP-Server das angegebene Skript aus und leitet die Ausgabe an den Webbrowser weiter, anstatt einfach diese Datei (/usr/local/apache/htdocs/cgi-bin/printenv.pl) zu senden. Das heißt, alles, was vom Skript an die Standardausgabe gesendet wird, wird an den Web-Client weitergeleitet, anstatt auf dem Bildschirm in einem Befehlsfenster angezeigt zu werden.

Die CGI-Spezifikation beschreibt, wie bereits erwähnt, das Senden zusätzlicher Informationen, die mit der Anfrage an das Skript übermittelt werden. Wenn beispielsweise ein Schrägstrich und zusätzliche Verzeichnisnamen direkt nach dem Skriptnamen an die URL angehängt werden (in diesem Fall /with/additional/path), wird dieser Pfad vor dem Aufruf des Skripts in der Umgebungsvariable PATH INFO gespeichert. Werden Parameter über eine HTTP-GET-Anfrage an das Skript übergeben (ein an die URL angehängtes Fragezeichen, gefolgt von Parameter-Wert-Paaren; zum Beispiel ?and=a&query=string), werden diese vor der Ausführung des Skripts in der Umgebungsvariable QUERY STRING gespeichert. Parameter, die über HTTP-POST an das Skript übermittelt werden, werden an die Standardeingabe des Skripts übergeben. Das Skript könnte dann diese Umgebungsvariablen oder Informationen aus der Standardeingabe empfangen und sich an die vom Webbrowser gestellte Anfrage anpassen.


Beispiel


Das folgende Perl-Programm zeigt alle vom Webserver bereitgestellten Umgebungsvariablen an:

Perl-Programm

Ein 64-Bit-Windows-7-Webserver, auf dem Cygwin läuft, gibt die folgenden Informationen aus, wenn ein Webbrowser die Umgebungsvariablen unter http://example.com/cgi-bin/printenv.pl/foo/bar?var1=value1&var2=with% 20%20encoding anfordert:


64-Bit-Windows-7-Webserver mit Cygwin

Der CGI-Standard definiert einige, wenn auch nicht alle dieser Variablen. Einige, wie PATH, INFO, QUERY STRING und diejenigen, die mit HTTP_ beginnen, übermitteln Informationen aus der HTTP-Anfrage.

Die Umgebung zeigt, dass es sich bei dem Webbrowser um Firefox auf einem Windows 7-PC handelt. Der Webserver ist Apache auf einem Unix-ähnlichen System, und das CGI-Skript heißt cgi-bin/printenv.pl.

Die Anwendung kann dann beliebige Inhalte erstellen und an die Standardausgabe schreiben, die der Webserver anschließend an den Browser sendet.

Die an CGI-Skripte übergebenen Umgebungsvariablen lauten wie folgt:

• Serverspezifische Variablen:

◦ SERVER_SOFTWARE: Name/Version des HTTP-Servers.
◦ SERVER_NAME: Hostname des Servers, kann eine IP-Adresse im Dezimalformat sein.
◦ GATEWAY_INTERFACE: CGI/Version.

• Anfragespezifische Variablen:

◦ SERVER_PROTOCOL: HTTP/Version.
◦ SERVER_PORT: TCP-Port (dezimal).
◦ REQUEST_METHOD: Name der HTTP-Methode (siehe oben).
◦ PATH_INFO: Pfadsuffix, falls an die URL nach dem Programmnamen und einem Schrägstrich angehängt.
◦ PATH_TRANSLATED: Entsprechender vollständiger Pfad, wie vom Server angenommen, sofern PATH_INFO vorhanden ist.
◦ SCRIPT_NAME: Relativer Pfad zum Programm, z. B. /cgi-bin/script.cgi.
◦ QUERY_STRING: Der Teil der URL nach dem Zeichen ?. Der Abfrage-String kann aus *name=value-Paaren bestehen, die durch Und-Zeichen getrennt sind (z. B. var1=val1&var2=val2...), wenn er zum Übermitteln von Formulardaten verwendet wird, die per GET-Methode gemäß der HTML-Spezifikation application/x-www-form-urlencoded übertragen werden.
◦ REMOTE_HOST: Hostname des Clients, nicht gesetzt, wenn der Server keine solche Abfrage durchgeführt hat.
◦ REMOTE_ADDR: IP-Adresse des Clients (Dezimalformat).
◦ AUTH_TYPE: Identifizierungstyp, falls zutreffend.
◦ REMOTE_USER wird für bestimmte AUTH_TYPEs verwendet.
◦ REMOTE_IDENT: siehe ident, nur wenn der Server eine solche Abfrage durchgeführt hat.
◦ CONTENT_TYPE: Internet-Medientyp der Eingabedaten, wenn die PUT- oder POST-Methode verwendet wird, wie über den HTTP-Header bereitgestellt.
◦ CONTENT_LENGTH: analog dazu die Größe der Eingabedaten (dezimal, in Oktetten), sofern über den HTTP-Header bereitgestellt.
◦ Vom User-Agent übergebene Variablen (HTTP_ACCEPT, HTTP_ACCEPT_LANGUAGE, HTTP_USER_AGENT, HTTP_COOKIE und möglicherweise weitere) enthalten die Werte der entsprechenden HTTP-Header und haben daher dieselbe Bedeutung.

Die Software sendet die Ausgabe im Standardausgabeformat an den Webserver, beginnend mit einem Header und endend mit einer Leerzeile.

Der Header ist ähnlich wie ein HTTP-Header kodiert und sollte den MIME-Typ des zurückgegebenen Inhalts angeben. Die vom Webserver bereitgestellten Header werden in der Regel zusammen mit der Antwort an den Kunden zurückgesendet.

Hier ist ein einfaches CGI-Programm, geschrieben in Python 3 und HTML, das eine unkomplizierte Additionsaufgabe bearbeitet.

add.html:

CGI-Programm

add.cgi:

CGI Python 3

Diese Python-3-CGI-Software liest die HTML-Eingaben und addiert die beiden Ganzzahlen.


Bereitstellung


Ein CGI-fähiger Webserver kann so konfiguriert werden, dass er erkennt, ob eine URL als Verweis auf ein CGI-Skript dient. Eine gängige Vorgehensweise besteht darin, einen Ordner „cgi-bin/“ im Stammverzeichnis der Verzeichnisstruktur anzulegen und alle ausführbaren Dateien in diesem Verzeichnis (aus Sicherheitsgründen jedoch keine anderen) als CGI-Skripte zu behandeln. Ein weiterer gängiger Standard ist die Verwendung von Dateinamenerweiterungen; wenn CGI-Skripte beispielsweise immer die Erweiterung .cgi haben, kann der Webserver so eingestellt werden, dass er alle diese Dateien als CGI-Skripte liest. Dies ist zwar nützlich und wird von vielen vorgefertigten Skripten verlangt, setzt den Server jedoch Angriffen aus, wenn ein entfernter Benutzer ausführbaren Code mit der entsprechenden Erweiterung hochlädt.

Die vom Benutzer übermittelten Daten werden im Falle von HTTP-PUTs oder -POSTs über die Standardeingabe an die Anwendung gesendet. Der Webserver erstellt eine Teilmenge der bereitgestellten Umgebungsvariablen und fügt HTTP-spezifische Daten hinzu.


Verwendung


CGI wird häufig verwendet, um Benutzereingaben zu verarbeiten und relevante Ausgaben bereitzustellen. Eine CGI-Anwendung, die ein Wiki implementiert, ist ein Beispiel für ein CGI-Programm. Der Webserver führt die CGI-Anwendung aus, wenn der Benutzer den Namen eines Eintrags anfordert. Die CGI-Software ruft den Quellcode der Seite für diesen Eintrag ab (sofern vorhanden), konvertiert ihn in HTML und gibt das Ergebnis aus. Der Webserver empfängt die Ausgabe des CGI und sendet sie an das Client-Gerät. Die CGI-Software füllt dann ein HTML-Textfeld oder ein anderes Bearbeitungselement mit den Informationen der Seite, wenn der Benutzeragent die Schaltfläche „Seite bearbeiten“ auswählt. Wenn der Benutzeragent schließlich die Option „Seite veröffentlichen“ drückt, speichert die CGI-Software den geänderten HTML-Code als Quellcode der Seite dieses Eintrags.


Sicherheit


CGI-Skripte laufen standardmäßig unter dem Sicherheitskontext des Webservers. Mit der Veröffentlichung des neuen CGI wurden verschiedene Beispielskripte in die Referenzdistributionen der Webserver von NCSA, CERN und Apache aufgenommen, um zu demonstrieren, wie Shell-Skripte oder C-Programme erstellt werden können, um dessen Vorteile zu nutzen. PHF, eine CGI-Software, die ein rudimentäres Telefonbuch entwickelte, war ein solches Beispielskript.

Dieses Skript nutzte, wie viele andere damals, eine Funktion namens escape_shell_cmd(). Sie sollte das Argument angesichts von Benutzereingaben bereinigen und es dann an die Unix-Shell übermitteln, um es in der Sicherheitsumgebung des Webservers auszuführen. Das Skript bereinigte nicht alle Eingaben ordnungsgemäß und ermöglichte es, zusätzliche Zeilen an die Shell zu übergeben, wodurch die Ausführung zahlreicher Befehle möglich wurde. Die Ausgabe dieser Befehle wurde dann auf dem Webserver angezeigt. Die Ausführung böswilliger Befehle durch Angreifer ist möglich, wenn die Sicherheitsumgebung des Webservers dies zulässt.

Dies war das erste weit verbreitete Beispiel für eine neue Form von webbasierten Angriffen, bei denen nicht bereinigte Daten von Webnutzern zur Aktivierung von Code auf einem Webserver führen konnten. Da der Beispielcode standardmäßig eingesetzt wurde, waren Angriffe weit verbreitet, was Anfang 1996 zu zahlreichen Sicherheitswarnungen führte.


Alternativen


Ein Webserver generiert für jede eingehende HTTP-Anfrage einen neuen CGI-Prozess und beendet diesen, sobald die Anfrage bearbeitet wurde. Das Erstellen und Beenden eines Prozesses kann weitaus mehr CPU-Leistung und Arbeitsspeicher beanspruchen als die eigentliche Ausgabeerstellung, insbesondere wenn das CGI-Programm noch von einer virtuellen Maschine geparst werden muss. Die daraus resultierende Last durch zahlreiche HTTP-Anfragen kann den Webserver mühelos überfordern.

Der Aufwand für das Erstellen und Beenden von CGI-Prozessen lässt sich mit den folgenden Techniken verringern:

  • CGI-Programme, die beispielsweise aus C++- oder C-Programmen in Maschinencode vorkompiliert wurden, anstelle von CGI-Programmen, die von einer virtuellen Maschine übersetzt werden, wie beispielsweise Python-, Perl- oder PHP-Programme.
  • Webserver-Erweiterungen wie Apache-Module (z. B. mod_perl, mod_php, mod_python), ISAPI-Plugins und NSAPI-Plugins ermöglichen es, lang laufende Anwendungsprozesse innerhalb des Webservers zu verarbeiten und mehrere Anfragen zu verwalten. Web 2.0 ermöglicht den Datenfluss vom Client zum Server auch ohne die Verwendung von HTML-Formularen und ohne Wissen des Benutzers.
  • SCGI, AJP und FastCGI ermöglichen lang laufende Anwendungsprozesse, die mehrere Anfragen außerhalb des Webservers bearbeiten. Jeder Anwendungsprozess lauscht auf einem Socket; bei dynamischen Inhalten verwaltet der Webserver eine HTTP-Anfrage und überträgt sie über ein anderes Protokoll (SCGI, AJP und FastCGI) an den Socket, während statische Inhalte in der Regel direkt vom Webserver verarbeitet werden. Da diese Methode weniger Anwendungsprozesse erfordert, verbraucht sie weniger Speicher als die Webserver-Erweiterungsmethode. Anwendungsprogramme werden nicht in eine Webserver-Erweiterung umgewandelt, sondern bleiben vom Webserver getrennt.
  • Jakarta EE führt Jakarta-Servlet-Anwendungen in einem Web-Container aus, um dynamische und potenziell statische Inhalte bereitzustellen, wodurch der Overhead beim Erstellen und Löschen von Prozessen zugunsten des deutlich reduzierten Overheads beim Erstellen und Beenden von Threads entfällt. Dadurch erhält der Entwickler zudem Zugriff auf die Java SE-Bibliothek, auf der die aktuelle Version von Jakarta EE aufbaut.

Die geeignete Konfiguration für jede Webanwendung wird durch anwendungsspezifische Details, das Datenverkehrsvolumen und die Komplexität der Transaktionen bestimmt; die Abwägung dieser Kompromisse ist notwendig, um die am besten geeignete Implementierung für eine bestimmte Aufgabe und ein bestimmtes Zeitbudget auszuwählen. Web-Frameworks bieten die Möglichkeit, über CGI-Skripte mit User-Agents zu interagieren.


Was this article helpful?

mood_bad Dislike 2
mood Like 3
visibility Views: 3575733