Analyse des Prinzips der Verwendung von PDO zur Verhinderung von SQL-Injection

Analyse des Prinzips der Verwendung von PDO zur Verhinderung von SQL-Injection

Vorwort

Dieser Artikel verwendet die Vorverarbeitungsmethode von PDO, um SQL-Injection zu vermeiden. Werfen wir einen Blick auf die ausführliche Einführung.

Im PHP-Handbuch unter „PDO – Prepared Statements and Stored Procedures“:

  • Viele der ausgereifteren Datenbanken unterstützen das Konzept vorbereiteter Anweisungen. Was sind vorbereitete Anweisungen? Stellen Sie es sich als kompilierte Vorlage des SQL vor, das Sie ausführen möchten und das mit variablen Parametern angepasst werden kann. Vorbereitete Anweisungen bieten zwei wesentliche Vorteile:
  • Die Abfrage muss nur einmal analysiert (oder vorverarbeitet) werden, kann aber mehrmals mit denselben oder unterschiedlichen Parametern ausgeführt werden. Wenn eine Abfrage vorbereitet wird, analysiert, kompiliert und optimiert die Datenbank den Plan zur Ausführung der Abfrage. Bei komplexen Abfragen kann dieser Vorgang lange dauern und Ihre Anwendung erheblich verlangsamen, wenn die gleiche Abfrage mehrmals mit unterschiedlichen Parametern wiederholt werden muss. Durch die Verwendung vorbereiteter Anweisungen können Sie wiederholte Analyse-/Kompilierungs-/Optimierungszyklen vermeiden. Kurz gesagt: vorbereitete Anweisungen verbrauchen weniger Ressourcen und werden daher schneller ausgeführt.
  • An vorbereitete Anweisungen übergebene Parameter müssen nicht in Anführungszeichen gesetzt werden; der Treiber erledigt dies automatisch. Wenn Ihre Anwendung nur vorbereitete Anweisungen verwendet, können Sie sicherstellen, dass keine SQL-Injection erfolgen kann. (Es besteht jedoch weiterhin die Gefahr einer SQL-Injection, wenn andere Teile der Abfrage aus nicht maskierten Eingaben erstellt werden).
  • Vorbereitete Anweisungen sind so nützlich, dass ihre einzige Funktion darin besteht, dass PDO sie emuliert, wenn der Treiber sie nicht unterstützt. Dadurch wird sichergestellt, dass Anwendungen dieselben Datenzugriffsmuster verwenden können, unabhängig davon, ob die Datenbank über solche Funktionen verfügt.

Im Folgenden sind die beiden oben genannten Vorteile aufgeführt:

1. Lassen Sie uns zunächst über die gespeicherten Prozeduren von MySQL sprechen. MySQL5 führte die Funktion für gespeicherte Prozeduren ein. Als die gespeicherte Prozedur erstellt wurde, hatte die Datenbank sie bereits analysiert und optimiert. Zweitens wird nach der Ausführung einer gespeicherten Prozedur eine Kopie dieser gespeicherten Prozedur im Speicher aufbewahrt, sodass diese bei der nächsten Ausführung derselben gespeicherten Prozedur direkt aus dem Speicher gelesen werden kann. Informationen zur Verwendung gespeicherter MySQL-Prozeduren finden Sie unter: https://www.jb51.net/article/7032.htm

Für PDO ist das Prinzip dasselbe, außer dass PDO EMULATE_PREPARES (simulierte Vorverarbeitung) unterstützt, die lokal vom PDO-Treiber abgeschlossen wird. Gleichzeitig können Sie die lokale simulierte Vorverarbeitung auch nicht verwenden und sie von MySQL abschließen lassen. Diese beiden Situationen werden weiter unten erläutert.

2. Um SQL-Injection zu verhindern, habe ich tcpdump und wireshark verwendet, um das Paket zur Analyse zu erfassen.

Führen Sie einen Codeabschnitt auf der virtuellen Maschine aus, um eine Anfrage an das Remote-MySQL zu initiieren:

<?php

$pdo = neues PDO("mysql:host=10.121.95.81;dbname=thor_cms;charset=utf8", "root", "qihoo@360@qihoo");

$st = $pdo->prepare("Wählen Sie * aus der Freigabe aus, wobei ID =? und UID = ?");

$id = 6;
$uid = 521;

$st->bindParam(1, $id);
$st->bindParam(2, $uid);

$st->execute();
$ret = $st->fetchAll();

drucken_r($ret);

Generieren Sie Dateien, indem Sie Pakete über tcpdump erfassen:

tcpdump -ieth0 -A -s 3000 Port 3306 -w ./mysql.dump

sz mysql.dump

Öffnen Sie die Datei über Wireshark:

Sie können den gesamten Prozess sehen: 3-Wege-Handshake - Anmeldeanforderung - Anforderungsabfrage - Anforderung zum Beenden

Wenn Sie sich das Request Query-Paket ansehen, können Sie Folgendes sehen:

Hä? Ist das nicht auch eine Verkettung von SQL-Anweisungen?

Tatsächlich unterscheidet sich dies nicht von der Art und Weise, wie wir normalerweise mysql_real_escape_string verwenden, um die Zeichenfolge zu escapen und sie dann in SQL-Anweisungen zu verketten. Es ist nur so, dass der lokale PDO-Treiber das Escape abschließt (EMULATE_PREPARES).

In diesem Fall ist SQL-Injection immer noch möglich, d. h., wenn mysql_real_escape_string in pdo prepare lokal in PHP aufgerufen wird, um die Abfrage auszuführen, der lokale Einzelbyte-Zeichensatz verwendet wird und wenn wir mehrbytecodierte Variablen übergeben, können immer noch SQL-Injection-Schwachstellen auftreten (eines der Probleme in Versionen vor PHP 5.3.6, weshalb empfohlen wird, auf PHP 5.3.6+ zu aktualisieren und den Zeichensatz in der DSN-Zeichenfolge anzugeben, wenn PDO verwendet wird).

Bei Versionen vor PHP 5.3.6 kann der folgende Code immer noch SQL-Injection-Probleme verursachen:

$pdo->query('Namen festlegen GBK'); 

$var = chr(0xbf) . chr(0x27) . " ODER 1=1 /*"; 

$query = "AUSWÄHLEN * FROM info WHERE name = ?"; 

$stmt = $pdo->prepare($query); 

: $stmt->execute(array($var));

Das richtige Escape-Verfahren sollte darin bestehen, den Zeichensatz für den MySQL-Server anzugeben und die Variable an den MySQL-Server zu senden, um das Zeichen-Escape-Verfahren abzuschließen.

Wie können wir also das lokale PHP-Escapen deaktivieren und das Escapen dem MySQL-Server überlassen?

PDO hat einen Parameter namens PDO::ATTR_EMULATE_PREPARES, der angibt, ob die lokale simulierte Vorbereitung von PHP verwendet werden soll. Dieser Parameter ist standardmäßig auf „true“ eingestellt. Ändern wir ihn in „false“ und erfassen dann das Paket.

Fügen Sie nach der ersten Codezeile hinzu

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Verwenden Sie tcpdump, um das Paket erneut zu erfassen. Über Wireshark können wir Folgendes sehen:

PHP verwendet die Methode prepare--execute zum Senden von SQL-Anweisungen

Dieses Mal wird die Variablen-Escape-Verarbeitung vom MySQL-Server durchgeführt.

Da die Variablen und die SQL-Vorlage zweimal gesendet werden, gibt es kein SQL-Injection-Problem, aber es wird offensichtlich eine weitere Übertragung geben, die nach php5.3.6 nicht mehr erforderlich ist.

Hinweise zur Verwendung von PDO

1. Aktualisieren Sie PHP auf 5.3.6+. Für Produktionsumgebungen wird dringend empfohlen, auf PHP 5.3.9+ oder PHP 5.4+ zu aktualisieren. PHP 5.3.8 weist eine schwerwiegende Hash-Kollisions-Sicherheitslücke auf.

2. Wenn Sie PHP 5.3.6+ verwenden, geben Sie bitte das Zeichensatzattribut im PDO DSN an. Weniger als 5.3.6: $dbh = neues PDO($dsn,$user,$pass,array(PDO::MYSQL_ATTR_INIT_COMMAND => "set names utf8"));

3. Wenn Sie PHP 5.3.6 oder früher verwenden, setzen Sie den Parameter PDO::ATTR_EMULATE_PREPARES auf „false“ (das heißt, lassen Sie den MySQL-Server die Variablen handhaben). PHP 5.3.6 und spätere Versionen haben dieses Problem bereits behandelt, unabhängig davon, ob Sie lokal simuliertes Prepare verwenden oder Prepare des MySQL-Servers aufrufen.

4. Wenn Sie PHP 5.3.6 oder früher verwenden, geben Sie den Wert von emulatePrepare in der Datenbankkonfigurationsdatei bitte als „false“ an, da das Yii-Framework den Wert von ATTR_EMULATE_PREPARES nicht standardmäßig festlegt.

Notiz:

1. Warum muss ich Setnamen <charset> ausführen, wenn ich den Zeichensatz im DSN angebe?

Tatsächlich hat der Satz von Namen <charset> zwei Funktionen:

Teilen Sie dem MySQL-Server mit, welche Kodierung der Client (PHP-Programm) ihm übermittelt hat.

Teilen Sie dem MySQL-Server mit, welche Kodierung der Client für das Ergebnis benötigt

Das heißt, wenn die Datentabelle den GBK-Zeichensatz verwendet und das PHP-Programm die UTF-8-Kodierung nutzt, können wir vor der Ausführung der Abfrage „set names utf8“ ausführen, um dem MySQL-Server mitzuteilen, dass er die richtige Kodierung verwenden soll, ohne die Kodierung im Programm konvertieren zu müssen. Wenn wir auf diese Weise Abfragen in UTF-8-Kodierung an den MySQL-Server senden, liegen die Ergebnisse ebenfalls in UTF-8-Kodierung vor. Dadurch entfällt die Notwendigkeit von Konvertierungsproblemen im Programm. Seien Sie unbesorgt, es entstehen keine verstümmelten Zeichen.

Was ist also der Zweck der Angabe des Zeichensatzes in DSN? Es teilt PDO lediglich mit, dass der lokale Treiber beim Escapen den angegebenen Zeichensatz verwenden soll (es legt nicht den Zeichensatz für die MySQL-Serverkommunikation fest). Um den Zeichensatz für die MySQL-Serverkommunikation festzulegen, müssen Sie auch den Befehl set names <charset> verwenden.

2. Der Mord, der durch das Setzen des Attributs PDO::ATTR_EMULATE_PREPARES auf „false“ verursacht wurde: http://my.oschina.net/u/437615/blog/369481

Zusammenfassen

Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Lernwert für Ihr Studium oder Ihre Arbeit hat. Wenn Sie Fragen haben, können Sie eine Nachricht hinterlassen. Vielen Dank für Ihre Unterstützung von 123WORDPRESS.COM.

Das könnte Sie auch interessieren:
  • So vermeiden Sie SQL-Injection-Risiken durch die Verwendung von PDO zum Abfragen von MySQL in PHP
  • Detaillierte Erklärung der PDO-Verwendung in PHP für MySQL-Verbindungen
  • So verwenden Sie PHP zum Herstellen einer Verbindung und Abfragen einer SQL-Datenbank mithilfe von PDO
  • PHP implementiert die MySQL-Datenbank-Operationsklasse von PDO
  • Verwenden von parametrisiertem Abfrage-SQL in PDO
  • PHP implementiert eine leistungsstarke MySQL-Kapselungsklasseninstanz basierend auf PDO
  • Analyse, wie PHP PDO zum Ausführen von SQL-Anweisungen verwendet

<<:  Implementierungsmethode für den Apache AB-Stresstest zur gleichzeitigen Belastung

>>:  Docker Swarm von der Bereitstellung bis zum grundlegenden Betrieb

Artikel empfehlen

border-radius-Methode zum Hinzufügen abgerundeter Ränder zu Elementen

border-radius:10px; /* Alle Ecken sind mit einem ...

Ein kurzer Überblick über CSS3-Pseudoklassenselektoren

Vorwort Wenn CSS die Grundfertigkeit der Front-En...

So löschen Sie Ordner, Dateien und Dekomprimierungsbefehle auf Linux-Servern

1. Ordner löschen Beispiel: rm -rf /usr/java Das ...

Bringen Sie Ihnen kostenlos bei, wie Sie AWS-Serverressourcen nutzen

AWS – Amazons Cloud-Computing-Serviceplattform Ic...

So konfigurieren Sie die CDN-Planung mit dem Modul Nginx_geo

Einführung in das Geo-Modul von Nginx Die Geo-Dir...

So analysieren Sie den SQL-Ausführungsplan in MySQL mit EXPLAIN

Vorwort In MySQL können wir den Befehl EXPLAIN ve...

Implementierungsbeispiel eines Videoplayers basierend auf Vue

Wenn der vorhandene Videoplayer die Anforderungen...

Probleme bei der Ausführungsreihenfolge von AND und OR in SQL-Anweisungen

Frage Beim Schreiben von Datenbank-SQL ist mir ge...

JavaScript zum Implementieren eines Dropdown-Listenauswahlfelds

In diesem Artikelbeispiel wird der spezifische Ja...

So verwenden Sie Dayjs zum Berechnen gängiger Daten in Vue

Bei der Verwendung von Vue zur Entwicklung von Pr...

So installieren Sie Nginx in CentOS7 und konfigurieren den automatischen Start

1. Laden Sie das Installationspaket von der offiz...

So entwickeln Sie Java 8 Spring Boot-Anwendungen in Docker

In diesem Artikel zeige ich Ihnen, wie Sie mit Ja...

Details zu Makrotasks und Mikrotasks in JavaScript

Inhaltsverzeichnis 1. Was sind Mikroaufgaben? 2. ...

Allgemeines Startskriptbeispiel für ein Linux-Java-Programm

Allerdings ist die Häufigkeit des Shell-Starts se...