Sie sind hier : basti1012.de/ Themen-Blog1 / htmlspecialchars-richtig-nutzen-fallstricke.php

htmlspecialchars richtig nutzen – Fallstricke

In der PHP-Welt scheint der Mythos vorzuherrschen, dass die Nutzung von htmlspecialchars sämtlichen Input in sämtlichen Situation sicher macht. Quasi die „one fits all“ – Funktion. Beginnen wir gleich mal mit einem Beispiel. Kein Witz, so gesehen:

function get_user_id($db)
{
	$username = htmlspecialchars(trim($_POST['username']));
	$res = $db->query("SELECT `id` FROM `accounts` WHERE `login` = '$username' LIMIT 1");
	return $res[0]['id'];
}

Cool! Schauen wir uns doch mal die Signatur von htmlspecialchars an:

string htmlspecialchars ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = 'UTF-8' [, bool $double_encode = true ]]] )

Das verflixte Hochkomma

Besonderes Augenmerk sei auf die Flags gelegt. ENT_COMPAT heißt „Konvertiert nur doppelte Anführungszeichen und lässt einfache Anführungszeichen unverändert.„. Also: Perfektes Einfallstor für SQL-Injection.

Gleiches ergibt sich im Formularhandling:

<?php
$_GET['firstname'] = "'onmouseover='alert(/xss!/)'";
$firstname = htmlspecialchars($_GET['firstname'], ENT_COMPAT);
?>
<input name='firstname' value='<?php echo $firstname ?>'>

Analog zu diesem PHP WTF-Artikel erfreut auch hier die !sinnvolle Wahl der Defaultparameter. Der Flags-Parameter sollte also in jedem Fall ENT_QUOTES enthalten, so werden nämlich auch Single-Quotes durch das entsprechende Pendant &#039; ersetzt.

Encoding

Seit PHP 5.4 ist der dritte Parameter string $encoding sinnvollerweise auf UTF-8 gesetzt. Vorher kam htmlspecialchars mit ISO-8859-1 als Standard daher. Bei der Frage des Encodings gilt: Immer dasselbe Encoding verwenden, das auch die Applikation selbst verwendet. Und das sollte ja in der Regel UTF-8 sein. Deswegen in Libraries am Besten eine eigene Wrapperfunktion bauen, die genau so aussieht:

function real_htmlspecialchars($string)
{
	return htmlspecialchars($string, ENT_QUOTES, "UTF-8");
}

Und trotz dessen: Für Datenbankparameter ist htmlspecialchars tabu! PDO bietet die quote-Funktion und wer wirklich noch mit nacktem MySQL rumjuckeln muss freut sich über mysql_real_escape_string oder alterantiv die Escape-Funktion des verwendeten Frameworks.

Interessant auch, wie es „die Großen“ betreiben: Die u.a. von Symfony verwendete Template-Engine Twig (siehe twig_escape_filter) und der Zend-Escaper kann man sich mal zu Gemüte führen. Sehr lesenswert ist auch das eingereichte Proposal für einen vernünftigen, kontextabhängigen PHP-builtin-Escaper.