TomC: Hat jemand Lust, die Sicherheit dieses Scripts zu beurteilen?

Ich weiß, das Script ist etwas kompliziert, aber ich uebe noch....

#!/usr/bin/perl -w ###!C:/Programme/Apache Group/Apache2/Perl/bin/perl.exe -w

use strict; use CGI::Carp qw(fatalsToBrowser);

my $pathtoall   = "http://www.domain.de/bla/all"; my $pathtopages = "http://www.domain.net/bla"; my $pathtocgi   = "http://www.domain.net/cgi-bin";

################################################################################

Erstmal die uebergebenen parameter auslesen

################################################################################ my $formulardaten; my $mail_ip; if($ENV{'REQUEST_METHOD'} eq 'GET'){    $formulardaten = $ENV{'QUERY_STRING'};    $mail_ip = $ENV{'REMOTE_ADDR'}; } else{    read(STDIN, $formulardaten, $ENV{'CONTENT_LENGTH'});    read(STDIN, $mail_ip, $ENV{'REMOTE_ADDR'}); } my @formularfelder = split(/&/, $formulardaten); my $formularfeld; my $name; my $value;

my $page_name_sended  = 'none'; my $action_sended     = 'none'; my $mail_absender     = 'none'; my $mail_absendername = 'none'; my $mail_empfaenger   = 'none'; my $mail_nachricht    = 'none'; my $mail_ranum        = 'none';

my $page_show         = 2; my $page_name         = 'none'; my $page_type         = 'none'; my $page_topic        = 'none'; my $page_main         = 'none'; my $page_title        = 'none'; my $page_link         = 'none';

my $html              = "Content-type: text/html\n\n"; my $mailprog = '/usr/lib/sendmail'; my $ranum = time();

foreach $formularfeld (@formularfelder){    ($name, $value) = split(/=/, $formularfeld);    $value =~ tr/+/ /;    $value =~ s/%0A//g;    $value =~ s/%0D/||/g;    $value =~ s/%7C/|/g;    $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;    $value =~ s/<!--(.|\n)*-->//g;

if   ($name eq "name")         {$page_name_sended = "$value";}    elsif($name eq "action")       {$action_sended = "$value";}    elsif($name eq "absender")     {$mail_absender = "$value";}    elsif($name eq "absendername") {$mail_absendername = "$value";}    elsif($name eq "empfaenger")   {$mail_empfaenger = "$value";}    elsif($name eq "nachricht")    {$mail_nachricht = "$value";}    elsif($name eq "ranum")        {$mail_ranum = "$value";} } $html .= qq~ <html>

<head>       <meta http-equiv="content-type" content="text/html;charset=iso-8859-1">       <title>Seite empfehlen</title>       <link rel=stylesheet type="text/css" href="$pathtoall/css/main.css">    </head>

<body bgcolor="#ffffff" text="#000000" leftmargin="10" topmargin="10" marginwidth="10" marginheight="10"> ~;

if($action_sended eq 'showwindow'){&createWindow;} elsif($action_sended eq 'sendmymail'){&sendMyMail;}

print $html;

################################################################################

sub createWindow{ my @pages; open(DATEI, '<table_pages.pl') || die 'Konnte die Tabelle mit den Seiten nicht oeffnen'; @pages = <DATEI>; close(DATEI); shift(@pages); chomp(@pages);

daten der aufgerufenen seite einlesen

foreach (@pages) {    ($page_show,$page_name,$page_main,$page_title,$page_link) = split(/|/,$_);    last if ($page_name eq $page_name_sended); }

falls in der datenbank noch irgendwo localhost/ im pfad steht: rausloeschen!

$page_link =~ s/localhost///gi;

datei zur pruefung der sendeberechtigung erstellen

open(DATEI, ">dudarfst/$ranum.pl") || die 'Konnte Erlaubnis nicht vergeben'; print DATEI "$ranum"; close(DATEI);

$html .= qq~

<br>       <h2>Seite empfehlen<img src="$pathtoall/img/dot_blau.gif" width="100%" height="1" border="0" vspace="2"></h2>       <form name="FormName" action="$pathtocgi/foo/empfehlung.pl" method="get">          <input type="hidden" name="action" value="sendmymail">          <input type="hidden" name="ranum" value="$ranum">          <table border="0" cellpadding="0" cellspacing="0" width="470">             <tr>                <td width="170" height="30" valign="top">Ihr Name</td>                <td width="300" height="30" valign="top"><input class="edit300" type="text" name="absendername" size="35"></td>             </tr>             <tr>                <td width="170" height="30" valign="top">Ihre E-Mail-Adresse</td>                <td width="300" height="30" valign="top"><input class="edit300" type="text" name="absender" size="35"></td>             </tr>             <tr>                <td width="170" height="30" valign="top">E-Mail des Empfängers</td>                <td width="300" height="30" valign="top"><input class="edit300" type="text" name="empfaenger" size="35"></td>             </tr>             <tr>                <td width="170" valign="top">Ihre Nachricht</td>                <td width="300" rowspan="2"><textarea class="w300" name="nachricht" cols="28" rows="6">Ich möchte Dir folgende Seite von domain.de empfehlen: $pathtopages/$page_link</textarea></td>             </tr>             <tr>                <td width="170" valign="bottom"><input type="submit" name="E" value="Empfehlung senden"></td>             </tr>          </table>       </form>       <p>          <img src="$pathtoall/img/dot_blau.gif" width="450" height="1" border="0" vspace="2"><br>          www.domain.de       </p>    </body> </html> ~; }

################################################################################

sub sendMyMail{

my $ranum_check = 0;    my $verzeichnis = "dudarfst";    my $dateistring = "$mail_ranum.pl";

opendir(DIR, $verzeichnis) || die "Konnte das Erlaubnis-Verzeichnis nicht oeffnen.";       my @dateien = readdir(DIR);    closedir(DIR);

foreach(@dateien){       if($dateistring eq $){          $ranum_check = 1;       }       last if($dateistring eq $);    }

if($ranum_check == 1){       open(MAIL,"|$mailprog -t");          print MAIL "To: $mail_empfaenger\n";          print MAIL "From: $mail_absender\n";          print MAIL "Subject: Seitenempfehlung von $mail_absendername \n";          print MAIL "X-Priority: 1 (Highest)\n\n";          print MAIL "$mail_nachricht";       close(MAIL);

unlink("dudarfs/$mail_ranum.pl");

$html .= qq~          <br>          <h1>Ihre Empfehlung wurde versendet</h1>          <p><b>Absender:</b><br> $mail_absendername</p>          <p><b>E-Mail-Adresse des Absenders:</b><br>$mail_absender</p>          <p><b>E-Mail-Adresse des Empfängers:</b><br>$mail_empfaenger</p>          <p><b>Nachricht:</b><br>$mail_nachricht</p>          <p>Sie können das Fenster jetzt <a href="javascript:window.close();">schließen</a></p>          </body></html>       ~;    } else {       open(MAIL,"|$mailprog -t");          print MAIL "To: webmaster@domain.de\n";          print MAIL "From: error@domain.net\n";          print MAIL "Subject: Fehler bei Seitenempfehlung\n";          print MAIL "X-Priority: 1 (Highest)\n\n";          print MAIL "$mail_ip\n";          print MAIL "$dateistring\n";          print MAIL "$mail_absendername\n";          print MAIL "$mail_absender\n";          print MAIL "$mail_empfaenger\n";          print MAIL "$mail_nachricht\n";       close(MAIL);

$html .= qq~          <br>          <h1>Fehler</h1>          <p>Mögliche Ursachen:</p>          <ul>             <li>Die URL wurde nicht korrekt übermittelt oder verändert             <li>Das Skript wurde nicht durch ordnungsgemäß aufgerufen             <li>Sonstige Manipulation          </ul>          <p>Um eine Manipulation auszuschließen, wurden die Daten der e-mail und die IP des Absenders zur &Uuml;berprüfung an den Webmaster gesendet.</p>          <p>Fenster <a href="javascript:window.close();">schließen</a></p>          </body></html>       ~;    } }

  1. Moin Moin !

    #!/usr/bin/perl -w
    ###!C:/Programme/Apache Group/Apache2/Perl/bin/perl.exe -w

    [...]

    my $formulardaten;
    my $mail_ip;
    if($ENV{'REQUEST_METHOD'} eq 'GET'){
       $formulardaten = $ENV{'QUERY_STRING'};
       $mail_ip = $ENV{'REMOTE_ADDR'};
    }
    else{
       read(STDIN, $formulardaten, $ENV{'CONTENT_LENGTH'});
       read(STDIN, $mail_ip, $ENV{'REMOTE_ADDR'});
    }

    Laß das selbstgestrickte Parsen der CGI-Daten sein und nimm das CGI-Modul. ( use CGI qw(:standard); )

    [...]

    my $ranum = time();

    _Ra_ndom _num_ber ? Wohl kaum! random() wäre es.

    [...]

    if   ($name eq "name")         {$page_name_sended = "$value";}
       elsif($name eq "action")       {$action_sended = "$value";}
       elsif($name eq "absender")     {$mail_absender = "$value";}
       elsif($name eq "absendername") {$mail_absendername = "$value";}
       elsif($name eq "empfaenger")   {$mail_empfaenger = "$value";}
       elsif($name eq "nachricht")    {$mail_nachricht = "$value";}
       elsif($name eq "ranum")        {$mail_ranum = "$value";}

    Kennst Du %hashes ?

    [...]

    sub createWindow{
    my @pages;
    open(DATEI, '<table_pages.pl') || die 'Konnte die Tabelle mit den Seiten nicht oeffnen';

    1. Wo ist dein Current Directory ? Meistens im /cgi-bin/-Verzeichnis, aber das ist nirgendwo genormt. Absolute Pfadangabe, bitte.

    2. Wenn Du ins /cgi-bin/-Directory schreibst (und unter Windows arbeitest), erzeugst Du Sicherheitslücken. Schreib in ein privates Datenverzeichnis.

    [...]

    datei zur pruefung der sendeberechtigung erstellen

    open(DATEI, ">dudarfst/$ranum.pl") || die 'Konnte Erlaubnis nicht vergeben';
    print DATEI "$ranum";
    close(DATEI);

    Gleiches Problem wie oben.

    Wird das ein Locking-Mechanismus ?

    www.domain.de

    Lies mal RFC2606, erfinde keine Domains!

    [...]

    sub sendMyMail{

    my $ranum_check = 0;
       my $verzeichnis = "dudarfst";
       my $dateistring = "$mail_ranum.pl";

    opendir(DIR, $verzeichnis) || die "Konnte das Erlaubnis-Verzeichnis nicht oeffnen.";

    Wieder: Wo ist das Current Directory ?

    [...]

    open(MAIL,"|$mailprog -t");

    Fehlerbehandlung fehlt.

    print MAIL "To: $mail_empfaenger\n";
             print MAIL "From: $mail_absender\n";
             print MAIL "Subject: Seitenempfehlung von $mail_absendername \n";
             print MAIL "X-Priority: 1 (Highest)\n\n";
             print MAIL "$mail_nachricht";

    Nicht elegant, aber geht. Ein print würde reichen.

    close(MAIL);

    Fehlerabfrage bei close fehlt (bei pipe opens NOTWENDIG).

    unlink("dudarfs/$mail_ranum.pl");

    Current Directory ?

    open(MAIL,"|$mailprog -t");

    Fehlerabfrage fehlt.

    So, back to the drawing board! ;-)

    Alexander

    Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll. Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
    1. THANX!

      Kannst Du beurteilen, wie sicher das ganze gegen Spam ist?

      TomC

      1. Moin Moin !

        Soweit habe ich das Script noch nicht gelesen. Aber das kannst Du Dir wahrscheinlich selbst beantworten:

        Kannst Du von außerhalb des Scriptes, sprich durch Formulardaten, einfluß auf die Mailadresse nehmen ? Dann kann man damit spammen.

        Werden als Ergebnis Mailadressen (wohlmöglich in Links) ausgegeben ? Dann lieferst Du den Spammern neues Futter.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
        1. Moin

          Kannst Du von außerhalb des Scriptes, sprich durch Formulardaten, einfluß auf die Mailadresse nehmen ? Dann kann man damit spammen.

          Der Empfänger wird mit einer einfachen Variablen angegeben -> Spam ist möglich.
          Allerdings muss das Script 2 mal aufgerufen werden: Einmal zum erzeugen des Forumlars und einer Datei auf dem Server und ein zweites mal, um eine Formular-Variable mit der Serverdatei abzugleichen und das Formular ggfs. zu versenden. Ich denke in meiner Unerfahrenheit, dass dieses Vorgehen die ganze Sache mit dem Spam erschwert.

          TomC

          1. Moin!

            Allerdings muss das Script 2 mal aufgerufen werden: Einmal zum erzeugen des Forumlars und einer Datei auf dem Server und ein zweites mal, um eine Formular-Variable mit der Serverdatei abzugleichen und das Formular ggfs. zu versenden. Ich denke in meiner Unerfahrenheit, dass dieses Vorgehen die ganze Sache mit dem Spam erschwert.

            Ok, das legt die Latte für den Spammer ... ähm, 0,001 Millimeter höher.

            Bedenke: Im HTTP-Universum gibt es kein Vorher und kein Nachher. Der Spammer wird sich dein Formular vom Server ziehen (egal wie es erstellt und übermittelt wird), die enthaltenen Formularfelder angucken, die Möglichkeit zur Übermittlung einer Empfängeradresse sehen und dann mal testen, ob das tatsächlich funktioniert.

            Sollte es funktionieren, wird er automatisiert dein Mailscript mit Formularabsendungen vollballern. Schritt 1 ist dabei absolut nicht notwendig. Das Skript arbeitet, wenn es Formulardaten enthält - und das wird es tun, egal, ob es vorher ein Formular ausgegeben hat oder nicht.

            Was du verhindern mußt, ist die im Prinzip freie Wahl der Empfängeradresse im Formular.

            Um es dir zu demonstrieren, mach mal folgendes: Speicher das Formular im Browser auf deiner Festplatte. Öffne es dann in einem Texteditor (der unter Start-Programme-Zubehör reicht aus, oder nimm deinen Programmeditor). Ändere dann die action des Formulars von action="cgi-bin/skript" auf die absolute Angabe action="http://www.example.com/pfad/cgi-bin/skript". Abspeichern.

            Wenn du jetzt im Browser das Formular von Festplatte lädst, sieht es genauso aus, wie vorher (vielleicht machen eingebundene Grafiken Probleme - stört aber nicht). Du kannst das Formular auch genauso absenden, als käme es von deinem Server. Du kannst insbesondere hidden-Felder im HTML-Quelltext ändern, die dann logischerweise auch geändert übertragen werden. Eine Mailempfängeradresse als hidden-Feld ist manipulierbar. Man kann das Feld beispielsweise einfach von "hidden" nach "text" ändern. Auf die gleiche Weise kann man dir im Prinzip beliebige Daten senden. Deshalb sorge dafür, dass diese Daten auch Daten bleiben und nicht zu Befehlen oder Programmen mutieren können. Vorsicht ist insbesondere bei Übergaben dieser Daten an die Shell, beim Öffnen von Dateien oder Pipes und bei Kommunikation über SQL mit Datenbanken geboten.

            Und das Absenden eines Formulars muss man natürlich nicht auf diese umständliche Weise manuell erledigen, das können Programme viel besser. Jede bessere Skriptsprache (auch Perl) kann sowas.

            - Sven Rautenberg

            --
            "Bei einer Geschichte gibt es immer vier Seiten: Deine Seite, ihre Seite, die Wahrheit und das, was wirklich passiert ist." (Rousseau)
            1. Hi,

              Hat jetzt nicht direkt etwas mit dem Thema zu tuen, aber ich habe neulich eine recht wirkungsvolle Strategie gesehen, die es Spammern vergleichsweise schwer macht unautorisiert Mails zu versenden:
              Ich weiß zwar nicht mehr wo das war, aber der, der das Script gechrieben hat, hat ein wenig bei Microsoft (Hotmail) abgeschaut und dann das Prinzip erweitert. Wenn man eine Mail, an einen beliebigen Empfänger, versenden wollte, musste man von einem Bild die das geschriebene oder beschriebene ablesen und in ein Teil des Formulares posten. Dabe waren es entweder einfache Bilder wie ein Apfel, ein See, eine Schnecke etc, oder es war in einer etwas verschnörkelten, aber dennoch gut lesbaren Schrift, ein Wort gedruckt. Dies dürft die Meßlatte für Spammer doch ein wenig hochheben, oder? Hat aber den großen Nachteil, dass es für Sehbehinderte etc. schlecht zu benutzen ist.
              Was haltet ihr von dieser Methode?

              mfg Andres Freund

              1. Hi Andres,

                Was haltet ihr von dieser Methode?

                wenn die Aufgabenstellung lautet, daß der Benutzer die Ziel-Mailadresse angeben können muß, ist das ganz okay - wenn der Form-Mailer nur an eine einzige Adresse mailen soll, dann gibt es keinen echten Grund, diese nicht in den Quelltext selbst zu schreiben.

                Viele Grüße
                      Michael

                --
                T'Pol: I apologize if I acted inappropriately.
                V'Lar: Not at all. In fact, your bluntness made me reconsider some of my positions. Much as it has now.
    2. Hi Alexander,

      Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.

      dieses cut&paste dauert doch sicher erheblich länger, als die Antwort einfach ein zweites Mal abzusenden?

      Viele Grüße
            Michael

      --
      T'Pol: I apologize if I acted inappropriately.
      V'Lar: Not at all. In fact, your bluntness made me reconsider some of my positions. Much as it has now.
      1. Moin Moin !

        Und leider stört jetzt die Quoting-Quota. Sorry, jetzt kommt nur noch Müll.

        dieses cut&paste dauert doch sicher erheblich länger, als die Antwort einfach ein zweites Mal abzusenden?

        Nicht viel.

        Aber irgendwie bin ich noch zu sehr im Heise-Ticker, wenn ich "FEHLER. Zu viel Originaltext" sehe. ;-)

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
  2. Hi,

    das Skript wuerde etwa 4 Sekunden auf mein Server leben.
    Also so lange bis ich "rm Skriptname.pl" geschrieben haette :))

    Ich zeige nur die kritischen Stellen.
    {Uebrigens im Gegensatz zu Alexanders Meinung finde ich es richtig, dass du deinen eigenen variablenparser nutzt und nicht
    CGI qw(:standard);
    Grund: Die Parsefunktion von CGI.pm ist umfangreicher als das was du brauchst.
    Also nur mehr Müll im Speicher. }

    »

    elsif($name eq "ranum")        {$mail_ranum = "$value";}

    [..]

    my $dateistring = "$mail_ranum.pl";

    unlink("dudarfs/$mail_ranum.pl");

    Irgendwo hast du dann auch in der letzten else-Schleife das touch()
    vergessen.

    Nun, der Fehler ist:
    $mail_ranum wird vom User bestimmt.
    Also kann das auch das sein:
    "blafasel.txt;/usr/bin/rm -Rf *;"

    Daraus wuerde dann in Perl:
    unlink("dudarfs/blafasel.txt;/usr/bin/rm -Rf *;.pl");

    Das koennte schief gehen :)

    Ausserdem solltest du mit dem Parameter
    "-f" beim Sendmailaufruf den Absender einstellen, damit im Fall eines
    Zustellungsfehlers die Mail nicht an den falschen geht.
    Bitte dabei nicht Errors-To verwenden.
    Unsere herzensguten System- und Mailadmins haben in RFC 2076 beschlossen, dass das nicht gut sei :(
    "Ausserdem wuerde das ja eh keiner verwenden...."
    (Die Sysadmins muessen es ja wissen. Die schreiben ja so viele Skripten)

    Um den parameter zu nutzen musst du aber sicherkehen, dass die Mailadresse dann auch wirklich eine Mailadresse ist und nicht irgendwas anderes.

    Ciao,
      Wolfgang

    1. Hi xwolf,

      Daraus wuerde dann in Perl:
      unlink("dudarfs/blafasel.txt;/usr/bin/rm -Rf *;.pl");
      Das koennte schief gehen :)

      viel schlimmer: Es könnte sogar _funktionieren_ ...

      Viele Grüße
            Michael

      --
      T'Pol: I apologize if I acted inappropriately.
      V'Lar: Not at all. In fact, your bluntness made me reconsider some of my positions. Much as it has now.