Sicherheitsaspekte

Problem Lösungsansatz
Den CGI-Server so konfigurieren, dass CGI-Skripte für den Serverbetrieb möglichst wenig Schaden anrichten können. Lesen Sie die Hinweise zur CGI-Umgebung .

Ihre CGI-Skripte müssen in Ihrem cgi-bin-Verzeichnisbaum liegen. CGI-Skripte werden auf dem CGI-Server in einer sogenannten suexec-Umgebung abgearbeitet. Dies bedeutet, dass die Skripte unter dem Account des Skript-Besitzers laufen. Skripte, die nicht dem Besitzer des CGI-Verzeichnisses gehören, werden vom Server nicht abgearbeitet. Damit wird verhindert, dass Ihr Skript in Verzeichnissen und in Dateien, auf denen Sie keinen Zugriff haben, Schaden anrichten kann.

Schreibrechte dürfen nur dem Besitzer eingeräumt werden, ansonsten verweigert der HTTP-Daemon die Abarbeitung des Skriptes. Ihr Skript soll nur von Ihnen selbst verändert werden dürfen. Für die Folgen der Abarbeitung Ihrer CGI-Skripte sind ohnehin alleine Sie verantwortlich.

Bedenken Sie, dass die Skripte im WWW allen zugänglich sind, denen Sie den Zugang erlauben und möglicherweise nicht so genutzt werden, wie Sie dies geplant hatten. Ein unbequemer Zeitgenosse könnte einem CGI-Skript ein mehrere Megabyte großes POSTing schicken. Bei Abarbeitung der param-Methode (bzw. Funktion) wird das gesamte POSTing in eine Variable eingelesen, die daraufhin sehr groß wird und den CGI-Server belastet. Die globale Variable $ENV{'CONTENT_LENGTH'} enthält die Anzahl der mit POST übertragenen Zeichen (des POSTings). Durch Auswertung dieser Variablen können Sie ein Weiterverarbeiten zu großer POSTings verhindern.

Die CGI.pm Variable $CGI::POST_MAX legt eine Obergrenze für POSTings fest. Einheit: Bytes.

Beispiel: Ein POSTing soll auf max 0.5 MB begrenzt werden

$CGI::POST_MAX=1024*500; 

Auch damit lässt sich die Weiterverarbeitung zu großer POSTings verhindern.

Eine andere Angriffsmöglichkeit: Ein WWW-Benutzer schreibt ein eigenes Formblatt und gibt als action Ihr CGI-Skript an. In diesem Formblatt wird z.B. aus einem von Ihnen geplanten Text-Parameter ein File-Upload-Parameter. CGI.pm wird den Upload, der beliebig groß sein kann, in einem temporären Verzeichnis unterbringen, selbst wenn das Skript eigentlich keinen Upload erwartet. CGI.pm löscht diese Datei beim Beenden zwar automatisch, aber in der Zwischenzeit könnte die Platte des Servers vollgelaufen sein und so den Betrieb erheblich behindern. Die globale Variable (aus CGI.pm)
$CGI::DISABLE_UPLOADS 
legt fest, ob Uploads zugelassen sein sollen oder nicht. Wenn Ihr Skript keine Uploads erwartet, sollten Sie den Wert dieser Variablen auf 1 setzen.

Beispiel: Uploads werden untersagt

$CGI::DISABLE_UPLOADS = 1;
Verhindern Sie, dass Ihr Skript von nicht autorisierten HTML-Dokumenten aus ausgerufen wird. Dies erreichen Sie z.B. durch die Auswertung der globalen Variablen $ENV{'HTTP_REFERER'}.

Die unerlaubte Nutzung durch ein nicht autorisiertes Eingabe-Formblatt kann dadurch verhindert werden, dass das Formblatt vom Skript selbst erzeugt wird und dann auch nur Eingaben vom Skript selbst akzeptiert werden.

$MY_URL = "http://cgi.tu-harburg.de" 
        .  $ENV{'SCRIPT_NAME'};
$BACK = $ENV{'HTTP_REFERER'};
if ($MY_URL ne $BACK) {
print "Content-type: text/html\n\n";
print "Zugriff nicht gestattet!<br>";
print "<a href=\"$BACK\">back</a>\n";
exit;
}
Überlegen Sie sich bei der Weiterverarbeitung von Benutzereingaben ganz genau, welche Aktionen - insbesondere durch die Eingabe von nicht-alphanumerischen Zeichen - ausgelöst werden könnten und fangen Sie unerlaubte Eingaben in Ihrem Skript ab.

Durch die Überprüfung der Eingaben muss verhindert werden, dass durch den Eingabetext nicht beabsichtigte Server Side Includes oder PHP-Anweisungen abgearbeitet werden können.
Beispiel:Subroutine VerboteneEingabe in dem Perl-Skript sicherheit.pl.)

Vorschlag für den "Kopf" Ihres Perl-Skriptes:

#!/usr/bin/perl -T
#
# CGI-Routinen laden
  use CGI qw/:standard -private_tempfiles/;
# Fehlermeldungen werden im Browser Window ausgegeben   
  use CGI::Carp qw(fatalsToBrowser);  
# keine Uploads erlaubt        
  $CGI::DISABLE_UPLOADS = 1; 
# max 0.1 MB bei POST-Request         
  $CGI::POST_MAX=1024*100;

# Request-URL ueberpruefen
$MY_URL = "Request-URL angeben";
if ( $MY_URL ne $ENV{'HTTP_REFERER'}) {     
  print "Content-type: text/html\n\n";
  print "Zugriff nicht gestattet!<br>\n";
  print "<a href=\"$ENV{'HTTP_REFERER'}\">go back</a>";
  exit;
}
##
## Es folgen Ihre Perl-Anweisungen
##