Tom23: Bitte um kurzes Review

Beitrag lesen

Hallo Alexander

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

Vielen Dank für die lehrreiche Antwort!  Dies hier habe ich angepasst und mit Mühe und Not wieder zum Laufen gebracht. Guter Hinweis auf perlsec! Aber ich hab da noch ein paar Fragen...

use constant XHTMLTEMPLATE => '../RealWorld/template.xsl';
Wer oder was garantiert Dir, dass das Script im "richtigen" Verzeichnis aufgerufen wird? Absolute Pfade würden meiner Paranoia weniger weh tun.

Es gibt nur ein CGI-Verzeichnis auf dem Webserver. Ich bevorzuge eigentlich relative Pfade weil ich sie für flexibler halte (sofern Relationen stimmen): Ich kann das komplette '../'-Verzeichnis frei bewegen. Warum macht dir das Angst? Ich habe jetzt trotzdem absoltue Pfade verwendet:

Set configuration constants

use constant BASEPATH => '/var/www/';
use constant FEED => BASEPATH . 'RealWorld/xhtml/news.xml';

use constant PLAINCACHE => 'feed.tmp';
Das aktuelle Verzeichnis ist für den WWW-User (sprich: das GESAMTE Internet) BESCHREIBBAR? SOFORT ABSTELLEN!

Sowas in der Art habe ich erwartet ;-) Aber keine Angst, das Skript hängt nicht am Netz.
Es ist nur diese eine Datei durch www-data veränderbar. Das Skript und die Temp-Datei liegen im CGI-Verzeichnis, wobei der Apache "nur" .cgi-Dateien ausführen darf. feed.tmp ist aber nicht executable und wird vor jeder Verwendung komplett neu erzeugt.

»  Ansonsten benutze ein Modul, das sicheren Umgang mit Temp-Files garantiert.
Zum Beispiel File::Temp? Das muss ich morgen mal ausprobieren.

Auf diese Art sparst Du Dir jede Menge Ärger mit der Shell (siehe unten) und übergibst xsltproc nur geprüfte Parameter.

Filtern habe ich probiert, nur mit dem Untainting hat es nicht auf Anhieb geklappt. Da ich zumindest $mode auch als Variable brauche, habe ich die zwei Schritte beibehalten:

Untaint parameters

$id   = ($id   =~ /^(\d+)$/) ? $1 : undef;
$cat  = ($cat  =~ /^(\w+)$/) ? $1 : undef;
$mode = ($mode =~ /^(\w+)$/) ? $1 : undef;

Compose xsltproc parameters

push @param, '--param','entry',$id if $id;
push @param, '--stringparam', 'category', $cat if $cat;
push @param, '--stringparam', 'param', "m=$mode" if $mode;

system('cat '.FEED);
Wer garantiert Dir, dass nicht irgendwo in $ENV{'PATH'} ein cat-Programm existiert, das etwas völlig Unerwartetes macht (böse Sprüche ausgeben, Festplatte plätten, Oma umbringen)?

Ähm... $ENV{'PATH'} = '/usr/bin/'; # Jetzt neu in meinem Skript (für xsltproc)

open FILE,'<',FEED or die; print while <FILE>; close FILE;

Das habe ich übernommen.

system("/usr/bin/xsltproc $xslt_param_plain ".XHTMLTEMPLATE.'
Parameter solltest Du in einem Array übergeben, statt sie erst zu einem String zusammenzukleben, die die Shell wieder auseinander pflücken muß (und dabei gelegentlich katastrophalen Mist baut).

Habe ich nun auch gemacht. In @xslt sthet der Befehl und die sauberen, beiden Aufrufen gemeinsamen Werte. Den Rest hänge ich so an:

system(@xslt, XHTMLTEMPLATE, PLAINCACHE);

Temp-File ist unnötig, Du kannst das Programm direkt nach STDOUT schreiben lassen. Fester Name für das Temp-File bedeutet Datenverlust bei gleichzeitigem Zugriff mehrerer Benutzer.

Leider brauche ich das Temp-File. Ich schreibe nun über die --output-Option von xsltproc in die Datei. Ob dies vor simultanen Zugriffen schützt wage muss ich noch abklären. Eine geschützte Datei würde sich gut als Cache eignen, aber eventuell werde ich für jeden Aufruf eine eigene Temp-Datei erzeugen müssen.

perldoc perlipc: Safe Pipe opens sollte Dir helfen. Im Child machst Du jeweils ein exec @xlst_with_arguments ohne IO Redirection, im Parent ein print while <KID_TO_READ>.

Phu, das war schwere Kost! Doch leider scheinen mir diese Pipes für meinen Zweck nicht ganz richtig geeignet. (Ich brauche Dateien, nicht deren Inhalt).

Ich habe schon ein paar mal versucht das Modul XML:LibXSLT zu installieren, doch leider haut das bei mir nicht hin. Konnte nicht heraus finden wo das Problem liegt. Doch um von den system-Calls weg zu kommen gibt es wohl nichts besseres.

Denkst du das haut jetzt hin? Gruss & Dank

Tom