Zusammenfassung

  • CGI/1.1 beschrieb eine gemeinsame Anfrage- und Antwortübergabe zwischen HTTP-Server und Skript, ließ manche Einzelheiten aber system- oder implementierungsabhängig.
  • RFC 3875 verortete TLS zwischen Client und Server: Der Server wurde gegenüber dem Client authentisiert, während das Skript weder einen eingebauten Nachweis seines Aufrufers noch Integritätsschutz für CGI-Nachrichten erhielt.

Die Verbindung ist geschützt. Die Anwendung sitzt deshalb noch nicht am anderen Ende.

Das ist die unscheinbare Grenze in RFC 3875, der Common Gateway Interface (CGI) Version 1.1 von 2004. Ein Browser kann TLS mit einem Webserver aufbauen. Der Server kann danach Anfragedaten an ein CGI-Programm übergeben. Doch die von der RFC beschriebene Sicherheitsbeziehung reicht nicht unverändert über diese zweite Übergabe hinaus. Der Server ist der Netzwerkpartner; das Skript ist ein dahinterliegender Anwendungsprozess.

CGI leistete schon lange vor RFC 3875 praktische Dienste. Ein HTTP-Server konnte als Gateway zu einer Datenbank oder einem anderen bestehenden Informationssystem dienen, während ein Skript aus der Anfrage eine Antwort erzeugte. Die historische CGI-Seite des W3C beschreibt die Schnittstelle als Vereinbarung zwischen Server-Implementierern zur Integration solcher Gateway-Skripte und -Programme. Sie verzeichnet einen Aktualisierungsversuch für CGI 1.1 von 1995 und die im November 1997 wiederaufgenommene Arbeit, aus der De-facto-Schnittstelle eine informative RFC zu machen. Der endgültige Text erschien im Oktober 2004 im Independent Stream.

Die Zeitspanne ist weniger eine Anekdote über Standardisierung als ein Hinweis darauf, was die Spezifikation festhalten sollte. CGI war bereits gelebte Praxis. RFC 3875 erfand keine dynamischen Webanwendungen; sie formulierte einen portablen Vertrag für eine Anfrage, die vom netzwerkseitigen Server in ein Anwendungsprogramm gelangen musste.

Der Vertrag benennt Anfrage-Metavariablen wie REQUEST_METHOD, QUERY_STRING, CONTENT_LENGTH, PATH_INFO und REMOTE_ADDR. Er definiert, wie ein Skript Header und Body zurückgibt, einschließlich Dokument- und Redirect-Antworten. Programme auf unterschiedlichen Servern erhalten damit ein gemeinsames Vokabular. Zugleich verteilt der Text die Aufgaben: Der Server kümmert sich um Clientverbindung, Datentransfer und Netzwerkprotokoll; das Skript übernimmt Anwendungsarbeit wie Datenzugriff und Dokumentverarbeitung.

Diese Aufteilung überträgt die Pflichten des Servers nicht. RFC 3875 sagt, dass der Server dem Client gegenüber für die Einhaltung des Netzwerkprotokolls verantwortlich bleibt, selbst wenn das Skript nicht spezifikationskonform arbeitet. Wendet der Server Authentisierung an, darf er das Skript außerdem erst ausführen, wenn die Anfrage die festgelegten Zugriffskontrollen bestanden hat. Der Server ist kein durchsichtiges Rohr, das für eine fehlerhafte Antwort oder eine übersprungene Schranke seinem Kindprozess die Schuld geben kann.

Abschnitt 9.4 zieht dann die Vertrauensgrenze enger. Bei einer TLS-Clientverbindung gilt das Sicherheitsmodell zwischen Client und Server, nicht zwischen Client und Skript. Der Server wird gegenüber dem Client authentisiert. Die Spezifikation gibt dem Skript keinen Mechanismus, den aufrufenden Server zu authentisieren, und erzwingt keine Integrität der CGI-Anfrage- und Antwortnachrichten.

Das heißt weder, dass das Skript grundsätzlich als feindlich gelten muss, noch dass Betreiber die lokale Prozessgrenze nicht schützen können. Ein Server kann Betriebssystemrechte, einen privaten Kanal oder andere lokale Kontrollen nutzen. Der engere Punkt lautet: TLS am HTTP-Rand authentisiert das nachgelagerte Skript nicht von selbst als denselben Netzwerkpartner. Erhält ein Skript HTTPS=on oder einen Benutzernamen in seiner Umgebung, bekommt es Werte; die CGI-Schnittstelle liefert keinen kryptografischen Nachweis, der diese Werte an eine authentisierte Clientsitzung bindet.

Die Architektur legte sich nicht auf ein Prozessmodell fest. RFC 3875 beschreibt einen Kindprozess unter Benutzer und Gruppe des Servers als häufigste Implementierung, erkennt aber auch direkt in den Server eingebundene Skripte an. Der Text unterscheidet zwischen systemdefiniertem und implementierungsdefiniertem Verhalten. Die gemeinsame Schnittstelle ließ sich zwischen Servern übertragen, ihre Portabilität hatte jedoch Grenzen.

Apaches mod_cgi-Dokumentation ist ein Implementierungsbeispiel, keine Bestandsaufnahme des Webs. Sie zeigt, wie eine Serverfamilie Skripte über Handler oder ScriptAlias auswählt und deren Ausgabe an Clients zurückgibt. Das veranschaulicht die Übergabe, ändert aber weder die RFC-Aussage zum TLS-Endpunkt noch belegt es die Konfiguration aller Server.

Der historische Beitrag von CGI war eine gemeinsame Grenze, kein gemeinsamer Prozess und kein Ende-zu-Ende-Sicherheitskanal. Server und Skript konnten über eine benannte Schnittstelle zusammenarbeiten und blieben dennoch getrennte Akteure mit unterschiedlichen Pflichten. So gelesen verhindert die RFC einen Kategorienfehler: Eine geschützte Anfrage zwischen Browser und Server wird nicht automatisch zu einer geschützten Beziehung zwischen Browser und Anwendung. RFC 3875 machte die Trennung sichtbar; sie hob sie nicht auf.

Quellen