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

Beitrag lesen

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".