SQL-Injektion ist ein einfacher Angriffsvektor, der auch heute noch sehr verbreitet ist. Der Grund dafür ist nichts anderes als kein Patch für Dummheit. Warum sagen Sie das? Nehmen wir JAVA als Beispiel zur Veranschaulichung:
Angenommen, eine solche Tabelle existiert in der Datenbank:
Dann verwenden Sie die JDBC-Aktionstabelle:
Der oben genannte Code wird von einigen Entwicklern häufig verwendet. Stellen Sie sich eine Situation vor, in der der eingehende userId-Parameter "3; Drop-Table-Nutzer; Die ausgeführte SQL-Anweisung lautet wie folgt:
Nachdem die Datenbank kompiliert und ausgeführt wurde, wird die Benutzertabelle gelöscht. Voilà, ein einfacher SQL-Injektionsangriff wirkt! Dies liegt daran, dass der obige Code nicht den Programmierspezifikationen entspricht.
Wenn wir gemäß der Spezifikation programmieren, ist SQL-Injektion nicht vorhanden. Das ist auch der FallDer erste Weg, SQL-Injection zu vermeiden: vorkompilierte Anweisungen, der Code lautet wie folgt:
Warum existiert keine SQL-Injektion im obigen Code? Da die vorkompilierte Anweisung verwendet wird, setzt die vorkompilierte Anweisung "Name vom Benutzer auswählen, wo id= ?" Die Anweisung wird im Voraus kompiliert, sodass sie beim Ausführen nur durch die eingehenden Parameter ersetzt werden muss? Platzhalter sind in Ordnung. Im ersten nicht-konformen Fall schreibt das Programm eine SQL-Anweisung und kompiliert diese dann mit dem vom Benutzer übermittelten Inhalt, was genau das Problem ist.
Neben der Verwendung vorkompilierter Anweisungen gibt es eine zweite OptionMöglichkeiten, SQL-Injection-Angriffe zu vermeiden: Gespeicherte Prozeduren。 Eine gespeicherte Prozedur ist eine Menge von SQL-Anweisungen, die eine bestimmte Funktion ausführen, kompiliert und in einer Datenbank gespeichert werden, und der Benutzer kann sie ausführen, indem er eine gespeicherte Prozedur aufruft und einen Parameter angibt (falls die gespeicherte Prozedur Parameter enthält), der ebenfalls SQL-Injection-Angriffe vermeiden kann
Das entsprechende gespeicherte Verfahren im obigen Code ist wie folgt:
Natürlich können Nutzer auch Zeichenprüfungen im Frontend durchführen, was ebenfalls eine Möglichkeit ist, SQL-Injektionen zu vermeiden: Zum Beispiel prüft der Benutzer für den oben genannten userId-Parameter nach einem Semikolon und es wird ein Fehler angezeigt. Der grundlegendste Grund ist jedoch, dass SQL-Injection-Angriffe existieren, weil Apps beim Zugriff auf Datenbanken kein Least Privilege nutzen. Es scheint, als hätten alle das Root-Konto genutzt, um auf die Datenbank zuzugreifen.
Wie vermeidet MyBatis also SQL-Injection-Angriffe? Oder nehmen wir den oben genannten Tabellenbenutzer: Angenommen, die Mapper-Datei ist:
Die entsprechenden Java-Dateien sind:
Man sieht, dass der Eingabeparameter userId vom Typ String ist, wenn wir userId="34; Drop-Table-Nutzer; Danach lautet die gedruckte Stellungnahme:
Unabhängig von der eingegebenen Benutzer-ID sieht seine SQL-Anweisung so aus. Dies liegt daran, dass Mybatis in der zugrundeliegenden Implementierung vorkompilierte Anweisungen verwendet. Wenn die Datenbank diese Anweisung ausführt, verwendet sie direkt die vorkompilierte Anweisung und ersetzt dann den Platzhalter durch die passierende userId? Geh einfach los. Platzhalter zuerst ersetzen? Der Kompilierungsprozess wird durchgeführt, sodass kein Platz für SQL-Injektionen besteht.
Wie führt MyBatis also SQL-Precompilation durch? Tatsächlich wird die PreparedStatement-Klasse am unteren Rand des Frameworks verwendet. Die PreparedStaement-Klasse vermeidet nicht nur SQL-Injection, sondern spart auch (N-1) Kompilierungszeit, wenn dieselbe SQL-Anweisung N Mal ausgeführt wird, was die Effizienz verbessert.
Wenn Sie die obige Aussage ändern zu:
Wenn wir userId="34; Drop-Table-Nutzer; Danach lautet die gedruckte Stellungnahme:
Derzeit verwendet Mybatis keine vorkompilierten Anweisungen, sondern fügt zuerst Strings zusammen und führt dann die Kompilierung durch, was genau die SQL-Injektion ist.
Versuchen Sie daher beim Schreiben von Mybatis-Mapping-Anweisungen das Format "#{xxx}" zu verwenden. Wenn du Parameter wie "${xxx}" verwenden musst, musst du sie manuell filtern, um SQL-Injection-Angriffe zu verhindern.
|