CGI / Perl auf Sicherheit testen
alligator
- perl
Hallo zusammen,
ich würd gerne mal mein Perl-Script, die Usereingaben empfangen auf
Sicherheit testen. Deshalb wollt ich mal schauen, was man alles machen kann, wenn der Tainted-Modus nicht aktivert ist.
Dazu folgendes lokales Mini-Testproggi:
use CGI;
$q = new CGI;
$value = $q->param('foo');
print $value;
$value;
Leider hab ich bis jetzt nicht hinbekommen (trotz dieses offenen Scriptes) z.B. nen Systembefehl oder sowas abzusetzen. Ich teste auf Windows...
Z.B.
perl tt.pl foo=exec('dir');
oder
perl tt.pl foo=sleep+10;
hat alles nix gebracht, außer die Ausgaben: exec('dir') und sleep 10.
Hat jemand ne Idee, was ich da falsch mache ?
cya
alligator
Hi,
hat alles nix gebracht, außer die Ausgaben: exec('dir') und sleep 10.
Hat jemand ne Idee, was ich da falsch mache ?
Ja. exec() ist nicht dafür da, einen systembefehl auszuführen, sondern um ein anderes Programm auszuführen, das ist ein Unterschied. Was du suchst sind backticks `` oder besser system().
Was fürs nächste auch mal wichtig wäre, dass du Fehlermeldungen hier auch postest. Da hilft es dir die Warunungen einzustellen (entweder mittels -w in der Shebang oder use warnings).
Grüße Andres Freund.
Halihallo alligator
ich würd gerne mal mein Perl-Script, die Usereingaben empfangen auf
Sicherheit testen. Deshalb wollt ich mal schauen, was man alles machen kann, wenn der Tainted-Modus nicht aktivert ist.
Der Tainted-Modus erhöht die Sicherheit nicht, das kannst _alleine_ du. Er stellt nur
sicher, dass du die externen Daten (eg. über Kommandozeile) über eine RegExp prüfst,
ob der Inhalt "sinnvoll" ist (bezgl. der Sicherheit z.B. keine Pipes enthält, womit
man sonst was tun könnte).
Leider hab ich bis jetzt nicht hinbekommen (trotz dieses offenen Scriptes) z.B. nen Systembefehl oder sowas abzusetzen. Ich teste auf Windows...
Ich halte das Script für sehr geschlossen. Wo siehst du hier eine Sicherheitslücke?
Das Script ist IMHO so gut wie gar nicht angreifbar. Wenn es jemand angreifen wollte,
müsste er den Quelltext haben und sehr, sehr viel über die internas von Perl verstehen,
sodass er unfug treiben könnte (Bufferoverflows z.B.).
perl tt.pl foo=exec('dir');
oder
perl tt.pl foo=sleep+10;
hat alles nix gebracht, außer die Ausgaben: exec('dir') und sleep 10.
Was hättest du erwartet? - Das das ausgeführt wird? - Ja, dann wäre es in der Tat eine
Sicherheitslücke, aber dem ist nicht so. Solange du nicht im Programm selber mit
Backticks, exec, system, open oder eval arbeitest und die Eingaben nicht überprüfst, dürfte es keine "wirklich grundlegenden" Sicherheitsprobleme geben.
Hat jemand ne Idee, was ich da falsch mache ?
_Wie_ erwartest du es denn richtig?
Viele Grüsse
Philipp
perl tt.pl foo=exec('dir');
oder
perl tt.pl foo=sleep+10;
hat alles nix gebracht, außer die Ausgaben: exec('dir') und sleep 10.Was hättest du erwartet? - Das das ausgeführt wird? - Ja, dann wäre es in der Tat eine
Sicherheitslücke, aber dem ist nicht so. Solange du nicht im Programm selber mit
Backticks, exec, system, open oder eval arbeitest und die Eingaben nicht überprüfst, dürfte es keine "wirklich grundlegenden" Sicherheitsprobleme geben.
Aha sehr gut zu wissen. D.h. also wenn ich die übergebenen Variablen nicht in einem Systemufruf benutze kann fast nix schief gehen...
Hier aber mal ein Beispiel, welches afaik unfug macht, oder.
Empfangen vom Formular
$mailto = hans@hacker </etc/passwd
Aufruf im Script
open (MAIL, "| /usr/bin/sendmail $mailto");
print MAIL "Blub";
close MAIL
Hat jemand ne Idee, was ich da falsch mache ?
_Wie_ erwartest du es denn richtig?
Naja richtig in meinem Fall wäre eine Sicherheitslücke gewesen, da ich ja diese testen wollte.
So long ...
alligator
Halihallo alligator
Aha sehr gut zu wissen. D.h. also wenn ich die übergebenen Variablen nicht in einem Systemufruf benutze kann fast nix schief gehen...
Genau.
Hier aber mal ein Beispiel, welches afaik unfug macht, oder.
Empfangen vom Formular
$mailto = hans@hacker </etc/passwd
Genau.
Aufruf im Script
open (MAIL, "| /usr/bin/sendmail $mailto");
print MAIL "Blub";
close MAIL
Und genau deshalb _sollte_ man sendmail mit -t Schalter
verwenden! - Dann wird die Adresse über den Mailcontent übergeben und
sendmail öffnet eben keine pipes sondern beschwert höchstens über
eine nicht konforme E-Mail Adresse. Ansonsten empfehle ich ohnehin
Net::SMTP.
Viele Grüsse
Philipp
Halihallo nochmals
Aha sehr gut zu wissen. D.h. also wenn ich die übergebenen Variablen nicht in einem Systemufruf benutze kann fast nix schief gehen...
Genau.
uha, das war böse! - "Genau" bezog sich auf den besprochenen Kontext. Ich hoffe, dass es
jedem klar ist, dass diese Möglichkeit nur _eine unter vielen_ ist, um unfug zu
betreiben, sprich Sicherheitslücken auszunutzen.
Ich will jetzt nicht die ganze "Sicherheitsthematik" nochmals durchkauen, ich wollte
nur darauf hinweisen, dass dies nur eine Möglichkeit unter sehr, sehr vielen ist.
Leider gibt's auch keine "Perfekte Checkliste/Handbuch der Sicherheit", denn die
Sicherheit hängt massgebend vom Programmierer und dem Server-Admin ab, beides sind
Menschen, beide machen Fehler und es ist nicht möglich alle möglichen Fehler abzudecken
bzw. in einer Checkliste zu vereinen.
Viele Grüsse
Philipp
use CGI;
$q = new CGI;
$value = $q->param('foo');
print $value;
$value;
^^^^^^^
hättest du Warnungen aktiviert, bekämst du hier eine Warnung "Useless use of a variable in void context ...". Bitte, beginne deine Programme mit "use strict; use warnings;"!
Perl ist nämlich keine Shell. Das einfach platzieren von $value bewirkt nicht, dass deren Inhalt ausgeführt wird. In dem Fall hättest du eine Sicherheitslücke.
Folgendes Programm ist sicherheitskritisch und darf NIEMALS auf einem Webserver liegen!
#!/usr/bin/perl
use strict;
use warnings;
use CGI qw/:standard/;
exec param('exec');
__END__
Aufruf:
$ perl tt.pl "exec=echo Sicherheitslücke"
Lies also perldoc warnings
, perldoc strict
, und unbedingt perldoc perlsec
!
use CGI;
$q = new CGI;
$value = $q->param('foo');
print $value;
$value;
^^^^^^^hättest du Warnungen aktiviert, bekämst du hier eine Warnung "Useless use of a variable in void context ...". Bitte, beginne deine Programme mit "use strict; use warnings;"!
»»
Hi,
mach ich ja normalerweise auch, aber bei so nem Minitestprogramm hab
ichs jetzt halt nicht gemacht. Die Faulheit läßt grüßen :o)
Perl ist nämlich keine Shell. Das einfach platzieren von $value bewirkt nicht, dass deren Inhalt ausgeführt wird. In dem Fall hättest du eine Sicherheitslücke.
Folgendes Programm ist sicherheitskritisch und darf NIEMALS auf einem Webserver liegen!
#!/usr/bin/perl
use strict;
use warnings;
use CGI qw/:standard/;exec param('exec');
__END__Aufruf:
$ perl tt.pl "exec=echo Sicherheitslücke"
Aha, ok sowas hab ich gesucht. Danke.
cya
alligator