Nutzereingaben in .php speichern - Wie maskieren?

Roin

Freier Denker
Registriert
22 Juli 2013
Beiträge
581
Hi Leute,

[src=php]$host = $_POST['host'];
$user = $_POST['user'];
$pw = $_POST['pw'];
$name = $_POST['name'];

$databaselogin = "<?php"."\n";
$databaselogin .= "\$db['host'] = '".$host."';"."\n";
$databaselogin .= "\$db['user'] = '".$user."';"."\n";
$databaselogin .= "\$db['pw'] = '".$pw."';"."\n";
/*...*/[/src]
Wenn ich etwas deratiges habe. Wie sollte ich dann die Daten maskieren, damit mir damit keine "bösen" Daten in die Datei geladen werden können?

Ich habe leider vergeblich nach etwas wie phpspecialchars() oder so gesucht.

Ich lasse während ein "Install"-Skript durchläuft mehrere Dateien erstellen die halt so, oder so ähnlich erstellt werden.
Allerdings könnte, solange der Installationsvorgang noch zugänglich ist, theoretisch (zufällig) ein Angreifer in diesen 10min oder so, auf die Datei zugreifen und unerwünschte Dateien einschleusen. Muss ich mir da selber extra eine Funktion überlegen, die auf php-Funktionen prüft?
Wie könnte die aussehen, was muss ich beachten?

Bei all meinen Suchen habe ich bisher immer nur gefunden wie man Formulare mit php erzeugt, aber nicht wie man über ein Formular (sicher) php-Code erzeugt.

Vielleicht kann mir hier ja einer weiterhelfen.

LG
 
Du könntest anhand der Nutzer-Eingaben erstmal testen ob eine Verbindung zur Datenbank damit möglich ist, bevor du die Login-Daten in eine Datei schreibst. Andere Datensätze lassen sich ggf. auch vorher validieren. Eine sichere Methoden PHP-Code zu filtern/maskieren wäre mir nicht bekannt.
 
  • Thread Starter Thread Starter
  • #3
Du könntest anhand der Nutzer-Eingaben erstmal testen ob eine Verbindung zur Datenbank damit möglich ist, bevor du die Login-Daten in eine Datei schreibst.

[src=php]<?php
if(!isset($_POST['host'],
$_POST['user'],
$_POST['name'],
$_POST['pw'])) {
define('ERROR');
} elseif(!mysql_connect($_POST['host'], $_POST['user'], $_POST['pw'])) {
define('ERROR');
} elseif(!mysql_select_db($_POST['name'])) {
define('ERROR');
} else {
$host = $_POST['host'];
$user = $_POST['user'];
$pw = $_POST['pw'];
$name = $_POST['name'];

$databaselogin = "<?php"."\n";
$databaselogin .= "\$db['host'] = '".$host."';"."\n";
$databaselogin .= "\$db['user'] = '".$user."';"."\n";
$databaselogin .= "\$db['pw'] = '".$pw."';"."\n";
$databaselogin .= "\$db['name'] = '".$name."';"."\n";
$databaselogin .= "\n";
$databaselogin .= "mysql_connect(\$db['host'], \$db['user'], \$db['pw']);"."\n";
$databaselogin .= "mysql_select_db(\$db['name']);"."\n";
$databaselogin .= "?>";
?>[/src]
Also im Endeffekt einfach so?
 
Joa, so im Prinzip - so ist zumindest sichergestellt, dass die Datenbank-Paramter richtig sind.
 
Allerdings schützt das nicht zuverlässig vor einer PHP-Code-Injection. Ein Angreifer könnte als Hostname einen eigenen MySQL-Server angeben, welcher beliebige Zugangsdaten akzeptiert, z.B. `';eval($_GET[e]);?>` als Benutzername und/oder Passwort. Ausserdem führt dein Ansatz zu Problemen, wenn der Benutzername oder das Passwort `'` oder `\` enthalten - zumindest diese Zeichen solltest du durch `\'` bzw. `\\` maskieren. Ausserdem wäre sinnvoll, beim ersten Aufruf des Installationsskripts sofort eine Lock-Datei zu erstellen, welche einen weiteren Aufruf verhindert.
 
Du könntest natürlich auch gewisse Zeichen explizit oder implizit ausschließen (bzw. nur einen bestimmten Satz an Zeichen zulassen).
Dass du damit Gefahr läufst dass deine Routine nicht alle (SQL-Server seitig erlaubten) Benutzernamen zulässt, ist natürlich problematisch.

Du könntest die Zeichenfolge natürlich auch base64 kodiert speichern:

[src=php]$databaselogin .= "\$db['user'] = '".base64_encode($user)."';";[/src]

und bei der Verwendeung:

[src=php]base64_decode($db['user']);[/src]
 
  • Thread Starter Thread Starter
  • #7
Wenn ich deine Lösung verwende accC, dann würde jedes weitere maskieren unnötig werden, richtig?
 
Wenn du die Daten nicht irgendwie weiter verwenden möchtest, dann sollte keine weitere Maskierung nötig werden.
Tabellenprefixe, die du in deine Querys einbaust, sollten natürlich weiter maskiert werden, etwa mit mysqli_real_escape_string (wahlweise mit oder ohne i, je nachdem, ob du von dem einen oder anderen Gebrauch gemacht hast) oder einem Äquivalent.
Auch für die Ausgabe müsstest du weiter maskieren, da dann mit htmlspecialchars oder einem Äquivalent.

Ich weiß allerdings auch nicht genau, ob base64 nur unproblematische Ausgaben erzeugt. bevor ich dir jetzt etwas falsches sage, solltest du dir die entsprechende Funktion mal genauer anschauen.
 
  • Thread Starter Thread Starter
  • #9
Wenn du die Daten nicht irgendwie weiter verwenden möchtest, dann sollte keine weitere Maskierung nötig werden.
Ich werde lediglich einmal eine Verbindung zu der Datenbank herstellen (in der Abfrage vorher). Danach wird die erzeugte Datei aufgerufen, wenn eine Datenbankverbindung benötigt wird. Sonst werden die Daten nicht mehr verwendet.
 
In einem *_connect() sollte das keine Probleme bereiten.
Nur wie gesagt, denke daran, dass du die Kodierung wieder aufheben musst: mysql(i)_connect(base64_decode($host), ...)
 
  • Thread Starter Thread Starter
  • #11
Wird dran gedacht ;-)

Danke für die Hilfe
 
  • Thread Starter Thread Starter
  • #13
spielt Cross-Site-Scripting keine Rolle?
Im Endeffekt habe ich genau das gefragt.
Damit keine XSS-Schwachstelle entsteht reicht es wohl, wenn ich Datenbankzugangsdaten wie oben beschrieben abspeichere und direkt in die Funktion einsetzte.
Da die gespeicherten Daten durch die base64-Codierung "entschärft" abgespeichert und direkt in die Funktion eingesetzt wurden, können diese Daten nicht mehr in einem anderen Kontext verwendet werden - somit sollte, wie ich es verstanden haben, kein Problem mehr auftreten können.
Zumindest nicht durch diese Eingabe ;-)
 
Ich würde an deiner Stelle ein Framework einsetzen, dass dir diese Funktionalität bietet und absichert.
 
spielt Cross-Site-Scripting keine Rolle?

Wenn keine Ausgabe und kein Ausführen der Eingabe angedacht ist, nicht.

In einem mysql_connect(); gewöhnlich nicht, in einem echo(); schon.
Allerdings maskierst du ja auch je nach Weiterverarbeitung anders.

[src=php]$evilString;

mysql_query("DO SOMETHING WITH " . $evilString); // böse
mysql_query("DO SOMETHING WITH " . mysql_real_escape_string($evilString)); // gut

echo "he said: " . $evilString; // böse
echo "he said: " . htmlspecialchars($evilString); // gut[/src]

Im mysql_query will ich mich vor SQL-Injections schützen, daher muss ich "nur" sicherstellen, dass der MySQL-Server im $evilString keinen Code interpretiert. Im Fall von echo möchte ich mich vor bösen HTML und/oder JavaScript "Code" schützen, den der Browser eines Clients dann interpretieren würde.

Der Schnipsel ist natürlich weder vollständig noch bietet er hundertprozentige Sicherheit, er ist lediglich als kurzer Hinweis auf die Unterscheidung gedacht.
 
Zurück
Oben