• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Ab wann ist ein vom Besucher geschriebner Text wirklich sicher?

ist es nicht doch irgendwie sinnvoller htmlentitiers() / htmlspeacialchars() vor dem Einfügen in die Tabelle einzusetzen. Sonst müssten die Funktionen bei zB einem Forum beim Auslesen nocheinmal angewandt werden, was eine längere Ladezeit zur Folge hat. D.h. nicht lieber einmal die Funktion nutzen anstatt bei jedem Seitenaufruf?

In Anbetracht dessen finde ich den Vorschlag von Loon3y garnicht so schlecht, da man ja nur eine Tabelle von den beiden nutzen muss, und bei dieser die Funktion dann bereits zum Einsatz kam. Auf der anderen Seite hat man volle Variabilität durch die Originaleingaben der anderen Tabelle.

Das wäre eine Form von Caching, also Zwischenspeichern einer bereits generierten Ausgabe. Das könnte man -- unabhängig vom Threadthema -- auch immer andenken. Ich würde hier wenn die Cache-Daten in eine andere Tabelle setzen (oder im Dateisystem ablegen), um eine sauberere Trennung zwischen "echter" Datenhaltung und Cache-Funktionalität zu erreichen. Recyclter Post:

Ich hänge dem Paradigma an, konsequent Originaldaten zu speichern, um flexibel jede Art von Ausgabe erzeugen zu können, die die Daten zulassen. Wenn du beispielsweise vor dem Eintragen in die Datenbank bereits ein htmlspecialchars über die Daten bügelst, dann aber später feststellst, dass du doch ganz gerne noch weitere Entities ersetzt hättest, weil du die Daten als ISO-8859-1 ausgeben willst, stehst du vor dem Problem, dass dir das htmlspecialchars aus "<" bereits "&lt;" gemacht hat und ein weiteres htmlentities daraus ohne vorherige Rückumformung erstmal ein "&amp;lt;" machen würde.

Mir fällt spontan kein überzeugendes Beispiel ein, aber man kann zu sehr unschönen Lösungen gezwungen sein, wenn man die Originaldaten in etwas weiterverarbeitet hat, das doch nicht so optimal war, wie man anfangs dachte.

Nimm vielleicht einen BBCode-Parser. Die laufen [üblicherweise] auch erst vor der Ausgabe, nicht nach der Eingabe, um nachträglich Änderungen am Parser vornehmen zu können und um nachträglich den Code bearbeiten zu können.​

Vielleicht wäre ein Argument speziell gegen htmlentities, dass ein "Märchen => M&auml;rchen" von der Datenbank nicht mehr in einer Textsuche zu finden ist.
 
Ja, klar. Mein Gedanke dahinter war, dass das Datenbanksystem an der Stelle dann aber nicht mehr ein einziges Wort annimmt ("Und"-Zeichen und ein Semikolon dazwischen) und "Märchen" gar nicht als Einzelbegriff in einen Suchindex aufgenommen würde. Ist aber wohl nicht so wichtig, wenn du einfach das Feld mit LIKE oder so durchsuchst. Zu htmlspecialchars habe ich oben versucht, was zu schreiben.

Wie gesagt, ich weiß kein besonders einleuchtendes Beispiel, wo es wirklich zu Problemen führt, nicht die Originaldaten gespeichert zu haben. Es mag vielfach auch egal sein oder Schwierigkeiten würden nie auftreten.

Ich möchte es dennoch nicht empfehlen.

PS: htmlentities braucht man im Grunde nur noch, wenn das Ausgabe-Charset nicht UTF-8 ist. Ich verwende seit Jahr und Tag nur noch htmlspecialchars.

struppi schrieb:
Wieso überhaupt ausreichen? Hat die Funktion irgendwelche Vorteile gegenüber mysql(i)_real_escape_string?

mysql(i)_real_escape_string ist und bleibt die richtige Funktion. Da können sich alle Leute hier auf den Kopf stellen. ;)
 
(Doppelpost, weil es sonst vielleicht keiner findet.)

Hier habt ihr auch euer SQL Injection Szenario:

PHP:
<?php

$param = 'test\\';
$param2 = '; DROP TABLE `tbl`; --';

$q = "SELECT `col1` FROM `tbl`
      WHERE  `col2` = '" . htmlentities($param) . "'
      AND    `col3` = '" . htmlentities($param2) . "'";
echo $q;

Ausgabe:

Code:
SELECT `col1` FROM `tbl` WHERE `col2` = 'test\' AND `col3` = '; DROP TABLE `tbl`; --'

Etwas realistischer:

PHP:
<?php

$name = '\\';
$password = ' OR 1 ORDER BY `id` ASC LIMIT 0,1--';

$q = "SELECT `id` FROM `users`
      WHERE  `name`     = '" . htmlentities($name) . "'
      AND    `password` = '" . htmlentities($password) . "'";
echo $q;

Würde den Besucher vermutlich als Nutzer mit ID 1 einloggen.

(Etwas akademisch, aber you get the point.)
 
Zuletzt bearbeitet:
Hey,

ich hätte nicht gedacht das dieser Thread mal 3 Seiten lang wird. :)

Eure Antworten haben mir sehr geholfen, doch habe ich jetzt noch eine Frage. Ich habe eine GET Variable in der ich eine Zahl erwarte, diese Variable überprüfe ich mit is_int() und wenn es ein andere Datentyp ist gebe ich einen error aus, andernfalls wird das Skript normal abgerabeitet. Diese Methode ist Sicher oder kann in Integer Schadcode sein?

Natürlich bin ich mir bewusst, das die Zahl falsch sein kann, aber das werde ich nach einer Datenbankabfrage mit num_rows() testen.


Gruß xXxPeterPanxXx
 
In Integern kann kein Schadcode sein, nein. Nur dürften alle Variablen in $_GET vom Typ String sein. Ich habe das bisher nur mit Typecasting gesehen:

PHP:
$_GET['id'] = (int) $_GET['id'];

So wird der Wert von $_GET['id'] zu einem Integer gecastet.

PHP: Type Juggling - Manual
 
htmlspecialchars vor dem Eintragen ist völliger Schwachsinn
Denk nur mal an ein Forum wenn es einem Admin erlaubt ist HTML zu nutzen und Usern nicht dann muss das bei der Ausgabe gemacht werden weil vlt ist jmd. jetzt User und in 2 Wochen Admin dann bekommst du richtig Probleme.. nur mal so als Beispiel
und zwecks SQL injections hat mermshaus ja eh schon schön erklärt :-)
 
wenn ich ein normales input feld befüllen möchte, nutze ich:

PHP:
static function sToInputText($var)
	{
		return str_replace(array('/', '\\'),'',(htmlentities(strip_tags($var), ENT_QUOTES, 'UTF-8')));
	}

Bei Textareas u. etc

PHP:
htmlentities($var, ENT_NOQUOTES, 'UTF-8');

wenn man einen wert aus einer superglobalen nutzt: ( bitte beachten, dass diese funktion nur einmal für jede superglobale aufgerufen werden darf!)

PHP:
...
if(get_magic_quotes_gpc())
	$_POST['data'][$model][$field] = stripslashes($_POST['data'][$model][$field]);
...

um zu prüfen ob der wert ein int ist:

PHP:
static function sIsInt($var)
	{
		if((string)((int)$var) !== $var)
			return false;
			
		return true;
	}

bei jeder datenbanktransaktion wird alles was kein int ist mit mysql(i)_real_escape_string abgesichert, eine alternative wäre die nutzung von PDO PHP: PDOStatement->bindParam - Manual
 
Zuletzt bearbeitet:
Zurück
Oben