PHP-Sicherheit Benutzereingaben

Noeden

Erfahrenes Mitglied
Hallo,
ich finde zwar viel zu dem Thema, aber da es 1000 Wege nach Rom gibt, bin ich ein wenig verwirrt, wie viel ich jetzt unternehmen muss mit den Benutzereingaben.

Alle Benutzereingaben werden bei mir durch folgende function gejagt, die ich bei Bedarf erweitern würde:

PHP:
	function escapeString ($unescstr) {
		$unescstr = htmlspecialchars($unescstr, ENT_QUOTES, UTF-8);
		
		return $unescstr;
	}

Einziger Nachteil, der aber mE vernachlässigbar ist, dass bei einem Abgleich es jetzt egal ist, ob der Benutzer seine Eingabe in html-Codierung macht ode rnicht. Aber so sollten doch alle Angriffe durch Injections verhindert werden oder?

Danke

PS: Bei einem besseren Weg wäre ich für den Vorschlag und die Begründung sehr dankbar!
 
Hi,

das generelle Filtern aller Eingaben kann Probleme verursachen und ich vermeide das soweit es geht.
Alle Benutzerdaten lasse ich also unangetastet in $_POST / $_GET. Erst später, wenn ich mit den Daten arbeiten muss werden diese gefiltert / entschärft.

Bevor ich die in eine Datenbank speichere lass ich stripslashes() und danach mysql_real_escape_string() drüber. Bei der Ausgabe auf der Seite dann entsprechend stripslashes() und htmlspecialchars().

Gruß
BK
 
Ich mach das auch erst, wenn ich damit arbeite, aber halt mit ALLEM, was vom Benutzer stammt.

Beim Passwort sollte man das aber nicht machen, bzw brauch das auch gar nicht, wenn man zum Beispiel md5 drüber laufen lässt, das lässt ja eh nichts mehr übrig, oder? Wofür brauchst Du noch htmlspecialchars bei der Ausgabe? Wo ist da die Sicherheitslücke? Und was macht das noch, wenn stripslashes drüber gelaufen ist, das setzt doch schon überall n \ vor oder?

Danke
 
Hi,

das scriptslashes() mach ich halt nur, wenn die GPC_magic_quotes (oder so ähnlich) gesetzt ist. Das sorgt dafür, dass alle GET, POST und REQUEST Variablen schon mal escaped werden.

Bisschen Off-Topic:
Der Grund, warum ich Benutzerdaten wirklich unverfälscht haben will, ist wie von dir vorgeschlagen zum Beispiel bei Passwörtern. Wenn ich diese durch meine skein768()-Methode durchlasse (oder halt sha1(), aber auf keinen Fall md5(), da das nicht mehr sicher ist!) dann will ich den Hash des exakten Passworts.

Beispiel: Ich ändere per phpmyadmin das Passwort eines Users auf seinen Wunsch auf "asd'123". Man beachte das Hochkomma... Wenn ich das nun so eintrage, wird der String wie gewünscht gehasht (nachdem ich den Salt manuell hinzugefügt habe) und in der Datenbank gespeichert. Stell dir vor, es ist nun das GPC-Quotes eingeschaltet. Benutzer geht zu Login, gibt das richtige Passwort ein und kommt trotzdem nicht rein. Warum? Weil die Prüfsumme über den String "asd\'123" gebildet wird und das natürlich dann nicht passt.

Back to topic:
Grundsätzlich werden alle Daten, die direkt oder indirekt vom Benutzer kommen mit htmlspecialchars() gefiltert / entschärft, bevor ich diese auf der Seite ausgebe. Ob es nun ein String, eine Zahl oder sonst was ist ist mir relativ egal. Wenn du den String nun aber durch eine Funktion wie md5(), sha1() oder intval() durchlässt, dann kann nichts gefährliches rauskommen, ergo geb ich diese Ergebnisse dann direkt aus.

Genauso wenn ich die Daten in der Datenbank speichere (hier verwende ich halt mysql_real_escape_string()). Die Daten stehen dann 1:1 komplett unverändert in der Datenbank. Somit muss ich halt wieder meinem Mantra folgen, dass ich alles was ich auf der Seite dynamisch ausgebe durch htmlspecialchars() lasse.

Gruß
BK

// Edit: Habe mir für genau diesen Zweck eine kleine Tools-Klasse geschrieben, hier mal die für dich interessanten Teile:
PHP:
<?php
abstract class Tools {
  public static function rSafeOutput($array, $encoding='UTF-8') {
    foreach($array as $key => $val) {
      $array[$key] = self::safeOutput($val, $encoding);
    }   

    return $array;
  }

  public static function safeOutput($string, $encoding='UTF-8') {
    return htmlspecialchars($string, ENT_QUOTES, $encoding);
  }

  public static function rSafeDatabase($array) {
    foreach($array as $key => $val) {
      $array[$key] = self::safeDatabase($val);
    }   

    return $array;
  }

  public static function safeDatabase($string) {
    $erg = @mysql_real_escape_string($string);

    if($erg === FALSE) {
      trigger_error('No database connection available, using deprecated mysql_escape_string()', E_USER_WARNING);
      return @mysql_escape_string($string);
    } else {
      return $erg;
    }   
  }
}

if(get_magic_quotes_gpc()) {
  function stripArray(&$arr) {
    if(!is_array($arr)) return;

    foreach($arr as $key => $val) {
      $arr[$key] = stripslashes($val);
    }   
  }

  stripArray($_GET);
  stripArray($_POST);
  stripArray($_COOKIE);
}
?>
 
Zuletzt bearbeitet:
Noch eine "Kür" Frage:

Wäre das ein Sicherheitsmanko, die Validierung ohne das vorherige Escapen zu vollziehen? Denn das Escapen ändert ja die Zeichenlänge und fügt Sonderzeichen hinzu, die uU nicht erlaubt sein sollen.

Nach einigem Nachdenken fällt mir keine Injection ein bei der Überprüpfung von Länge und beim Abgleich mit einem regulären Ausdruck.

Danke nochmal

PS: Ich halte mich hier mega mit sowas auf und komme nicht weiter, bisschen ärgerlich
 
Hi,

ich denke du brauchst Strings für die Validierung nicht extra escapen. Da kann ja - wie du sagtest - eigentlich nichts passieren, nur beim der späteren Speicherung (in die DB) oder Ausgabe.

PS: Ich halte mich hier mega mit sowas auf und komme nicht weiter, bisschen ärgerlich
Lieber sich Zeit für eine gute Absicherung nehmen, als später nach vielen Sicherheitslücken zu suchen ;)

Ich hatte dazu auch ein Tutorial geschrieben, vieles wurde schon gesagt, aber du kannst ja trotzdem gerne reinschauen.
Sicherheit in PHP-Codes schaffen
 
Zurück