QuiBui LE download

Download QuiBui LE Version 1.5.1 (beta)

Freitag, 29. Februar 2008

HTML-Ausgabe ohne XSS-Schwachstelle

Bei den "Best practices" des BSI von 2006 wird unter anderem die Filterung der Ausgabedaten behandelt. Es gibt dazu ein Beispiel einer Filterfunktion für Perl. Für PHP wird nur auf die üblichen Funktionen verwiesen.

* strips_tags()
* htmlentities()


Beide Funktionen können nicht immer sicherstellen, dass XSS-Schwachstellen abgedichtet sind.

strip_tags() entfernt HTML-Tags aus dem Eingabestring. Es werden aber nicht immer Tags gebraucht, um JavaScript-Code zu injizieren. Ist die Feldausgabe (value) nicht mit Hochkommas (") abgeschlossen, kann über JavaScript-Events erfolgreich XSS betrieben werden.

Beispiel: INPUT-Feld mit nicht abgeschlossenem "value"

echo "<input name=id value=" . $_GET['id'] . " type=text>";


Beispiel: JS-XSS-Code

3 onclick=alert('XSS')


Beispiel: XSS-Code in INPUT-Tag

<input name=id value=3 onclick=alert('XSS') type=text>


Sobald der Nutzer dort klickt, wird der Code ausgeführt. Was höre ich da? "magic_quotes_gpc" ist an? Ausgabe wird zuvor mit htmlentities() kodiert und anschließend mit strips_tags() behandelt? (Jetzt zappelt da nix mehr!)

Beispiel: XSS-Code, dem "magic_quotes_gpc", htmlentities() und strips_tags() nichts anhaben kann

3 onclick=eval(String.fromCharCode(97,108,101,114,116,40,39,88,83,83,39,41))


Wir sehen: XSS-Schutz ist mit Blacklist-Filter keine gute Idee. Die "Best practices" des BSI haben aber für Perl einen schönen Whitelist-Filter. Heißt: was nicht erlaubt ist, wird kodiert. Und erlaubt ist wenig:

Beispiel: Erlaubte Zeichen des Whitelist-Filters

a-z A-Z 0-9 _ . -


Die Übertragung des Filters von Perl nach PHP ist nicht schwer. Ergibt also einen Ausgabefilter für PHP, welches alle Zeichen außer den oben genannten nach Hexadezimal kodiert.

Beispiel: PHP-Whitelist-Filter


function seq_string_reformat_($match_ = '') {
return sprintf('&#x%04x;', ord($match_[1]));
}

function SEQ_OUTPUT($string_ = '') {
$string = seq_remove_slashes_($string_);
$string = preg_replace_callback('/([^a-zA-Z0-9_.-])/', "seq_string_reformat_", $string);
return $string;
}


ANMERKUNG: Die Funktion "seq_remove_slashes_" findet sich im Post davor!

Freitag, 22. Februar 2008

PHP: "intelligent" Slashes entfernen

Eine Funktion, die etwas "Intelligenz" bei der Säuberung der Ausgabe vor "Escapes" (\) verwendet. Ganz egal, ob der String aus POST, GET, COOKIE (mit ein- oder ausgeschaltetem "magic_quotes_gpc") kommt oder aus der Datenbank ("escaped" oder nicht), er wird korrekt aber ohne Escape-Zeichen (\) ausgegeben.

function seq_remove_slashes_($string_ = '') {
if (
get_magic_quotes_gpc()) {
$string_ = stripslashes($string_);
}
$orig = $string_;
$stripped = stripslashes($orig);
if (
$orig != $stripped) {
$escaped = addslashes($stripped);
if (
$orig == $escaped) {
$sec_value = stripslashes($escaped);
} else {
$sec_value = $orig;
}
} else {
$sec_value = $orig;
}
return
$sec_value;
}






c:\docc:\doc
EingabeAusgabe
c:\\docc:\doc
O\'ReillyO'Reilly
c:\\doc\\O\'Reillyc:\doc\O'Reilly
c:\doc\O'Reillyc:\doc\O'Reilly


ANMERKUNG:

Die Funktion entscheidet nicht für Teilstrings, ob eine Konvertierung erfolgt oder nicht. Wenn die Eingabe also gemischte ("escapte" und nicht "escapte") Stringstücke enthält, wird NICHT konvertiert.

c:\doc\O\'Reillyc:\doc\O\'Reilly