Reichen PDO-vorbereitete Anweisungen aus, um eine SQL-Injection zu verhindern?

661

Angenommen, ich habe folgenden Code:

$dbh = new PDO("blahblah");

$stmt = $dbh->prepare('SELECT * FROM users where username = :username');
$stmt->execute( array(':username' => $_REQUEST['username']) );

In der PDO-Dokumentation heißt es:

Die Parameter für vorbereitete Anweisungen müssen nicht in Anführungszeichen gesetzt werden. Der Fahrer erledigt das für Sie.

Ist das wirklich alles, was ich tun muss, um SQL-Injektionen zu vermeiden? Ist es wirklich so einfach?

Sie können MySQL annehmen, wenn es einen Unterschied macht. Außerdem bin ich wirklich nur neugierig auf die Verwendung vorbereiteter Anweisungen gegen SQL-Injection. In diesem Zusammenhang interessieren mich XSS oder andere mögliche Schwachstellen nicht.

Mark Biek
quelle
5
Besserer Ansatz 7. Nummer Antwort stackoverflow.com/questions/134099/…
NullPoiиteя

Antworten:

806

Die kurze Antwort lautet NEIN . PDO-Vorbereitungen schützen Sie nicht vor allen möglichen SQL-Injection-Angriffen. Für bestimmte dunkle Randfälle.

Ich passe diese Antwort an, um über PDO zu sprechen ...

Die lange Antwort ist nicht so einfach. Es basiert auf einem hier demonstrierten Angriff .

Der Angriff

Beginnen wir also damit, den Angriff zu zeigen ...

$pdo->query('SET NAMES gbk');
$var = "\xbf\x27 OR 1=1 /*";
$query = 'SELECT * FROM test WHERE name = ? LIMIT 1';
$stmt = $pdo->prepare($query);
$stmt->execute(array($var));

Unter bestimmten Umständen wird mehr als eine Zeile zurückgegeben. Lassen Sie uns analysieren, was hier los ist:

  1. Auswählen eines Zeichensatzes

    $pdo->query('SET NAMES gbk');

    Für diesen Angriff zu arbeiten, müssen wir die Codierung , dass der Server die auf der Verbindung erwartet sowohl codieren 'als in ASCII dh 0x27 und einige Zeichen zu haben , deren letzte Byte ist ein ASCII \dh 0x5c. Wie sich herausstellt, gibt es 5 solche Codierungen in MySQL 5.6 standardmäßig unterstützt: big5, cp932, gb2312, gbkund sjis. Wir werden gbkhier auswählen .

    Nun ist es sehr wichtig, die Verwendung von SET NAMEShier zu beachten . Dies setzt den Zeichensatz auf dem Server . Es gibt noch einen anderen Weg, aber wir werden früh genug dort sein.

  2. Die Nutzlast

    Die Nutzlast, die wir für diese Injektion verwenden werden, beginnt mit der Bytesequenz 0xbf27. In gbkist das ein ungültiges Multibyte-Zeichen. in latin1, es ist die Zeichenfolge ¿'. Beachten Sie, dass in latin1 und gbk , 0x27auf seinem eigenen ein wörtlicher ist 'Charakter.

    Wir haben diese Nutzlast gewählt , weil, wenn wir aufgerufen addslashes()darauf, würden wir eine ASCII einfügen \dh 0x5c, vor dem 'Charakter. Also haben wir mit aufzuwickeln würde 0xbf5c27, die in gbkeine zwei Zeichenfolge: 0xbf5cgefolgt von 0x27. Oder mit anderen Worten, ein gültiges Zeichen, gefolgt von einem nicht entflohenen '. Aber wir benutzen nicht addslashes(). Also weiter zum nächsten Schritt ...

  3. $ stmt-> execute ()

    Das Wichtigste dabei ist, dass PDO standardmäßig KEINE wirklich vorbereiteten Anweisungen ausführt. Es emuliert sie (für MySQL). Daher erstellt PDO intern die Abfragezeichenfolge und ruft mysql_real_escape_string()(die MySQL C-API-Funktion) für jeden gebundenen Zeichenfolgenwert auf.

    Der C-API-Aufruf von mysql_real_escape_string()unterscheidet sich addslashes()darin, dass er den Verbindungszeichensatz kennt. So kann die Escape-Anweisung für den vom Server erwarteten Zeichensatz ordnungsgemäß ausgeführt werden. Bis zu diesem Punkt glaubt der Client jedoch, dass wir immer noch latin1für die Verbindung verwenden, da wir es nie anders gesagt haben. Wir haben dem Server mitgeteilt gbk, dass wir ihn verwenden , aber der Client glaubt immer noch, dass dies der Fall ist latin1.

    Daher der Aufruf, mysql_real_escape_string()den Backslash einzufügen, und wir haben einen frei hängenden 'Charakter in unserem "entkommenen" Inhalt! Wenn wir uns $varden gbkZeichensatz ansehen würden, würden wir tatsächlich sehen:

    縗 'OR 1 = 1 / *

    Welches ist genau das, was der Angriff erfordert.

  4. Die Abfrage

    Dieser Teil ist nur eine Formalität, aber hier ist die gerenderte Abfrage:

    SELECT * FROM test WHERE name = '縗' OR 1=1 /*' LIMIT 1

Herzlichen Glückwunsch, Sie haben gerade ein Programm mit PDO Prepared Statements erfolgreich angegriffen ...

Die einfache Lösung

Nun ist es erwähnenswert, dass Sie dies verhindern können, indem Sie emulierte vorbereitete Anweisungen deaktivieren:

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

Dies führt normalerweise zu einer wirklich vorbereiteten Anweisung (dh die Daten werden in einem von der Abfrage getrennten Paket gesendet). Beachten Sie jedoch, dass PDO leise Rückfall auf Anweisungen emuliert , dass MySQL nicht nativ vorbereiten können: diejenigen , die es können , sind aufgelistet in dem Handbuch, aber passen Sie den entsprechenden Server - Version wählen).

Die richtige Lösung

Das Problem hierbei ist, dass wir nicht die C-APIs mysql_set_charset()anstelle von aufgerufen haben SET NAMES. In diesem Fall wäre alles in Ordnung, vorausgesetzt, wir verwenden seit 2006 eine MySQL-Version.

Wenn Sie eine frühere MySQL - Release verwenden, dann einen Fehler in mysql_real_escape_string()gemeint , dass ungültige Mehrbytezeichen wie die in unserer Nutzlast als einzelnes Bytes behandelt wurden , für die Zwecke entkommen , auch wenn der Kunde hat richtig die Verbindung Codierung informiert worden und so dieser Angriff würde immer noch erfolgreich. Der Fehler wurde in MySQL 4.1.20 , 5.0.22 und 5.1.11 behoben .

Das Schlimmste ist PDOjedoch, dass die C-API mysql_set_charset()erst in Version 5.3.6 verfügbar gemacht wurde. In früheren Versionen kann sie diesen Angriff nicht für jeden möglichen Befehl verhindern! Es wird jetzt als DSN-Parameter angezeigt , der anstelle von SET NAMES ...

Die rettende Gnade

Wie eingangs erwähnt, muss die Datenbankverbindung mit einem anfälligen Zeichensatz codiert werden, damit dieser Angriff funktioniert. utf8mb4ist nicht anfällig und kann dennoch jedes Unicode-Zeichen unterstützen. Sie können sich also dafür entscheiden, dieses zu verwenden. Es ist jedoch erst seit MySQL 5.5.3 verfügbar. Eine Alternative ist utf8, die ebenfalls nicht anfällig ist und die gesamte mehrsprachige Unicode- Grundebene unterstützen kann .

Alternativ können Sie den NO_BACKSLASH_ESCAPESSQL-Modus aktivieren , der (unter anderem) den Betrieb von ändert mysql_real_escape_string(). Wenn dieser Modus aktiviert ist, 0x27wird er durch 0x2727und nicht ersetzt, 0x5c27und daher kann der Escape-Prozess keine gültigen Zeichen in einer der anfälligen Codierungen erstellen, in denen sie zuvor nicht vorhanden waren (dh 0xbf27immer noch 0xbf27usw.). Daher lehnt der Server die Zeichenfolge weiterhin als ungültig ab . In der Antwort von @ eggyal finden Sie jedoch eine andere Sicherheitsanfälligkeit, die sich aus der Verwendung dieses SQL-Modus ergeben kann (allerdings nicht mit PDO).

Sichere Beispiele

Die folgenden Beispiele sind sicher:

mysql_query('SET NAMES utf8');
$var = mysql_real_escape_string("\xbf\x27 OR 1=1 /*");
mysql_query("SELECT * FROM test WHERE name = '$var' LIMIT 1");

Weil der Server erwartet utf8...

mysql_set_charset('gbk');
$var = mysql_real_escape_string("\xbf\x27 OR 1=1 /*");
mysql_query("SELECT * FROM test WHERE name = '$var' LIMIT 1");

Weil wir den Zeichensatz richtig eingestellt haben, damit Client und Server übereinstimmen.

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query('SET NAMES gbk');
$stmt = $pdo->prepare('SELECT * FROM test WHERE name = ? LIMIT 1');
$stmt->execute(array("\xbf\x27 OR 1=1 /*"));

Weil wir emulierte vorbereitete Anweisungen deaktiviert haben.

$pdo = new PDO('mysql:host=localhost;dbname=testdb;charset=gbk', $user, $password);
$stmt = $pdo->prepare('SELECT * FROM test WHERE name = ? LIMIT 1');
$stmt->execute(array("\xbf\x27 OR 1=1 /*"));

Weil wir den Zeichensatz richtig eingestellt haben.

$mysqli->query('SET NAMES gbk');
$stmt = $mysqli->prepare('SELECT * FROM test WHERE name = ? LIMIT 1');
$param = "\xbf\x27 OR 1=1 /*";
$stmt->bind_param('s', $param);
$stmt->execute();

Weil MySQLi ständig wirklich vorbereitete Anweisungen ausführt.

Einpacken

Wenn du:

  • Verwenden Sie moderne Versionen von MySQL (Ende 5.1, alle 5.5, 5.6 usw.) UND den DSN-Zeichensatzparameter von PDO (in PHP ≥ 5.3.6).

ODER

  • Verwenden Sie keinen anfälligen Zeichensatz für die Verbindungscodierung (Sie verwenden nur utf8/ latin1/ ascii/ etc).

ODER

  • Aktivieren Sie den NO_BACKSLASH_ESCAPESSQL-Modus

Du bist 100% sicher.

Andernfalls sind Sie anfällig , obwohl Sie PDO Prepared Statements verwenden ...

Nachtrag

Ich habe langsam an einem Patch gearbeitet, um die Standardeinstellung so zu ändern, dass keine Vorbereitungen für eine zukünftige Version von PHP emuliert werden. Das Problem, auf das ich stoße, ist, dass viele Tests dabei unterbrochen werden. Ein Problem ist, dass emulierte Vorbereitungen nur Syntaxfehler bei der Ausführung auslösen, echte Vorbereitungen jedoch Fehler bei der Vorbereitung. Das kann also Probleme verursachen (und ist Teil des Grundes, warum Tests nicht funktionieren).

ircmaxell
quelle
47
Dies ist die beste Antwort, die ich gefunden habe. Können Sie einen Link für weitere Informationen bereitstellen?
StaticVariable
1
@nicogawenda: das war ein anderer Fehler. Vor 5.0.22 wurden mysql_real_escape_stringFälle, in denen die Verbindung ordnungsgemäß auf BIG5 / GBK eingestellt war, nicht ordnungsgemäß behandelt. Selbst das Aufrufen mysql_set_charset()von MySQL <5.0.22 wäre für diesen Fehler anfällig! Also nein, dieser Beitrag gilt weiterhin für 5.0.22 (da mysql_real_escape_string nur für Anrufe von Zeichensätzen entfernt mysql_set_charset()ist, worüber in diesem Beitrag die Umgehung gesprochen wird) ...
ircmaxell
1
@progfa Ob dies der Fall ist oder nicht, Sie sollten Ihre Eingabe auf dem Server immer überprüfen, bevor Sie etwas mit Benutzerdaten tun.
Tek
2
Bitte beachten Sie, dass NO_BACKSLASH_ESCAPESdies auch zu neuen Sicherheitslücken führen kann: stackoverflow.com/a/23277864/1014813
lepix
2
@slevin das "OR 1 = 1" ist ein Platzhalter für alles, was Sie wollen. Ja, es wird nach einem Wert im Namen gesucht, aber stellen Sie sich vor, der Teil "OR 1 = 1" war "UNION SELECT * FROM users". Sie steuern jetzt die Abfrage und können sie als solche missbrauchen ...
ircmaxell
515

Vorbereitete Anweisungen / parametrisierte Abfragen reichen im Allgemeinen aus, um eine Injektion 1. Ordnung in diese Anweisung * zu verhindern . Wenn Sie an anderer Stelle in Ihrer Anwendung ungeprüftes dynamisches SQL verwenden, sind Sie immer noch anfällig für Injektionen 2. Ordnung .

Injektion 2. Ordnung bedeutet, dass Daten einmal durch die Datenbank geleitet wurden, bevor sie in eine Abfrage aufgenommen wurden, und dass es viel schwieriger ist, sie abzurufen. AFAIK, Sie sehen fast nie echte technische Angriffe 2. Ordnung, da es für Angreifer normalerweise einfacher ist, sich als Social-Engineer einzumischen, aber manchmal treten Fehler 2. Ordnung aufgrund besonders harmloser 'Charaktere oder Ähnlichem auf.

Sie können einen Injektionsangriff 2. Ordnung ausführen, wenn Sie veranlassen können, dass ein Wert in einer Datenbank gespeichert wird, die später als Literal in einer Abfrage verwendet wird. Angenommen, Sie geben beim Erstellen eines Kontos auf einer Website die folgenden Informationen als neuen Benutzernamen ein (vorausgesetzt, MySQL DB für diese Frage):

' + (SELECT UserName + '_' + Password FROM Users LIMIT 1) + '

Wenn es keine weiteren Einschränkungen für den Benutzernamen gibt, würde eine vorbereitete Anweisung dennoch sicherstellen, dass die oben eingebettete Abfrage zum Zeitpunkt des Einfügens nicht ausgeführt wird, und den Wert korrekt in der Datenbank speichern. Stellen Sie sich jedoch vor, dass die Anwendung später Ihren Benutzernamen aus der Datenbank abruft und die Zeichenfolgenverkettung verwendet, um diesen Wert in eine neue Abfrage aufzunehmen. Möglicherweise sehen Sie das Passwort einer anderen Person. Da die ersten Namen in der Benutzertabelle in der Regel Administratoren sind, haben Sie möglicherweise auch gerade die Farm verschenkt. (Beachten Sie auch: Dies ist ein weiterer Grund, Passwörter nicht im Klartext zu speichern!)

Wir sehen also, dass vorbereitete Anweisungen für eine einzelne Abfrage ausreichen , aber allein nicht ausreichen, um sich vor SQL-Injection-Angriffen in einer gesamten Anwendung zu schützen, da ihnen ein Mechanismus fehlt, um den gesamten Zugriff auf eine Datenbank innerhalb einer Anwendung zu erzwingen, die sicher verwendet wird Code. Jedoch im Rahmen eines ordnungsgemäßen Anwendung Design verwendet - die Praktiken wie Code - Review oder statische Analyse oder Verwendung eines ORM, Datenschicht oder Dienstschicht umfassen kann , dass Grenzen dynamische SQL - Prepared Statements sind das wichtigste Werkzeug für die Lösung der SQL - Injection Problem.Wenn Sie gute Prinzipien für das Anwendungsdesign befolgen, sodass Ihr Datenzugriff vom Rest Ihres Programms getrennt ist, können Sie leicht erzwingen oder prüfen, ob jede Abfrage die Parametrisierung korrekt verwendet. In diesem Fall wird die SQL-Injektion (sowohl erster als auch zweiter Ordnung) vollständig verhindert.


* Es stellt sich heraus, dass MySql / PHP (okay, waren) nur dumm im Umgang mit Parametern sind, wenn breite Zeichen beteiligt sind, und es gibt immer noch einen seltenen Fall, der in der anderen hoch bewerteten Antwort hier umrissen ist , der es ermöglichen kann, dass die Injektion durch einen parametrisierten Parameter rutscht Abfrage.

Joel Coehoorn
quelle
6
Das ist interessant. Mir war die 1. Ordnung gegenüber der 2. Ordnung nicht bekannt. Können Sie etwas näher erläutern, wie die 2. Ordnung funktioniert?
Mark Biek
193
Wenn ALLE Ihre Abfragen parametrisiert sind, sind Sie auch gegen Injektionen 2. Ordnung geschützt. Bei der Injektion 1. Ordnung wird vergessen, dass Benutzerdaten nicht vertrauenswürdig sind. Bei der Injektion 2. Ordnung wird vergessen, dass Datenbankdaten nicht vertrauenswürdig sind (da sie ursprünglich vom Benutzer stammen).
cjm
6
Danke cjm. Ich fand diesen Artikel auch hilfreich bei der Erklärung von Injektionen 2. Ordnung: codeproject.com/KB/database/SqlInjectionAttacks.aspx
Mark Biek
49
Ah ja. Aber was ist dritter Ordnung Injektion . Muss sich dessen bewusst sein.
Troelskn
81
@troelskn das muss sein, wo der Entwickler die Quelle von nicht vertrauenswürdigen Daten ist
MikeMurko
45

Nein, das sind sie nicht immer.

Dies hängt davon ab, ob Sie zulassen, dass Benutzereingaben in die Abfrage selbst eingefügt werden. Zum Beispiel:

$dbh = new PDO("blahblah");

$tableToUse = $_GET['userTable'];

$stmt = $dbh->prepare('SELECT * FROM ' . $tableToUse . ' where username = :username');
$stmt->execute( array(':username' => $_REQUEST['username']) );

wäre anfällig für SQL-Injektionen und die Verwendung vorbereiteter Anweisungen in diesem Beispiel funktioniert nicht, da die Benutzereingabe als Bezeichner und nicht als Daten verwendet wird. Die richtige Antwort wäre hier eine Art Filterung / Validierung wie:

$dbh = new PDO("blahblah");

$tableToUse = $_GET['userTable'];
$allowedTables = array('users','admins','moderators');
if (!in_array($tableToUse,$allowedTables))    
 $tableToUse = 'users';

$stmt = $dbh->prepare('SELECT * FROM ' . $tableToUse . ' where username = :username');
$stmt->execute( array(':username' => $_REQUEST['username']) );

Hinweis: Sie können PDO nicht zum Binden von Daten verwenden, die außerhalb von DDL (Data Definition Language) liegen. Dies funktioniert also nicht:

$stmt = $dbh->prepare('SELECT * FROM foo ORDER BY :userSuppliedData');

Der Grund, warum das oben genannte nicht funktioniert, ist, weil DESCund ASCsind keine Daten . PDO kann nur für Daten entkommen . Zweitens können Sie nicht einmal 'Anführungszeichen setzen . Die einzige Möglichkeit, die vom Benutzer gewählte Sortierung zuzulassen, besteht darin, manuell zu filtern und zu überprüfen, ob dies entweder DESCoder der Fall ist ASC.

Turm
quelle
11
Vermisse ich hier etwas, aber geht es nicht um vorbereitete Anweisungen, um zu vermeiden, dass SQL wie eine Zeichenfolge behandelt wird? Würde nicht so etwas wie $ dbh-> vorbereiten ('SELECT * FROM: tableToUse where username =: username'); um dein Problem herumkommen?
Rob Forrest
4
@ RobForrest ja du vermisst :). Die Daten, die Sie binden, funktionieren nur für DDL (Data Definition Language). Sie brauchen diese Zitate und die richtige Flucht. Wenn Sie Anführungszeichen für andere Teile der Abfrage setzen, wird diese mit hoher Wahrscheinlichkeit unterbrochen. SELECT * FROM 'table'Kann zum Beispiel falsch sein, wie es sein sollte SELECT * FROM `table`oder ohne Backsticks. Dann können einige Dinge wie, ORDER BY DESCwoher DESCder Benutzer kommt, nicht einfach entkommen. Praktische Szenarien sind also eher unbegrenzt.
Turm
8
Ich frage mich, wie 6 Personen einen Kommentar positiv bewerten könnten, der eine eindeutig falsche Verwendung einer vorbereiteten Aussage vorschlägt. Hätten sie es einmal versucht, hätten sie sofort festgestellt, dass die Verwendung eines benannten Parameters anstelle eines Tabellennamens nicht funktioniert.
Félix Gagnon-Grenier
Hier ist ein großartiges Tutorial zu PDO, wenn Sie es lernen möchten. a2znotes.blogspot.in/2014/09/introduction-to-pdo.html
RN Kushwaha
11
Sie sollten niemals eine Abfragezeichenfolge / einen POST-Body verwenden, um die zu verwendende Tabelle auszuwählen. Wenn Sie keine Modelle haben, verwenden Sie mindestens a switch, um den Tabellennamen abzuleiten.
ZiggyTheHamster
29

Ja, das reicht aus. Die Art und Weise, wie Injection-Angriffe funktionieren, besteht darin, dass ein Interpreter (die Datenbank) etwas auswertet, das Daten sein sollte, als wäre es Code. Dies ist nur möglich, wenn Sie Code und Daten auf demselben Medium mischen (z. B. wenn Sie eine Abfrage als Zeichenfolge erstellen).

Parametrisierte Abfragen funktionieren, indem der Code und die Daten separat gesendet werden, sodass es niemals möglich wäre, eine Lücke darin zu finden.

Sie können jedoch weiterhin anfällig für andere Angriffe vom Typ Injektion sein. Wenn Sie beispielsweise die Daten in einer HTML-Seite verwenden, können Sie Angriffen vom Typ XSS ausgesetzt sein.

troelskn
quelle
10
"Niemals" ist weit übertrieben, bis es irreführend ist. Wenn Sie vorbereitete Anweisungen falsch verwenden, ist es nicht viel besser, als sie überhaupt nicht zu verwenden. (Natürlich macht eine "vorbereitete Anweisung", in die Benutzereingaben eingefügt wurden, den Zweck zunichte ... aber ich habe es tatsächlich gesehen. Und vorbereitete Anweisungen können Bezeichner (Tabellennamen usw.) nicht als Parameter verarbeiten.) Hinzufügen Dazu emulieren einige der PDO-Treiber vorbereitete Anweisungen, und es gibt Raum für sie, dies falsch zu tun (z. B. durch halbherziges Parsen der SQL). Kurzfassung: Niemals davon ausgehen, dass es so einfach ist.
CHao
29

Nein, das reicht nicht (in bestimmten Fällen)! Standardmäßig verwendet PDO emulierte vorbereitete Anweisungen, wenn MySQL als Datenbanktreiber verwendet wird. Sie sollten emulierte vorbereitete Anweisungen immer deaktivieren, wenn Sie MySQL und PDO verwenden:

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

Eine andere Sache, die immer getan werden sollte, stellte die korrekte Codierung der Datenbank ein:

$dbh = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass');

Siehe auch diese verwandte Frage: Wie kann ich die SQL-Injection in PHP verhindern?

Beachten Sie auch, dass es nur um die Datenbankseite der Dinge geht, die Sie beim Anzeigen der Daten noch selbst beobachten müssten. ZB durch erneutes Verwenden htmlspecialchars()mit dem richtigen Codierungs- und Zitierstil.

PeeHaa
quelle
14

Persönlich würde ich immer zuerst eine Form der Bereinigung der Daten durchführen, da Sie Benutzereingaben niemals vertrauen können. Wenn Sie jedoch Platzhalter / Parameterbindungen verwenden, werden die eingegebenen Daten separat an die SQL-Anweisung an den Server gesendet und dann zusammengebunden. Der Schlüssel hier ist, dass dies die bereitgestellten Daten an einen bestimmten Typ und eine bestimmte Verwendung bindet und jede Möglichkeit ausschließt, die Logik der SQL-Anweisung zu ändern.

JimmyJ
quelle
1

Eaven, wenn Sie das Front-End der SQL-Injektion mithilfe von HTML- oder JS-Prüfungen verhindern möchten, müssen Sie berücksichtigen, dass Front-End-Prüfungen "umgehbar" sind.

Sie können js deaktivieren oder ein Muster mit einem Front-End-Entwicklungstool bearbeiten (das heutzutage mit Firefox oder Chrome integriert ist).

Um eine SQL-Injection zu verhindern, ist es daher richtig, das Backend für das Eingabedatum in Ihrem Controller zu bereinigen.

Ich möchte Ihnen vorschlagen, die native PHP-Funktion filter_input () zu verwenden, um GET- und INPUT-Werte zu bereinigen.

Wenn Sie bei vernünftigen Datenbankabfragen mit der Sicherheit fortfahren möchten, möchte ich Ihnen empfehlen, reguläre Ausdrücke zur Überprüfung des Datenformats zu verwenden. preg_match () hilft dir in diesem Fall! Aber pass auf dich auf! Regex Motor ist nicht so leicht. Verwenden Sie es nur bei Bedarf, da sonst die Anwendungsleistung abnimmt.

Sicherheit hat Kosten, aber verschwenden Sie nicht Ihre Leistung!

Einfaches Beispiel:

Wenn Sie überprüfen möchten, ob ein von GET empfangener Wert eine Zahl ist, weniger als 99, wenn (! preg_match ('/ [0-9] {1,2} /')) {...} schwerer ist

if (isset($value) && intval($value)) <99) {...}

Die endgültige Antwort lautet also: "Nein! PDO Prepared Statements verhindern nicht alle Arten von SQL-Injection"; Es verhindert keine unerwarteten Werte, sondern nur eine unerwartete Verkettung

Scharfschützen
quelle
5
Sie verwechseln SQL-Injection mit etwas anderem, was Ihre Antwort völlig irrelevant macht
Your Common Sense