Heim  >  Artikel  >  Backend-Entwicklung  >  So verhindern Sie die SQL-Injection in PHP

So verhindern Sie die SQL-Injection in PHP

伊谢尔伦
伊谢尔伦Original
2016-11-24 14:35:571290Durchsuche

Problembeschreibung:
Wenn die vom Benutzer eingegebenen Daten ohne Verarbeitung in eine SQL-Abfrageanweisung eingefügt werden, ist die Anwendung wahrscheinlich SQL-Injection-Angriffen ausgesetzt, wie im folgenden Beispiel:

$unsafe_variable = $_POST['user_input'];

mysql_query("INSERT INTO `table` (`column`) VALUES ('" . $unsafe_variable . "')");
Weil die Eingabe des Benutzers so aussehen könnte:

value'); DROP TABLE table;--
Dann sieht die SQL-Abfrage wie folgt aus:

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

Welche wirksamen Methoden sollten angewendet werden, um SQL-Injection zu verhindern?

Beste Antwort (von Theo):
Verwenden Sie vorbereitete Anweisungen und parametrisierte Abfragen. Die vorbereiteten Anweisungen und Parameter werden jeweils zum Parsen an den Datenbankserver gesendet und die Parameter werden als normale Zeichen behandelt. Dieser Ansatz verhindert, dass Angreifer bösartiges SQL einschleusen. Sie haben zwei Möglichkeiten, diese Methode zu implementieren:

1. Verwenden Sie PDO:

$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');  
   
$stmt->execute(array('name' => $name));  
   
foreach ($stmt as $row) {  
    // do something with $row  
}

2. Verwenden Sie mysqli:

$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');  
$stmt->bind_param('s', $name);  
   
$stmt->execute();  
   
$result = $stmt->get_result();  
while ($row = $result->fetch_assoc()) {  
    // do something with $row  
}


Beachten Sie, dass die standardmäßige Verwendung von PDO es der MySQL-Datenbank nicht ermöglicht, echte vorbereitete Anweisungen auszuführen (Gründe siehe unten). Um dieses Problem zu lösen, sollten Sie die PDO-Emulation vorbereiteter Anweisungen deaktivieren. Ein Beispiel für die korrekte Verwendung von PDO zum Erstellen einer Datenbankverbindung ist wie folgt:

$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass');  
   
$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);  
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Im obigen Beispiel ist der Fehlerberichtsmodus (ATTR_ERRMODE) nicht erforderlich, es wird jedoch empfohlen, ihn hinzuzufügen . Auf diese Weise stoppt das Skript beim Auftreten eines schwerwiegenden Fehlers (Fatal Error) nicht die Ausführung, sondern gibt dem Programmierer die Möglichkeit, PDOExceptions abzufangen, damit der Fehler ordnungsgemäß behandelt werden kann. Allerdings ist der erste setAttribute()-Aufruf erforderlich, der PDO daran hindert, vorbereitete Anweisungen zu simulieren und echte vorbereitete Anweisungen verwendet, d. h. MySQL führt vorbereitete Anweisungen aus. Dadurch wird sichergestellt, dass Anweisungen und Parameter nicht von PHP verarbeitet wurden, bevor sie an MySQL gesendet wurden, wodurch Angreifer daran gehindert werden, bösartiges SQL einzuschleusen. Um den Grund zu verstehen, lesen Sie bitte diesen Blogbeitrag: Analyse des PDO-Anti-Injektionsprinzips und Vorsichtsmaßnahmen für die Verwendung von PDO. Beachten Sie, dass Sie in älteren PHP-Versionen (
Analyse
Was passiert, wenn Sie eine SQL-Anweisung zur Vorverarbeitung und Analyse an den Datenbankserver senden? Teilen Sie der Datenbank-Engine mit, wo Sie filtern möchten, indem Sie einen Platzhalter angeben (ein ? oder einen :name wie im Beispiel oben). Wenn Sie „execute“ aufrufen, wird die vorbereitete Anweisung mit den von Ihnen angegebenen Parameterwerten kombiniert. Der entscheidende Punkt liegt hier: Der Parameterwert wird mit der analysierten SQL-Anweisung kombiniert, nicht mit der SQL-Zeichenfolge. Die SQL-Injection wird durch Skripte ausgelöst, die beim Erstellen von SQL-Anweisungen schädliche Zeichenfolgen enthalten. Durch die Trennung von SQL-Anweisungen und Parametern verhindern Sie also das Risiko einer SQL-Injection. Alle von Ihnen gesendeten Parameterwerte werden als normale Zeichenfolgen behandelt und vom Datenbankserver nicht analysiert. Um auf das obige Beispiel zurückzukommen: Wenn der Wert der Variablen „$name“ „Sarah“ ist; Ein weiterer Vorteil der Verwendung vorbereiteter Anweisungen besteht darin, dass, wenn Sie dieselbe Anweisung mehrmals in derselben Datenbankverbindungssitzung ausführen, sie nur einmal analysiert wird, was die Ausführungsgeschwindigkeit etwas verbessern kann. Wenn Sie fragen möchten, wie das Einfügen erfolgt, schauen Sie sich bitte das folgende Beispiel an (mit PDO):

$preparedStatement = $db->prepare('INSERT INTO table (column) VALUES (:column)');  
   
$preparedStatement->execute(array('column' => $unsafeValue));


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn