2769 Stimmen

Wie kann ich SQL-Injection in PHP verhindern?

Wenn Benutzereingaben ohne Änderung in eine SQL-Abfrage eingefügt werden, wird die Anwendung anfällig für SQL-Einschleusung , wie im folgenden Beispiel:

$unsafe_variable = $_POST['user_input']; 

mysql_query("INSERT INTO `table` (`column`) VALUES ('$unsafe_variable')");

Das liegt daran, dass der Benutzer etwas eingeben kann wie value'); DROP TABLE table;-- und die Abfrage wird:

INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')

Was kann getan werden, um dies zu verhindern?

241voto

nbari Punkte 22791

Wenn Sie die Vorteile von Cache-Maschinen nutzen möchten, wie Redis o Memcached könnte vielleicht DALMP eine Option sein. Es verwendet reine MySQLi . Prüfen Sie das: DALMP Datenbankabstraktionsschicht für MySQL mit PHP.

Außerdem können Sie Ihre Argumente "vorbereiten", bevor Sie Ihre Abfrage vorbereiten, so dass Sie dynamische Abfragen erstellen können und am Ende eine vollständig vorbereitete Abfrage mit Anweisungen haben. DALMP Datenbankabstraktionsschicht für MySQL mit PHP.

236voto

Xeoncross Punkte 53024

Für diejenigen, die sich nicht sicher sind, wie man PDO benutzt (und die von der mysql_ Funktionen), habe ich eine sehr, sehr einfacher PDO-Wrapper das ist eine einzelne Datei. Es soll zeigen, wie einfach es ist, all die üblichen Dinge zu tun, die Anwendungen benötigen, um erledigt zu werden. Funktioniert mit PostgreSQL, MySQL und SQLite.

Im Grunde genommen, lesen Sie es während Sie das Handbuch lesen um zu sehen, wie man die PDO-Funktionen in der Praxis einsetzt, um das Speichern und Abrufen von Werten im Format zu vereinfachen Sie wollen.

Ich möchte eine einzelne Spalte

$count = DB::column('SELECT COUNT(*) FROM `user`');

Ich möchte ein Array(Schlüssel => Wert) Ergebnisse (d.h. für die Erstellung einer Selectbox)

$pairs = DB::pairs('SELECT `id`, `username` FROM `user`');

Ich möchte ein einzeiliges Ergebnis

$user = DB::row('SELECT * FROM `user` WHERE `id` = ?', array($user_id));

Ich möchte eine Reihe von Ergebnissen

$banned_users = DB::fetch('SELECT * FROM `user` WHERE `banned` = ?', array('TRUE'));

231voto

Danijel Punkte 11880

Einige Richtlinien für die Umgehung von Sonderzeichen in SQL-Anweisungen.

Verwenden Sie nicht MySQL . Diese Erweiterung ist veraltet. Verwenden Sie MySQLi o PDO stattdessen.

MySQLi

Um Sonderzeichen in einer Zeichenkette manuell zu escapen, können Sie die mysqli_real_escape_string Funktion. Die Funktion funktioniert nicht richtig, wenn nicht der richtige Zeichensatz mit mysqli_set_charset .

Ejemplo:

$mysqli = new mysqli('host', 'user', 'password', 'database');
$mysqli->set_charset('charset');

$string = $mysqli->real_escape_string($string);
$mysqli->query("INSERT INTO table (column) VALUES ('$string')");

Für das automatische Escaping von Werten mit vorbereiteten Anweisungen verwenden Sie mysqli_prepare y mysqli_stmt_bind_param wobei die Typen für die entsprechenden Bindungsvariablen für eine entsprechende Konvertierung angegeben werden müssen:

Ejemplo:

$stmt = $mysqli->prepare("INSERT INTO table (column1, column2) VALUES (?,?)");

$stmt->bind_param("is", $integer, $string);

$stmt->execute();

Unabhängig davon, ob Sie vorbereitete Erklärungen verwenden oder mysqli_real_escape_string müssen Sie immer die Art der Eingabedaten kennen, mit denen Sie arbeiten.

Wenn Sie also eine vorbereitete Anweisung verwenden, müssen Sie die Typen der Variablen für mysqli_stmt_bind_param Funktion.

Und die Verwendung von mysqli_real_escape_string dient, wie der Name schon sagt, dazu, Sonderzeichen in einer Zeichenkette zu entschärfen, macht also keine ganzen Zahlen sicher. Der Zweck dieser Funktion ist es, das Aufbrechen von Zeichenketten in SQL-Anweisungen und die dadurch verursachten Schäden an der Datenbank zu verhindern. mysqli_real_escape_string ist eine nützliche Funktion, wenn sie richtig eingesetzt wird, insbesondere in Kombination mit sprintf .

Ejemplo:

$string = "x' OR name LIKE '%John%";
$integer = '5 OR id != 0';

$query = sprintf( "SELECT id, email, pass, name FROM members WHERE email ='%s' AND id = %d", $mysqli->real_escape_string($string), $integer);

echo $query;
// SELECT id, email, pass, name FROM members WHERE email ='x\' OR name LIKE \'%John%' AND id = 5

$integer = '99999999999999999999';
$query = sprintf("SELECT id, email, pass, name FROM members WHERE email ='%s' AND id = %d", $mysqli->real_escape_string($string), $integer);

echo $query;
// SELECT id, email, pass, name FROM members WHERE email ='x\' OR name LIKE \'%John%' AND id = 2147483647

3 Stimmen

Die Frage ist sehr allgemein gehalten. Einige großartige Antworten oben, aber die meisten schlagen Prepared Statements vor. MySQLi async unterstützt keine vorbereiteten Anweisungen, so dass die sprintf sieht aus wie eine große Option für diese Situation.

230voto

Nicolas Finelli Punkte 2112

Mit dieser PHP-Funktion mysql_escape_string() können Sie schnell eine gute Prävention erreichen.

Zum Beispiel:

SELECT * FROM users WHERE name = '".mysql_escape_string($name_from_html_form)."'

mysql_escape_string - Entfernt eine Zeichenkette zur Verwendung in einer mysql_query

Für mehr Prävention können Sie am Ende hinzufügen ...

wHERE 1=1   or  LIMIT 1

Schließlich erhalten Sie:

SELECT * FROM users WHERE name = '".mysql_escape_string($name_from_html_form)."' LIMIT 1

186voto

Apurv Nerlekar Punkte 2290

Die einfache Alternative zu diesem Problem könnte darin bestehen, dass in der Datenbank selbst entsprechende Berechtigungen vergeben werden. Beispiel: Wenn Sie eine MySQL-Datenbank verwenden, rufen Sie die Datenbank über das Terminal oder die mitgelieferte Benutzeroberfläche auf und folgen Sie einfach diesem Befehl:

 GRANT SELECT, INSERT, DELETE ON database TO username@'localhost' IDENTIFIED BY 'password';

Dadurch wird der Benutzer darauf beschränkt, nur die angegebenen Abfragen zu erhalten. Entfernen Sie die Löschberechtigung, so dass die Daten nie aus der von der PHP-Seite abgefeuerten Abfrage gelöscht werden. Die zweite Sache, die zu tun ist, ist, die Privilegien zu flushen, so dass die MySQL die Berechtigungen und Updates aktualisiert.

FLUSH PRIVILEGES; 

mehr Informationen über Spülen .

Um die aktuellen Berechtigungen des Benutzers anzuzeigen, führen Sie die folgende Abfrage durch.

select * from mysql.user where User='username';

Erfahren Sie mehr über GRANT .

27 Stimmen

Diese Antwort lautet grundsätzlich falsch Denn es hilft nicht, eine Injektionsprävention zu verhindern, sondern nur, die Folgen zu mildern. Vergeblich.

1 Stimmen

Richtig, es bietet keine Lösung, aber es zeigt, was man im Vorfeld tun kann, um Dinge zu vermeiden.

2 Stimmen

@Apurv Wenn es mein Ziel ist, private Informationen aus Ihrer Datenbank zu lesen, dann bedeutet die fehlende DELETE-Berechtigung nichts.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X