You are here: Wissensbasis Web>UtilFaqInclude>CgiSicherheit (2008-07-24)

Einiges zum Thema CGI-Sicherheit

Inhalt:

Ok, nachdem es im Forum tagelang nur im Kreis ging, fange ich einfach mal an...
Dieser Wiki-Artikel wird einiges zum Thema "Wie mache ich meine CGI-Skripte sicherer?" beinhalten. Da das aber ein sehr breit gefächertes Thema ist, ist es unmöglich alles aufzuschreiben. Aber jeder ist dazu eingeladen, Tipps hier einzupflegen...

-- ReneeBaecker

Ein guter Lesehinweis ist auch perldoc perlsec ...

Benutzereingaben

Es gibt einen Grundsatz, den man immer berücksichtigen sollte:
Traue keiner Benutzereingabe!

Als Programmierer sollte man immer denken "Der User will mir schaden". Man sollte also eine gesunde Paranoia entwickeln...

CGI.pm

Als allererstes sollte man das Modul CGI.pm verwenden. Es nimmt einem viel Arbeit ab und reduziert so die Fehlerwahrscheinlichkeit. Das Modul wird schon seit einigen Jahren entwickelt und hat somit einen sehr guten Stand.

Taint-Modus

Man sollte das Skript immer im Taint-Modus laufen lassen. Dazu wird perl beim Aufruf die Option -T mitgegeben. Unter UNIX/Linux geht das einfach in der Shebangzeile am Anfang des Skriptes:
#!/usr/bin/perl -T
...
In diesem Modus sorgt Perl dafür, dass Eingaben, die aus der "bösen Außenwelt" kommen, automatisch als "tainted" (befleckt) markiert werden und in kritischen Funktionsaufrufen nicht verwendet werden können. Das Tainting funktioniert allerdings nicht automatisch bei der Verwendung von XS/C-Modulen, hier ist Vorsicht geboten.

Leider gibt es hier einen Unterschied zwischen Linux und Windows. Bei Windows bringt es nichts, wenn das -T im Shebang steht, weil die Shebangzeile nicht vor dem Aufruf des Interpreters ausgewertet wird. Die Option muss schon beim Starten des Interpreters bekannt sein. Irgendwo in der Webserverkonfiguration (je nach Webserver) muß man festlegen, wie dieser mit der Endung .pl (o.ä.) umgehen soll. Dort schreibt man dann nicht C:\perl\bin\perl.exe ..., sondern eben C:\perl\bin\perl.exe -T .... Blöd daran ist nur, daß die Einstellung dann für alles, bzw. wenn möglich, für den so konfigurierten Teil gilt. Aber weil man -T bekanntlich sowieso immer anwenden soll, ist es auch wieder kein Problem.

HTML und BBCode

Injizierter HTML- und Javascript-Code kann zu Angriffen auf die Client-Seite einer Anwendung verwendet werden. Wenn man gewisse HTML-Elemente zulassen will (z.B. in einem Forum), ist es geschickt, eines der BBCode-Module von CPAN zu benutzen. So kann man alle HTML-Elemente, die der Benutzer direkt eingibt, "unschädlich" machen, z.B. mit HTML::Entities.

HTML-Escaping

Die Template-Module HTML::Template und HTML::Template::Compiled bieten auch die Möglichkeit, ein "default_escape" zu setzen. Ist das der Standard-Wert auf 'html' eingestellt, werden automatisch bei allen Parametern die Sonderzeichen umgewandelt in Entities. Das vereinfacht das Verhindern von XSS.

Datenbanken

Das DBI-Modul bietet die wunderbare Möglichkeit, die ?-Notation (Platzhalter) zu verwenden. Damit werden automatisch alle Sonderzeichen gequotet und die Möglichkeit des Injizierens von SQL-Code verhindert. Siehe auch "Placeholders and Bind Values" in perldoc DBI. Weiterhin gibt es eine (experimentelle) Möglichkeit, Ein- und Ausgabewerte als "tainted" zu markieren (Optionen TaintIn?, TaintOut?, Taint). Zu diesen Optionen ist zu sagen, dass sich TaintIn? z.b. auch bei Platzhaltern beschwert, bei denen eigentlich nichts passiert. Benutzt man diese Optionen, muss man also zusätzlich zu den Platzhaltern jede Variable untainten.

Öffnen einer Datei

Grundsätzlich sollte man nicht den User bestimmen lassen, wie der Dateiname lautet. Man sollte eigentlich immer selbst festlegen, wie die Datei heißt und wo sie hingespeichert wird.

Außerdem ist die Drei-Parameter-Form von open() (also open (FILEHANDLE, ">", $dateiname)) sicherer, da das Umlenkungszeichen damit eindeutig festgelegt wird. Beim Verwenden des Taint-Modus wird man automatisch vor der Verwendung von unsicheren Dateinamen geschützt.

Öffnen einer Pipe

Wenn z.B. mit sendmail eine E-Mail verschicken werden soll, wird gerne der typische Fehler gemacht, die E-Mail-Adresse des Empfängers direkt in die Kommandozeile zu schreiben:

open PIPE, "|/usr/lib/sendmail $empfaenger";

Was fällt auf? Genau, $empfaenger ist hier vermutlich eine Benutzereingabe. Der sollten wir niemals trauen. In die Kommandozeile gehören nur selbst festgelegte Parameter. Den Empfänger kann man auch mit der Option -t und einer "To:"-Zeile bestimmen.

# Etwas besser, aber noch nicht gut:
open PIPE, "|/usr/lib/sendmail -t" or die $!;
print PIPE <<EOM;
To: $empfaenger
Subject: Blubber

Hallo $name,
usw.
EOM
...

Aber auch das ist nicht sicher. Denn erstens kann $empfaenger oder $name mehrere Zeilen beinhalten, die noch ein paar zusätzliche Header-Zeilen wie z.B. "Bcc: boeser_bube@domain.example" beinhalten kann oder auch eine komplette E-Mail hinzufügen kann. sendmail betrachtet eine E-Mail als fertig, wenn im Body der Punkt alleine auf einer Zeile vorkommt.

Also, Usereingaben gehören auch nicht ungeprüft in den Header einer E-Mail, und sendmail startet man mit der Option "-oi", die das mit dem erwähnten Punkt verhindert.

# Prüfe $empfaenger auf Gültigkeit, z.B. mit Email::Valid
# Ersetze stumpf alle unerwünschten Zeichen:
$empfaenger =~ tr/\r\n\t\f\0//d;
open PIPE, '|-', '/usr/lib/sendmail -t -oi' or die $!;
print PIPE <<EOM;
From: test@test.com
To: $empfaenger
Subject: Blubber

Hallo $name,
usw.
EOM
...

Haeufig kann man solche Pipe-Verwendungen vermeiden, indem man z.B. auf Module zurueckgreift. Im Fall von "Mails versenden" kann man z.B. das Mail::Sender-Modul benutzen.

Verwendung von eval

Man sollte im Allgemeinen auf String-evals mit Daten aus unsicheren Quellen verzichten, da der String eine "böse" Zeichenfolge beinhalten könnte. Auch hier wird man im Taint-Modus geschützt.

Wenn doch ein String-eval mit unbekannten Inhalt verwendet werden soll, kann man auf das Module Safe zurückgreifen, mit dem man bestimmte Perl-Funktionen (Opcodes) erlauben oder ausschalten kann. Es ist allerdings möglich, dass Safe Sicherheitslücken hat!

Neueste Perl-Version

Auch das Perl-Binary kann typische, aus der C-Welt bekannte Fehler wie Buffer Overflows enthalten. Deshalb sollte man möglichst die neueste Perl-Version verwenden. Bei kritischen Bugfixes werden auch die älteren Stränge (5.6.x, 5.003_xx) aktualisiert.

Weitere CPAN-Module für CGI-Programmierung

Weiterführende Links

CGI-Sicherheit

Sicherheitsprobleme durch Javascript
Cross Site Scripting (XSS) und Cross-Site Request Forgery (XSRF)

Es gibt noch mehr Links, die ich aber auf Grund der unklaren deutschen Rechtslage hier nicht einfüge. (GwenDragon?)

Ergänzungen, Kommentare

Text ergänzt, Umlaute eingefügt. -- PlTk - 28 Dec 2005
-- HaraldBongartz - 30 Dec 2005
Links hinzugefügt -- GwenDragon - 21 Jul 2008, 23 Jul 2008

UtilFaqSubForm edit

Titel Einiges zum Thema CGI-Sicherheit
Autor ReneeBaecker
Bereich FaqCGI
Tags CGI, Sicherheit
Topic revision: r15 - 2008-07-24 - 16:21:00 - TinaMueller
 
Bitte die NutzungsBedingungen beachten.
Bei Vorschlägen, Anfragen oder Problemen mit dem PerlCommunityWiki bitten wir um WebBottomBarExample">Rückmeldung.