Patrick Andrieu: Tainted Love again, .pl vs .cgi - Lese-Wink an Alexander(HH)

Hallo alle!

@@Alexander(HH):

Kannst Du Dich an unsere Tainted Love, äh, unseren Tainted Love-Thread-Zweig erinnern? ;)

Es ging damals darum, dass ich auf meinem Webspace das im Thread vorgestellte Skriptchen nicht zum Laufen bringen konnte, sobald -T, bzw. -wT in der Shebang war.

Jetzt dürfte es sich 'rumgesprochen, dass ich Apache installiert habe (*g*), und eben ist mir dieses Skriptchen wieder eingefallen. Und nun siehe da:

tainted_test.PL -> 500er
tainted_test.CGI -> funzt(TM)

Würde bedeuten, der »Tainted Mode« ist nur für Skripts mit der Endung .cgi reserviert?

Der lokale Apache schreibt in die error.log:

[Fri Jan 25 12:37:55 2008] [error] [client 192.168.0.1] Premature end of script headers: tainted_test.pl
[Fri Jan 25 12:37:55 2008] [error] [client 192.168.0.1] "-T" is on the #! line, it must also be used on the command line at /.../tainted_test.pl line 1.\r

Ich lasse mir hier zusätzlich @INC ausgeben, weil ich festgestellt habe, dass "." im Tainted Mode nicht mehr ausgegeben wird:

not_tainted.cgi

Gibt es eine _deutschprachige_ Seite, auf welcher genau erklärt wird, was -T alles bewirkt?

Viele Grüße aus Frankfurt/Main,
Patrick

--

_ - jenseits vom delirium - _
[link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
Nichts ist unmöglich? Doch!
Heute schon gegökt?
  1. Re!

    Kannst Du Dich an unsere Tainted Love, äh, unseren Tainted Love-Thread-Zweig erinnern? ;)

    Das war hier, wollte ich eigentlich beim Posten mitverlinken...

    Viele Grüße aus Frankfurt/Main,
    Patrick

    --

    _ - jenseits vom delirium - _
    [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
    Nichts ist unmöglich? Doch!
    Heute schon gegökt?
  2. Moin Moin!

    tainted_test.PL -> 500er
    tainted_test.CGI -> funzt(TM)

    Ersteres ist kaputt, siehe error_log.

    Würde bedeuten, der »Tainted Mode« ist nur für Skripts mit der Endung .cgi reserviert?

    Nein. Tainted Mode hat nichts mit Dateiendungen oder URLs zu tun.

    Der lokale Apache schreibt in die error.log:

    [Fri Jan 25 12:37:55 2008] [error] [client 192.168.0.1] Premature end of script headers: tainted_test.pl
    [Fri Jan 25 12:37:55 2008] [error] [client 192.168.0.1] "-T" is on the #! line, it must also be used on the command line at /.../tainted_test.pl line 1.\r

    Du rufst ein Script mit "#!/usr/bin/perl -T" indirekt via perl executable auf, ohne dort ebenfalls -T zu benutzen.

    perl taint_mode_script.pl

    wird nie funktionieren, es muß immer

    perl -T taint_mode_script.pl

    heißen.

    Hast Du mod_perl aktiviert, dass auf .pl via Apache::Registry reagiert und zudem OHNE Taint-Mode läuft? Letzteres wäre ohnehin nicht sehr clever.

    Das würde den beobachteten Unterschied zwischen .pl (via mod_perl und Apache::Registry) und .cgi (via mod_cgi und /usr/bin/perl) erklären. Beim direkten Aufruf des Scripts zerlegt der OS-Kernel die erste Zeile des Scripts in Interpreter-Programm und Kommandozeilen-Parameter, und hängt schließlich den Script-Namen und die Original-Parameter an.

      
    execl("/usr/bin/script.pl","/usr/bin/script.pl","foo","bar",NULL);  
    
    

    macht, wenn Zeile 1 von /usr/bin/script.pl wie folgt ist,

      
    #!/usr/bin/perl -w -T  
    
    

    exakt das selbe wie

      
    execl("/usr/bin/perl","/usr/bin/perl","-w","-T","/usr/bin/script.pl","foo","bar",NULL);  
    
    

    Weil Perl beim -T-Parameter aber paranoid wird, ist das, anders als bei allen anderen Kommandozeilen-Parameter, nicht identisch mit

      
    execl("/usr/bin/perl","/usr/bin/perl","/usr/bin/script.pl","foo","bar",NULL);  
    
    

    -w und andere Parameter pickt sich Perl auch selbst aus der Zeile 1, wenn der Interpreter schon läuft, aber der Taint-Mode muß aktiviert werden, BEVOR der Interpreter läuft. Daher bleiben an dieser Stelle nur zwei Möglichkeiten: Taint-Modus trotz anders lautenden Instruktionen ausgeschaltet lassen und unsicher weiter arbeiten, oder aber laut Zeter und Mordio schreien. Unter Sicherheitsaspekten ist nur die letzte Möglichkeit sinnvoll.

    Unter Windows mußt Du im Apachen "ScriptInterpreterSource Registry" auskommentieren bzw. auf script ändern, damit der Apache die Bemühungen eines Unix-Kernels simuliert, und die #!-Zeile auf "#!C:/perl/bin/perl.exe -T -w" ändern.

    Ich lasse mir hier zusätzlich @INC ausgeben, weil ich festgestellt habe, dass "." im Tainted Mode nicht mehr ausgegeben wird:

    Richtig. Das ist so gewollt und auch in perlsec dokumentiert.

    not_tainted.cgi

    Gibt es eine _deutschprachige_ Seite, auf welcher genau erklärt wird, was -T alles bewirkt?

    use English; # ;-)

    perldoc perlsec

    http://wiki.perl-community.de/bin/view/Perldoc/PerlDokumentListe ist ein bescheidener Anfang.

    babelfish ist nicht wirklich gut, eher lustig ...

    Alexander

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

      Moin Moin!

      Jaja, Ihr Nordlichter... hier sache mer: Ei, Gudde!

      Vielen Dank für die ausführlichen Erklärungen, die schon mal einen »fachlich hilfreich« Wert sind!

      tainted_test.PL -> 500er
      tainted_test.CGI -> funzt(TM)
      Ersteres ist kaputt, siehe error_log.

      Nein, ist nicht ;) Hatten wir letztens schon: der 500er wird durch das -T in der Shebang verursacht. Und an die error.log bei 1&1 komme ich nach wie vor nicht, ich ahne zwar, wo die sich befindet, ernte aber ein »permission denied«, jedesmal wenn ich mit PuTTy oder mit Perl versuche, in das vermutete Verzeichnis 'reinzuschauen. Eine Frage an den Support wurde mit einem Hilfsmittel beantwortet, wie man mit PHP eigene Error-Dateien generiert, aber das interessiert mich nicht! Ich _will_ die error-Logs vom Server!

      Aber das war überhaupt der Grund meines Postings, dass es mit meinem lokalen Apache _genauso_ ist: .pl mit -T wirft einen 500er, .cgi mit -T nicht.

      Nein. Tainted Mode hat nichts mit Dateiendungen oder URLs zu tun.

      Glaube ich Dir. Nur, warum klappt das bei 1&1 nicht? Kann jemand mit einem anderen Webhoster ein .pl-Skript mit -T in der Shebang hochladen, und mir sagen, was passiert?

      Du rufst ein Script mit "#!/usr/bin/perl -T" indirekt via perl executable auf, ohne dort ebenfalls -T zu benutzen.
      perl taint_mode_script.pl
      wird nie funktionieren, es muß immer
      perl -T taint_mode_script.pl

      Dann _kann_ es einfach nicht funktionieren, entnehme ich aus dieser Erklärung - weder beim Webhoster auf Linux, noch lokal auf Windows, oder? CGI-Skripte, die über einen Browser aufgerufen werden, können ja nicht mit perl -T skriptname.pl augerufen werden... Oder verstehe ich alles falsch?

      Hast Du mod_perl aktiviert, dass auf .pl via Apache::Registry reagiert und zudem OHNE Taint-Mode läuft? Letzteres wäre ohnehin nicht sehr clever.

      Nein. Weder lokal noch bei 1&1 ist mod_perl aktiv.

      code lang=C
      execl("/usr/bin/script.pl","/usr/bin/script.pl","foo","bar",NULL);

      Das verstehe ich überhaupt nicht, sorry, ich habe von ZÄH keine Ahnung - von UNIX-Befehlen auch nicht, übrigens ;)

      -w und andere Parameter pickt sich Perl auch selbst aus der Zeile 1, wenn der Interpreter schon läuft, aber der Taint-Mode muß aktiviert werden, BEVOR der Interpreter läuft. Daher bleiben an dieser Stelle nur zwei Möglichkeiten: Taint-Modus trotz anders lautenden Instruktionen ausgeschaltet lassen und unsicher weiter arbeiten, oder aber laut Zeter und Mordio schreien. Unter Sicherheitsaspekten ist nur die letzte Möglichkeit sinnvoll.

      Oder die Skripte, die auf den Taint Mode angewiesen sind, als .cgi speichern? Denn wenn in meinem Beispiel tainted_test.CGI @INC »geschrumpft« wird, heißt es doch, dass der Taint Mode greift, oder?

      Unter Windows mußt Du im Apachen "ScriptInterpreterSource Registry" auskommentieren bzw. auf script ändern, damit der Apache die Bemühungen eines Unix-Kernels simuliert, und die #!-Zeile auf "#!C:/perl/bin/perl.exe -T -w" ändern.

      Ja, aber das werde ich nicht tun, sonst vergesse ich vor dem Hochladen womöglich die Shebang auf UNIX-Shebang zu ändern, und suche dann ewig nach Fehlern, weil ich nicht mehr dran denke ;)

      Auf die Konfiguration beim Webhoster habe ich eh keinen Einfluß.

      Ich lasse mir hier zusätzlich @INC ausgeben, weil ich festgestellt habe, dass "." im Tainted Mode nicht mehr ausgegeben wird:
      Richtig. Das ist so gewollt und auch in perlsec dokumentiert.

      Ah, OK, danke.

      Gibt es eine _deutschprachige_ Seite, auf welcher genau erklärt wird, was -T alles bewirkt?

      use English; # ;-)

      use german; wäre mir lieber, aber na gut,

      perldoc perlsec

      in ca. drei Wochen habe ich das vielleicht verstanden ;)

      http://wiki.perl-community.de/bin/view/Perldoc/PerlDokumentListe ist ein bescheidener Anfang.

      babelfish ist nicht wirklich gut, eher lustig ...

      Ja!

      Viele Grüße aus Frankfurt/Main,
      Patrick

      --

      _ - jenseits vom delirium - _
      [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
      Nichts ist unmöglich? Doch!
      Heute schon gegökt?
      1. Moin Moin!

        Und an die error.log bei 1&1 komme ich nach wie vor nicht, ich ahne zwar, wo die sich befindet, ernte aber ein »permission denied«, jedesmal wenn ich mit PuTTy oder mit Perl versuche, in das vermutete Verzeichnis 'reinzuschauen. Eine Frage an den Support wurde mit einem Hilfsmittel beantwortet, wie man mit PHP eigene Error-Dateien generiert, aber das interessiert mich nicht! Ich _will_ die error-Logs vom Server!

        Was sagt Dir der Begriff KK-Antrag?

        Glaube ich Dir. Nur, warum klappt das bei 1&1 nicht? Kann jemand mit einem anderen Webhoster ein .pl-Skript mit -T in der Shebang hochladen, und mir sagen, was passiert?

        Ich weiß aus eigener Erfahrung mit 1&1, dass dort *S*E*H*R* merkwürdige Dinge mit Perl-Scripten passieren. Man setzt offensichtlich eine Kombination aus mod_rewrite, Server Side Includes und mod_perl/Apache::Registry ein. Die HTTP-Header im Environment passen jedenfalls so überhaupt nicht zu dem, was man normalerweise im CGI-Kontext für Perl-Scripte erwartet.

        Du rufst ein Script mit "#!/usr/bin/perl -T" indirekt via perl executable auf, ohne dort ebenfalls -T zu benutzen.
        perl taint_mode_script.pl
        wird nie funktionieren, es muß immer
        perl -T taint_mode_script.pl

        Dann _kann_ es einfach nicht funktionieren, entnehme ich aus dieser Erklärung - weder beim Webhoster auf Linux, noch lokal auf Windows, oder? CGI-Skripte, die über einen Browser aufgerufen werden, können ja nicht mit perl -T skriptname.pl augerufen werden... Oder verstehe ich alles falsch?

        Unter Linux funktioniert -T im Script normalerweise völlig problemlos, weil der Webserver unter Linux das Script einfach genauso ausführt wie ein compiliertes Programm, und der Kernel sich um den Rest kümmert. Siehe unten.

        Hast Du mod_perl aktiviert, dass auf .pl via Apache::Registry reagiert und zudem OHNE Taint-Mode läuft? Letzteres wäre ohnehin nicht sehr clever.

        Nein. Weder lokal noch bei 1&1 ist mod_perl aktiv.

        Letzteres glaube ich nicht so ganz.

        code lang=C
        execl("/usr/bin/script.pl","/usr/bin/script.pl","foo","bar",NULL);

        Das verstehe ich überhaupt nicht, sorry, ich habe von ZÄH keine Ahnung - von UNIX-Befehlen auch nicht, übrigens ;)

        Ändere das. Wenn Du überhaupt keinen Schimmer hast, was auf dem Rechner vor sich geht, machst Du Dir die Fehlersuche unnötig schwer -- weil Du einfach irgendwelche Knöpfe drückst, ohne Dir über die Wirkung im Klaren zu sein.

        Der erste Parameter von execl() ist das Programm (egal ob compiliert oder Script), das der Kernel ausführen soll. Alle weiteren Parameter werden als argv[]-Array an main() des ausgeführten Programms übergeben, NULL kennzeichnet dabei das Array-Ende. Im aufgerufenen Programm wird das erste Element von argv[], also argv[0], als Programmname angenommen. Man kann das aufgerufene Programm also über seinen eigenen Namen belügen -- oder aber den Namen selbst als Parameter nutzen, wie z.B. busybox.

        -w und andere Parameter pickt sich Perl auch selbst aus der Zeile 1, wenn der Interpreter schon läuft, aber der Taint-Mode muß aktiviert werden, BEVOR der Interpreter läuft. Daher bleiben an dieser Stelle nur zwei Möglichkeiten: Taint-Modus trotz anders lautenden Instruktionen ausgeschaltet lassen und unsicher weiter arbeiten, oder aber laut Zeter und Mordio schreien. Unter Sicherheitsaspekten ist nur die letzte Möglichkeit sinnvoll.

        Oder die Skripte, die auf den Taint Mode angewiesen sind, als .cgi speichern?

        Kann es sein, dass Du gerade Ursache und Wirkung durcheinander wirfst? Die Datei-Extension hat keinen Einfluß auf den Perl-Interpreter, insbesondere wird sie nicht die Logik hinter der -T-Parameter-Paranoia ändern.

        Was Du bei 1&1 beobachtest, ist, dass *.cgi anders behandelt wird als *.pl. *.cgi wird tatsächlich als stinknormales CGI ausgeführt, für *.pl läßt 1&1 irgendwelche "schwarze Magie" laufen, um trotz persistent laufendem Interpreter eine CGI-Schnittstelle zu simulieren -- leider nicht sonderlich gut.

        Denn wenn in meinem Beispiel tainted_test.CGI @INC »geschrumpft« wird, heißt es doch, dass der Taint Mode greift, oder?

        Vermutlich. Sicher gehen kannst Du, indem Du ${^TAINT} auswertest: 0=aus, 1=richtig an, -1=halb an (Warnung statt Fehler).

        Unter Windows mußt Du im Apachen "ScriptInterpreterSource Registry" auskommentieren bzw. auf script ändern, damit der Apache die Bemühungen eines Unix-Kernels simuliert, und die #!-Zeile auf "#!C:/perl/bin/perl.exe -T -w" ändern.

        Ja, aber das werde ich nicht tun, sonst vergesse ich vor dem Hochladen womöglich die Shebang auf UNIX-Shebang zu ändern, und suche dann ewig nach Fehlern, weil ich nicht mehr dran denke ;)

        Du lädst manuell hoch? Warum das? Schreibe ein Script, dass den Upload automatisiert, damit vermeidest Du jede Menge Fehler. Und ganz nebenbei kannst Du die Shebang-Zeile anpassen.

        Auf die Konfiguration beim Webhoster habe ich eh keinen Einfluß.

        KK-Antrag

        perldoc perlsec

        in ca. drei Wochen habe ich das vielleicht verstanden ;)

        Nimm Dir zwei Stunden Zeit, mehr brauchst Du nicht. Der Taint-Mode gibt nur jeder Variablen von "außen" ein weiteres internes Flag mit, dass bei allen Operationen an andere Variablen weitergegeben wird (logisches ODER), außer beim Extrahieren von Teilstrings per Pattern Matching (Eingabevalidierung). Einige wenige Routinen (open, system, exec) verweigern die Arbeit mit expliziten oder impliziten ($ENV{'PATH'}, ...) Parametern, die dieses Flag gesetzt haben. Einige wenige Libraries (mir fällt spontan nur DBI mit den Attributen TaintIn, TaintOut und Taint ein) *können* sich ebenso verhalten.

        Alexander

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

          Ich antworte hier in einem einzigen Beitrag auf Deine Postings, vielen Dank für Deine Mühe an dieser Stelle!

          Was sagt Dir der Begriff KK-Antrag?

          Ist mir bekannt! Nur, ich bin erst seit März 2007 bei 1&1 mit einem zweijährigen Vertrag... ich habe also etwas Zeit, mich umzusehen ;)

          Ich weiß aus eigener Erfahrung mit 1&1, dass dort *S*E*H*R* merkwürdige Dinge mit Perl-Scripten passieren. Man setzt offensichtlich eine Kombination aus mod_rewrite, Server Side Includes und mod_perl/Apache::Registry ein. Die HTTP-Header im Environment passen jedenfalls so überhaupt nicht zu dem, was man normalerweise im CGI-Kontext für Perl-Scripte erwartet.

          Ist mir aufgefallen. Abgesehen davon, dass es den Status-Code 500 kaum gibt (wird irgendwie redirected, denn in der access.log taucht er nie auf, sondern nur 200 - ich habe schon mehrmals berichtet), ist es mit den Umgebungsvariablen auch so eine Sache:

          Umgebungsvariablen bei der Script-Einbindung mittels SSI

          Beispiel gesuchter Ausgabe: /wae/wae_0.shtml = Pfad von aufrufender .shtml-Datei vom Document Root ausgehend...

          lokal (Xitami auf Windows) = SCRIPT_NAME

          lokal (Apache auf Windows) = DOCUMENT_URI bei <!--#exec cgi="/cgi-bin/script.pl"--> und <!--#include virtual="/cgi-bin/script.pl"-->, SCRIPT_URL in beiden Fällen undef

          communitech (Apache auf UNIX) = DOCUMENT_URI bei <!--#exec cgi="/cgi-bin/script.pl"--> und <!--#include virtual="/cgi-bin/script.pl"-->, SCRIPT_URL nicht getestet

          1&1 (Apache auf Linux) = SCRIPT_URL bei <!--#exec cgi="/cgi-bin/script.pl"--> und <!--#include virtual="/cgi-bin/script.pl"-->, DOCUMENT_URI ist bei <!--#include virtual="/cgi-bin/script.pl"--> undef

          Weitere Seltsamkeiten, der Hashbang betreffend (nicht ausgeführt -> 500er):

          1&1 (Apache auf Debian-Linux):
          .pl wird ausgeführt auch mit #!perl oder #!perlhuhn
          .cgi wird ausgeführt NUR mit #!/usr/bin/perl

          Apache lokal:
          .pl wird ausgeführt auch mit #!perl oder #!perlhuhn
          .cgi wird ausgeführt NUR mit #!perl oder #!C:\perl\bin\perl.exe, NICHT ABER mit #!/usr/bin/perl (ScriptInterpreterSource registry)

          Xitami lokal (*):
          .pl wird ausgeführt auch mit #!perl aber nicht mit #!perlhuhn
          .cgi wird ausgeführtauch mit #!perl aber nicht mit #!perlhuhn

          (*) Allerdings ist der Xitami nicht relevant, gerade was SSI angeht. Bei der Shebang wird laut der eigenen Dokumentation lediglich nach »perl« gesucht, um die bei Windows damit verknüpfte Anwendung zu starten. Wahrscheinlich sogar mit Wortgrenzen, weswegen vermutlich »perlhuhn« nicht durchgeht (naja, sollte eigentlich auch nicht, oder *g*)... Ich nehme ihn aber gerne in der Tests mit ;)

          Hast Du mod_perl aktiviert, dass auf .pl via Apache::Registry reagiert und zudem OHNE Taint-Mode läuft? Letzteres wäre ohnehin nicht sehr clever.
          Nein. Weder lokal noch bei 1&1 ist mod_perl aktiv.
          Letzteres glaube ich nicht so ganz.

          Zumindest ist die Ausgabe von $ENV{'MOD_PERL'} leer (undef?), Du hattest mir den Tipp im letzten »Tainted Love«-Thread gegeben. Lokal bringt diese Umgebungsvariable auch keine Ausgabe, genauso wie $ENV{'MOD_PERL_API_VERSION'}.

          print "MOD_PERL: $ENV{'MOD_PERL'}\n";
          print "MOD_PERL_2: $ENV{'MOD_PERL_API_VERSION'}\n";

          Das verstehe ich überhaupt nicht, sorry, ich habe von ZÄH keine Ahnung - von UNIX-Befehlen auch nicht, übrigens ;)
          Ändere das.

          Kommt Zeit, kommt (Er-)Kenntnis ;)

          Was Du bei 1&1 beobachtest, ist, dass *.cgi anders behandelt wird als *.pl. *.cgi wird tatsächlich als stinknormales CGI ausgeführt, für *.pl läßt 1&1 irgendwelche "schwarze Magie" laufen, um trotz persistent laufendem Interpreter eine CGI-Schnittstelle zu simulieren -- leider nicht sonderlich gut.

          Dazu kommen wir gleich mit den Ausgaben aus Deinem Skriptbeispiel.

          Vermutlich. Sicher gehen kannst Du, indem Du ${^TAINT} auswertest: 0=aus, 1=richtig an, -1=halb an (Warnung statt Fehler).

          Bei 1&1 vermutlich nur zu 1/4tel, sehen wir gleich...

          Du lädst manuell hoch? Warum das? Schreibe ein Script, dass den Upload automatisiert, damit vermeidest Du jede Menge Fehler. Und ganz nebenbei kannst Du die Shebang-Zeile anpassen.

          Ja, das ist eine Idee, danke - da war doch gerade dieses FTP-Modul...

          Auf die Konfiguration beim Webhoster habe ich eh keinen Einfluß.
          KK-Antrag

          Jaja, ich weiß schon... ;)

          perldoc perlsec
          in ca. drei Wochen habe ich das vielleicht verstanden ;)
          Nimm Dir zwei Stunden Zeit, mehr brauchst Du nicht.

          Naja, drei Wochen war vielleicht übertrieben, aber mit »zwei Stunden« überschätzt Du meinen Englisch. Ich kann mich zwar gut unterhalten, Small Talk mäßig, aber Lesen und Schreiben, dazu noch Technisches, bereitet mir schon Schwierigkeiten.

          Der Taint-Mode gibt nur jeder Variablen von "außen" ein weiteres internes Flag mit, dass bei allen Operationen an andere Variablen weitergegeben wird (logisches ODER), außer beim Extrahieren von Teilstrings per Pattern Matching (Eingabevalidierung). Einige wenige Routinen (open, system, exec) verweigern die Arbeit mit expliziten oder impliziten ($ENV{'PATH'}, ...) Parametern, die dieses Flag gesetzt haben. Einige wenige Libraries (mir fällt spontan nur DBI mit den Attributen TaintIn, TaintOut und Taint ein) *können* sich ebenso verhalten.

          Danke für die Erläuterungen! Das mit »open« hatte ich irgendwo gelesen, aber noch kein Praxisbeispiel gesehen. Und nun zu Deinem Beispiel:

          1. /cgi-bin/nottaint.pl => ausgeführt, ${^TAINT} ist erwartungsgemäß 0.
          2. /cgi-bin/tainted.pl => 500 Internal Server Error
          3. /cgi-bin/tainted.cgi => als Quelltext ausgeliefert! - Trotz mode 0755 und CGI-Verzeichnis

          Na, Strato und 1&1 reichen sich ja die Hand (mittlerweile lese ich, während ich diese Antwort zum zweiten Mal verfasse [**], weil mir der Browser vorhin abgeg... ist, dass sich Struppi zu Wort gemeldet hat, und ordentliche Ausgaben erzeugt), was?

          Ausgabe bei mir:
          1&1:
          tainted.pl: Klick!
          tainted.cgi: Klick!
          nottaint.pl: Klick!

          Und was sehen wir da? ${^TAINT} ist undef!!!

          Ausgabe auf dem lokalen Apache:
          tainted.pl: Internal Server Error [1]
          tainted_ap.cgi [2]:
             Tainted Love
             Taint ist: 1
             INC ist: C:/Perl/lib, C:/Perl/site/lib
          nottaint.pl:
             Tainted Love
             Taint ist: 0
             INC ist: C:/Perl/lib, C:/Perl/site/lib, .

          Ausgabe auf dem lokalen Xitami:
          tainted.pl:
             Tainted Love
             Taint ist: 1
             INC ist: C:/Perl/lib, C:/Perl/site/lib
          tainted.cgi
             Tainted Love
             Taint ist: 1
             INC ist: C:/Perl/lib, C:/Perl/site/lib
          nottaint.pl
             Tainted Love
             Taint ist: 0
             INC ist: C:/Perl/lib, C:/Perl/site/lib, .

          [1] OK. Hier hat das also mit ScriptInterpreterSource zu tun, wie Du schon mal sagtest... Was aber ist bei 1&1 los? @INC wird erwartungsgemäß »geschrumpft«, ${^TAINT} ist aber leer?

          [2] Ich musste die Shebang in #!perl -T -w ändern

          [**] Daran merkt man, dass mich das Thema interessiert. Bei ca. einer halben Stunden Testerei und Tipperei hätte ich bei jedem anderen Themal aufgegeben ;)

          Viele Grüße aus Frankfurt/Main,
          Patrick

          --

          _ - jenseits vom delirium - _
          [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
          Nichts ist unmöglich? Doch!
          Heute schon gegökt?
          1. Moin Moin!

            Weitere Seltsamkeiten, der Hashbang betreffend (nicht ausgeführt -> 500er):

            1&1 (Apache auf Debian-Linux):
            .pl wird ausgeführt auch mit #!perl oder #!perlhuhn

            Das ist für ein Unix-CGI ungewöhnlich. Das Script wird definitiv nicht per exec()-Systemcall aufgerufen, sondern irgendwie in einen schon laufenden Interpreter gezogen.

            .cgi wird ausgeführt NUR mit #!/usr/bin/perl

            So soll es sein.

            Apache lokal:
            .pl wird ausgeführt auch mit #!perl oder #!perlhuhn
            .cgi wird ausgeführt NUR mit #!perl oder #!C:\perl\bin\perl.exe, NICHT ABER mit #!/usr/bin/perl (ScriptInterpreterSource registry)

            Es gibt eine Besonderheit von Perl bei #!-Zeilen:

            If the #! line does not contain the word "perl", the program named after the #! is executed instead of the Perl interpreter. This is slightly bizarre, but it helps people on machines that don't do #!, because they can tell a program that their SHELL is /usr/bin/perl, and Perl will then dispatch the program to the correct interpreter for them. -- http://perldoc.perl.org/5.8.8/perlrun.html

            Eigentlich wäre das eher eine Erklärung, warum die C:\perl\bin\perl.exe-Variante nicht funktioniert. Denn Perl macht ein @words=split '/',$shebangline und findet dann @words=("C:\perl\bin\perl.exe"). Auch unter Windows sollst Du ÜBERALL in Perl den Forward Slash benutzen (Windows selbst hat wie auch schon DOS außer in command.com und cmd.exe damit überhaupt kein Problem).

            Hast Du eine Verknüpfung von *.cgi mit perl.exe eingerichtet? Wenn nicht, kann ich mir vorstellen, dass der Apache in höchster Not (kein sinnvoller Eintrag in der Registry) auf die Unix-Emulation ("ScriptInterpreterSource script") zurückfällt und dann "perl" und "C:\perl\bin\perl.exe" per CreateProcess() funktionieren (ersteres weil $ENV{PATH} durchsucht wird), "/usr/bin/perl" per CreateProcess() aber eben nicht.

            Wenn Du spaßeshalber ein Verzeichnis C:\usr\bin anlegst und perl.exe dorthin kopierst, müßte das auch funktionieren.

            Xitami lokal (*):
            .pl wird ausgeführt auch mit #!perl aber nicht mit #!perlhuhn
            .cgi wird ausgeführtauch mit #!perl aber nicht mit #!perlhuhn

            (*) Allerdings ist der Xitami nicht relevant, gerade was SSI angeht. Bei der Shebang wird laut der eigenen Dokumentation lediglich nach »perl« gesucht, um die bei Windows damit verknüpfte Anwendung zu starten. Wahrscheinlich sogar mit Wortgrenzen, weswegen vermutlich »perlhuhn« nicht durchgeht (naja, sollte eigentlich auch nicht, oder *g*)... Ich nehme ihn aber gerne in der Tests mit ;)

            Halbwegs sinnvolles Verhalten. Was macht Xitami, wenn ich meine CGIs durch awk oder lua laufen lassen will? Schneidet Xitami einfach alle Pfade weg und ruft dann CreateProcess() auf, in der Hoffnung, awk und lua in $ENV{PATH} zu finden, oder ist Perl ein Sonderfall?

            Hast Du mod_perl aktiviert, dass auf .pl via Apache::Registry reagiert und zudem OHNE Taint-Mode läuft? Letzteres wäre ohnehin nicht sehr clever.
            Nein. Weder lokal noch bei 1&1 ist mod_perl aktiv.
            Letzteres glaube ich nicht so ganz.

            Zumindest ist die Ausgabe von $ENV{'MOD_PERL'} leer (undef?), Du hattest mir den Tipp im letzten »Tainted Love«-Thread gegeben. Lokal bringt diese Umgebungsvariable auch keine Ausgabe, genauso wie $ENV{'MOD_PERL_API_VERSION'}.

            Hmmm, dan gäbe es noch FastCGI und PersistentPerl alias SpeedyCGI. Letzteres ist exotisch, FastCGI ist allerdings durchaus üblich. Sieh mal nach, ob in %INC (nicht @INC) etwas von FCGI.pm oder CGI/Fast.pm steht.

            Ich bezweifle nur (ohne jetzt Benchmarken zu wollen), dass das Laden und Interpretieren eines Scripts in einen laufenden FastCGI-Prozess wesentlich schneller ist als ein ganz normaler Start als eigenständiger Prozess. Erst mit massivem Caching würde so etwas sinnvoll sein, quasi ein in FastCGI nachgebasteltes Apache::Registry. Es wäre dann auch möglich, mit Safe zu arbeiten, um die Aktivitäten des Kunden-Scripts zu begrenzen. Auch wäre ein Timeout so recht einfach zu realisieren (alarm()). Mit etwas Muße müßte man sowas durchaus herausfinden können. Safe ist per %INC nachweisbar, alarm() durch Fehlermeldungen, wenn man versucht, den alarm() wieder abzuwürgen oder einen eigenen $SIG{ALRM}-Handler zu installieren.

            Und nun zu Deinem Beispiel:

            1. /cgi-bin/nottaint.pl => ausgeführt, ${^TAINT} ist erwartungsgemäß 0.
            2. /cgi-bin/tainted.pl => 500 Internal Server Error
            3. /cgi-bin/tainted.cgi => als Quelltext ausgeliefert! - Trotz mode 0755 und CGI-Verzeichnis

            Na, Strato und 1&1 reichen sich ja die Hand (mittlerweile lese ich, während ich diese Antwort zum zweiten Mal verfasse [**], weil mir der Browser vorhin abgeg... ist, dass sich Struppi zu Wort gemeldet hat, und ordentliche Ausgaben erzeugt), was?

            Ausgabe bei mir:
            1&1:
            tainted.pl: Klick!
            tainted.cgi: Klick!
            nottaint.pl: Klick!

            Und was sehen wir da? ${^TAINT} ist undef!!!

            Und vor allem: Das Perl ist ANTIK! Das Relase-Datum von Perl 5.6.1 ist der 8. April 2001. Das erklärt auch die fehlende Ausgabe von ${^TAINT}, denn in 5.6.1 ist die Variable nicht vorhanden. Andere Kleinigkeiten wie Unicode-Support und ein paar Hundert Bugfixes fehlen natürlich auch.

            $^-Variablen sind zwar für Perl reserviert, aber es ist kein Fehler, auf nicht vorhandene Variablen zuzugreifen, auch nicht auf nicht vorhandene Variablen in reservierten Namensbereichen. Wieder ein Grund für "use strict".

            Ob Taint in der Antiquität wirklich aktiv ist, mußt Du sehr umständlich rausfinden: sub is_tainted auf $ENV{'PATH'} oder sonst eine garantiert "taintete" Variable anwenden.

            Ausgabe auf dem lokalen Apache:

            Du meinst 1&1?

            tainted.pl: Internal Server Error [1]

            [1] OK. Hier hat das also mit ScriptInterpreterSource zu tun, wie Du schon mal sagtest... Was aber ist bei 1&1 los? @INC wird erwartungsgemäß »geschrumpft«, ${^TAINT} ist aber leer?

            Altes Perl.

              
            #!/usr/bin/perl  
            print "Content-Type: text/plain\r\n\r\n";  
            print "Perl-Version, alte Methode: $]\n"; # numerisch  
            print "Perl-Version, neue Methode: $^V\n"; # binär, chr(5).chr(6).chr(1)  
            
            

            Siehe perlvar.

            Alexander

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

              1&1 (Apache auf Debian-Linux):
              .pl wird ausgeführt auch mit #!perl oder #!perlhuhn
              Das ist für ein Unix-CGI ungewöhnlich.

              Ich war auch überrascht!

              Das Script wird definitiv nicht per exec()-Systemcall aufgerufen, sondern irgendwie in einen schon laufenden Interpreter gezogen.

              Sieht so aus...

              Apache lokal:
              .pl wird ausgeführt auch mit #!perl oder #!perlhuhn
              .cgi wird ausgeführt NUR mit #!perl oder #!C:\perl\bin\perl.exe, NICHT ABER mit #!/usr/bin/perl (ScriptInterpreterSource registry)
              Es gibt eine Besonderheit von Perl bei #!-Zeilen:
              If the #! line does not contain the word "perl", the program named after the #! is executed instead of the Perl interpreter. This is slightly bizarre, but it helps people on machines that don't do #!, because they can tell a program that their SHELL is /usr/bin/perl, and Perl will then dispatch the program to the correct interpreter for them. -- http://perldoc.perl.org/5.8.8/perlrun.html
              Eigentlich wäre das eher eine Erklärung, warum die C:\perl\bin\perl.exe-Variante nicht funktioniert. Denn Perl macht ein @words=split '/',$shebangline und findet dann @words=("C:\perl\bin\perl.exe"). Auch unter Windows sollst Du ÜBERALL in Perl den Forward Slash benutzen (Windows selbst hat wie auch schon DOS außer in command.com und cmd.exe damit überhaupt kein Problem).
              Hast Du eine Verknüpfung von *.cgi mit perl.exe eingerichtet?

              Ja. Habe es allerdings über die Eigenschaften von Datei, Öffnen mit -> Ändern gemacht - und nicht in der Registry nachgeprüft, ob bei es die gleichen Schlüssel wie bei .pl gibt.

              Halbwegs sinnvolles Verhalten. Was macht Xitami, wenn ich meine CGIs durch awk oder lua laufen lassen will? Schneidet Xitami einfach alle Pfade weg und ruft dann CreateProcess() auf, in der Hoffnung, awk und lua in $ENV{PATH} zu finden, oder ist Perl ein Sonderfall?

              Keine Ahnung ;)

              Hmmm, dan gäbe es noch FastCGI und PersistentPerl alias SpeedyCGI. Letzteres ist exotisch, FastCGI ist allerdings durchaus üblich. Sieh mal nach, ob in %INC (nicht @INC) etwas von FCGI.pm oder CGI/Fast.pm steht.

              print "%INC contains:\n";
              for (sort keys %INC)
              {
                print "$_ : $INC{$_}\n";
              }

              Ausgabe:

              CGI/Carp.pm : /usr/share/perl/5.6.1/CGI/Carp.pm
              Carp.pm : /usr/share/perl/5.6.1/Carp.pm
              Exporter.pm : /usr/share/perl/5.6.1/Exporter.pm

              Und vor allem: Das Perl ist ANTIK! Das Relase-Datum von Perl 5.6.1 ist der 8. April 2001. Das erklärt auch die fehlende Ausgabe von ${^TAINT}, denn in 5.6.1 ist die Variable nicht vorhanden.

              Ja. $] wird ausgegeben, $^V nicht.

              Ob Taint in der Antiquität wirklich aktiv ist, mußt Du sehr umständlich rausfinden: sub is_tainted auf $ENV{'PATH'} oder sonst eine garantiert "taintete" Variable anwenden.

              Werde mich schlau machen, danke. Ich bin dank Dir jetzt schon schlauer als vorher ;)

              Ausgabe auf dem lokalen Apache:
              Du meinst 1&1?

              Nein, das war wirklich auch der lokale Apache, wie gesagt, ich habe ScriptInterpreterSource registry noch nicht geändert.

              Viele Grüße aus Frankfurt/Main,
              Patrick

              --

              _ - jenseits vom delirium - _
              [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
              Nichts ist unmöglich? Doch!
              Heute schon gegökt?
      2. Moin Moin!

        Kann jemand mit einem anderen Webhoster ein .pl-Skript mit -T in der Shebang hochladen, und mir sagen, was passiert?

        Strato "PowerWeb A"-Paket:

        /cgi-bin/nottaint.pl => ausgeführt, ${^TAINT} ist erwartungsgemäß 0.
        /cgi-bin/tainted.pl => 500 Internal Server Error
        /cgi-bin/tainted.cgi => als Quelltext ausgeliefert! - Trotz mode 0755 und CGI-Verzeichnis

          
        #!/usr/bin/perl -T -w  
        # Dies ist tainted.pl bzw. tainted.cgi, nottaint.pl ist bis auf das fehlende -T identisch.  
          
        use strict;  
          
        print "Content-Type: text/plain\r\n\r\n";  
        print "Tainted Love\n";  
        print "Taint ist: ${^TAINT}\n";  
        print "INC ist: ",join(", ",@INC),"\n";  
        
        

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
      3. Glaube ich Dir. Nur, warum klappt das bei 1&1 nicht? Kann jemand mit einem anderen Webhoster ein .pl-Skript mit -T in der Shebang hochladen, und mir sagen, was passiert?

        Hosteurope:
        /cgi-bin/tainted.pl
        Tainted Love
        Taint ist: 1
        INC ist: (kein .)

        /cgi-bin/tainted.cgi
        Die gleich Ausgabe

        /cgi-bin/notainted.pl
        Tainted Love
        Taint ist: 0
        INC ist: ..., .

        Planethosting:
        /cgi-bin/tainted.pl
        /cgi-bin/tainted.cgi
        Tainted Love
        Taint ist: 1
        INC ist: (kein .)

        /cgi-bin/notainted.pl
        Tainted Love
        Taint ist: 0
        INC ist: (...),.

        also bei beiden Hostern, dass was man erwartet.

        Struppi.

        1. Moin Moin!

          also bei beiden Hostern, dass was man erwartet.

          So soll es sein. Zwei Kandidaten für den KK-Antrag. ;-)

          Hast Du spaßeshalber auch mal die Versionsnummern ermittelt?

          Alexander

          --
          Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
          1. also bei beiden Hostern, dass was man erwartet.

            So soll es sein. Zwei Kandidaten für den KK-Antrag. ;-)

            Ich bin auch sehr zufrieden mit denen, wobei bei Planethosting der Support sehr flapsig ist (emails strotzen vor Rechtschreibefehlern und das fällt sogar mir auf) aber die Antworten rund um die Uhr sofort auf emails. Das Backend ist sehr gewöhnungsbedürftig (und basiert fast auschließlich auf JS), dafür sind sie unschlagbar günstig.

            Hast Du spaßeshalber auch mal die Versionsnummern ermittelt?

            Ja, grad eben, bei beiden 5.008008

            Struppi.

            1. Moin Moin!

              Ich bin auch sehr zufrieden mit denen, wobei bei Planethosting der Support sehr flapsig ist (emails strotzen vor Rechtschreibefehlern und das fällt sogar mir auf) aber die Antworten rund um die Uhr sofort auf emails.

              Naja, an rääktscreipunk kann man sich irgendwann gewöhnen, notfalls winkt man mal mit dem einen oder anderen Zaunpfahl.

              Das Backend ist sehr gewöhnungsbedürftig (und basiert fast auschließlich auf JS), dafür sind sie unschlagbar günstig.

              Hast Du spaßeshalber auch mal die Versionsnummern ermittelt?

              Ja, grad eben, bei beiden 5.008008

              So soll es sein 5.10.0 ist gerade frisch rausgekommen, das würde ich auch noch nicht produktiv einsetzen. Erstmal 5.10.1 oder .2 abwarten. 5.8 war vor 5.8.1 auch nicht zu gebrauchen.

              Alexander

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