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?

323voto

Johannes Fahrenkrug Punkte 40264

Meiner Meinung nach ist der beste Weg, um SQL-Injection in Ihrer PHP-Anwendung (oder jeder anderen Webanwendung) zu verhindern, die Architektur Ihrer Anwendung zu berücksichtigen. Wenn der einzige Weg, sich vor SQL-Injection zu schützen, darin besteht, sich daran zu erinnern, eine spezielle Methode oder Funktion zu verwenden, die jedes Mal, wenn Sie mit der Datenbank kommunizieren, das Richtige tut, dann machen Sie es falsch. Auf diese Weise ist es nur eine Frage der Zeit, bis Sie an irgendeiner Stelle in Ihrem Code vergessen, Ihre Abfrage korrekt zu formatieren.

Die Übernahme des MVC-Musters und eines Frameworks wie CakePHP o CodeIgniter ist wahrscheinlich der richtige Weg: Gängige Aufgaben wie die Erstellung sicherer Datenbankabfragen wurden in solchen Frameworks gelöst und zentral implementiert. Sie helfen Ihnen, Ihre Webanwendung sinnvoll zu organisieren und lassen Sie mehr über das Laden und Speichern von Objekten nachdenken als über die sichere Erstellung einzelner SQL-Abfragen.

9 Stimmen

Ich denke, Ihr erster Absatz ist wichtig. Verstehen ist der Schlüssel. Außerdem arbeitet nicht jeder für ein Unternehmen. Für einen großen Teil der Menschen widersprechen Rahmenwerke tatsächlich der Idee von Verständnis . Sich mit den Grundlagen vertraut zu machen, wird vielleicht nicht geschätzt, wenn man unter Zeitdruck arbeitet, aber die Heimwerker da draußen machen sich gerne die Hände schmutzig. Framework-Entwickler sind nicht so privilegiert, dass alle anderen sich verbeugen und davon ausgehen müssen, dass sie nie Fehler machen. Die Macht, Entscheidungen zu treffen, ist immer noch wichtig. Wer kann schon sagen, dass mein Framework in Zukunft nicht ein anderes System verdrängen wird?

0 Stimmen

@AnthonyRutledge Sie haben völlig recht. Es ist sehr wichtig, dass verstehen. was vor sich geht und warum. Die Wahrscheinlichkeit, dass ein erprobtes und aktiv genutztes und entwickeltes Framework bereits auf viele Probleme gestoßen ist und diese gelöst und viele Sicherheitslücken geschlossen hat, ist jedoch ziemlich hoch. Es ist eine gute Idee, einen Blick in den Quellcode zu werfen, um ein Gefühl für die Qualität des Codes zu bekommen. Wenn es ein ungetestetes Chaos ist, ist es wahrscheinlich nicht sicher.

3 Stimmen

Hier. Und hier. Gute Argumente. Allerdings würden Sie zustimmen, dass viele Menschen studieren und lernen können, ein MVC-System zu übernehmen, aber nicht jeder kann es von Hand reproduzieren (Controller und Server). Man kann mit diesem Punkt zu weit gehen. Muss ich meine Mikrowelle verstehen, bevor ich meine Erdnussbutter-Pekannuss-Kekse aufwärme, die mir meine Freundin gemacht hat? ;-)

314voto

Manish Shrivastava Punkte 27921

Es gibt viele Möglichkeiten, SQL-Injections und andere SQL-Hacks zu verhindern. Sie können sie leicht im Internet finden (Google-Suche). Natürlich PDO ist eine der guten Lösungen. Aber ich möchte Ihnen einige gute Links zur Vorbeugung von SQL-Injection vorschlagen.

Was ist SQL-Injection und wie kann man sie verhindern?

PHP-Handbuch für SQL-Injection

_Microsoft-Erklärung zu SQL-Injection und Prävention in PHP_

Und einige andere wie Verhinderung von SQL-Injection mit MySQL und PHP .

Jetzt, Warum müssen Sie Ihre Abfrage vor SQL-Injection schützen?

Das möchte ich Ihnen mitteilen: Warum wir versuchen, SQL-Injektion zu verhindern, mit einem kurzen Beispiel unten:

Abfrage nach Übereinstimmung der Anmeldeauthentifizierung:

$query="select * from users where email='".$_POST['email']."' and password='".$_POST['password']."' ";

Wenn nun jemand (ein Hacker) die

$_POST['email']= admin@emali.com' OR '1=1

und Passwort alles....

Die Abfrage wird nur bis zu diesem Zeitpunkt in das System eingelesen:

$query="select * from users where email='admin@emali.com' OR '1=1';

Der andere Teil wird weggeworfen. Was wird also passieren? Ein nicht autorisierter Benutzer (Hacker) kann sich als Administrator anmelden, ohne sein Passwort zu kennen. Nun kann er/sie alles tun, was der Administrator/die E-Mail-Person tun kann. Sie sehen, es ist sehr gefährlich, wenn SQL-Injection nicht verhindert wird.

313voto

Nikhil Punkte 3590

Ich favorisiere gespeicherte Verfahren ( MySQL bietet seit Version 5.0 Unterstützung für gespeicherte Prozeduren. ) unter dem Gesichtspunkt der Sicherheit - die Vorteile sind -

  1. Die meisten Datenbanken (einschließlich MySQL ) ermöglichen es, den Benutzerzugriff auf die Ausführung von gespeicherten Prozeduren zu beschränken. Die fein abgestufte Sicherheitszugriffskontrolle ist nützlich, um Angriffe zur Eskalation von Privilegien zu verhindern. Dadurch wird verhindert, dass kompromittierte Anwendungen SQL direkt auf der Datenbank ausführen können.
  2. Sie abstrahieren die rohe SQL-Abfrage von der Anwendung, so dass weniger Informationen über die Datenbankstruktur für die Anwendung verfügbar sind. Dies erschwert es dem Benutzer, die zugrunde liegende Struktur der Datenbank zu verstehen und geeignete Angriffe zu entwerfen.
  3. Sie akzeptieren nur Parameter, so dass die Vorteile der parametrisierten Abfragen erhalten bleiben. Natürlich müssen Sie - IMO - Ihre Eingaben immer noch bereinigen, insbesondere wenn Sie dynamisches SQL innerhalb der gespeicherten Prozedur verwenden.

Die Nachteile sind -

  1. Sie (gespeicherte Verfahren) sind schwer zu pflegen und neigen dazu, sich sehr schnell zu vermehren. Das macht ihre Verwaltung zu einem Problem.
  2. Sie eignen sich nicht sehr gut für dynamische Abfragen - wenn sie so aufgebaut sind, dass sie dynamischen Code als Parameter akzeptieren, werden viele der Vorteile zunichte gemacht.

282voto

RDK Punkte 4523

Ich denke, wenn jemand PHP und MySQL oder einen anderen Datenbankserver verwenden möchte:

  1. Über das Lernen nachdenken PDO (PHP Data Objects) - es handelt sich um eine Datenbankzugriffsschicht, die eine einheitliche Methode für den Zugriff auf mehrere Datenbanken bietet.
  2. Über das Lernen nachdenken MySQLi
  3. Verwenden Sie native PHP-Funktionen wie: strip_tags , mysql_real_escape_string oder, falls die Variable numerisch ist, einfach (int)$foo . Lesen Sie mehr über den Typ von Variablen in PHP aquí . Wenn Sie Bibliotheken wie PDO oder MySQLi verwenden, benutzen Sie immer PDO::quote() y mysqli_real_escape_string() .

Beispiele für Bibliotheken:

---- PDO

----- Keine Platzhalter - reif für SQL-Injection! Das ist schlecht

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) values ($name, $addr, $city)");

----- Unbenannte Platzhalter

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) values (?, ?, ?);

----- Benannte Platzhalter

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) value (:name, :addr, :city)");

--- MySQLi

$request = $mysqliConnection->prepare('
       SELECT * FROM trainers
       WHERE name = ?
       AND email = ?
       AND last_login > ?');

    $query->bind_param('first_param', 'second_param', $mail, time() - 3600);
    $query->execute();

P.S. :

PDO gewinnt diesen Kampf mit Leichtigkeit. Mit Unterstützung für zwölf verschiedene Datenbanktreiber und benannte Parameter, können wir den Leistungseinbußen ignorieren und sich an seine API gewöhnen. Vom Standpunkt der Sicherheit sind beide sicher, solange der Entwickler sie so verwendet so verwendet, wie sie verwendet werden sollen

Aber während sowohl PDO als auch MySQLi recht schnell sind, leistet MySQLi unbedeutend schneller in Benchmarks - ~2,5% für nicht vorbereitete Anweisungen und ~6,5 % für vorbereitete Anweisungen.

Und bitte testen Sie jede Abfrage an Ihre Datenbank - das ist ein besserer Weg, um Injektionen zu verhindern.

1 Stimmen

Dass mysqli falsch ist. Der erste Parameter drückt die Datentypen aus.

270voto

devOp Punkte 3140

Wenn möglich, casten Sie die Typen Ihrer Parameter. Das funktioniert aber nur bei einfachen Typen wie int, bool und float.

$unsafe_variable = $_POST['user_id'];

$safe_variable = (int)$unsafe_variable ;

mysqli_query($conn, "INSERT INTO table (column) VALUES ('" . $safe_variable . "')");

3 Stimmen

Dies ist einer der wenigen Fälle, in denen ich einen "escaped value" anstelle einer vorbereiteten Anweisung verwenden würde. Und die Konvertierung von Integer-Typen ist extrem effizient.

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