ini_set(session.cookie_httponly,1);
ini_set(session.use_trans_sid,0);
ini_set(session.use_only_cookies,1);
Die Zeilen tun gar nichts. (Anführungszeichen um die Strings vergessen.) Ruhig mal das Error-Reporting aktivieren. Entweder in der php.ini oder per:
PHP:
ini_set('display_errors', 1);
error_reporting(E_ALL); // Vor PHP 5.4: E_ALL|E_STRICT schreiben
$fehler[] = "Bitte Nutzereingaben überprüfen!";
Sortier deine Charsets.
Es gibt praktisch keinen Grund, Umlaute als Entities zu schreiben.
In der Regel beste Lösung: Editor auf UTF-8 (NFC, ohne BOM) einstellen und in PHP den UTF-8-Charset-Header setzen:
PHP:
header('Content-Type: text/html; charset=UTF-8');
Hinter header-Zeilen mit Location tendenziell immer ein exit; setzen, weil das PHP-Skript sonst erst mal weiterläuft. (Ist im Einzelfall bei Codeausschnitten schwierig zu beurteilen, ob das beabsichtigt ist oder nicht.)
htmlentities($string, ENT_QUOTES, "UTF-8");
Besser:
htmlspecialchars($string, ENT_QUOTES, 'UTF-8'); Der Grund ist der gleiche wie bei ü oben: Es müssen lediglich die syntaktisch relevanten Zeichen (<, >, ", ', &) maskiert werden. Bei anderen Zeichen erfüllt eine Maskierung keinen wirklichen Zweck.
Dann vielleicht noch mal zu der Sache mit dem Schutz gegen JavaScript. Das ist eigentlich überhaupt kein Sonderfall und ist ganz normal mit dem erwähnten htmlspecialchars (mit ENT_QUOTES) auch erledigt.
Kontextwechsel nach HTML: htmlspecialchars und fertig. Ob in den Daten nun JavaScript-Code steht oder HTML oder PHP-Code oder sonst was, ist völlig egal.
Der „Sonderfall“ bei JavaScript ist der, dass JavaScript-Code über manche HTML-Attribute ausgeführt werden kann.
<div onclick="alert('foo');">click</div>
<a href="javascript:alert('foo')">click</a>
Für so was gibt es keine Escaping-Funktion. Das ist kein Kontextwechselproblem, sondern ein anwendungslogisches Problem.
Bei der ersten Zeile ist es wohl einsehbar, dass es keine gute Idee ist, Nutzereingaben überhaupt – oder zumindest ungefiltert – in derlei Event-Handler zu schreiben. Wie eine Filterung aussehen könnte, ist Sache der Anwendungslogik. Das sollte schon korrekt dort ankommen, wo die Ausgabe zusammengebaut wird.
Bei der zweiten Zeile ist es genauso. Es fällt in die Zuständigkeit der Anwendung, erst gar keine „javascript:“-URIs zu akzeptieren oder an den Ausgabeteil durchzureichen. Das sollte nicht erst beim Generieren der Ausgabe auffallen, weil der Code dort nicht die Befugnisse hat, zu entscheiden, ob JavaScript-Code an der Stelle gewollt ist oder nicht. Es gibt halt auch zig andere Fälle, in denen der Ausgabeteil darauf vertraut, dass die Restanwendung richtige Daten liefert. Wieso sollte er es hier nicht tun?
Edit: Der Ausgabeteil hat sich in Sachen Escaping und dergleichen mit dem Kontextwechsel zum Zielformat zu befassen. Das ist seine Aufgabe.
Das war jetzt zumindest die Theorie. Aber werden wir mal praktisch.
Es ist zufällig simpel, auf „javascript:“-URIs zu prüfen, und man kann recht sicher sagen, dass die Dinger
quasi nie gewollt sind, und es ist bekannt, dass genau dieses Einschleusen von JS-Code einer der prominentesten Angriffsvektoren ist. Deshalb tue ich mich schwer, ernsthaft zu sagen, dass entsprechende Checks im Ausgabecode nichts zu suchen haben – ungeachtet der Tatsache, dass sie dort meines Erachtens an der falschen Stelle stehen.
Die Funktion, von der ich spreche, würde ungefähr so aussehen (ungetestet):
PHP:
function blockXss($uri)
{
if (0 === strpos(strtolower(trim($uri)), 'javascript:')) {
throw new Exception('JavaScript URI slipped through');
}
return $uri;
}
Anwendung (escape() ist die normale htmlspecialchars-ENT_QUOTES-Funktion):
PHP:
<a href="<?=escape(blockXss($uri))?>">click</a>
Aber man sieht an dem Code meiner Meinung nach schon ganz schön, dass das so ein wenig was von „Ich vertraue meiner eigenen Anwendung nicht“ hat. Das ist etwas schizophren. Dann wiederum ist Vertrauen gut, aber Kontrolle besser.