[JAVA] Sprechen Sie über die Vorteile von Datenbankbindungsvariablen (② Verdienst: Verhinderung der SQL-Injection)

2018/7/14 Vollständige Überarbeitung

====================================================================

** 0. Einleitung **

Letzter Beitrag Was sind also Datenbankbindungsvariablen? Ich habe es erklärt, aber dieses Mal möchte ich Ihnen den ersten Vorteil der Verwendung erläutern. Kurz gesagt, es kann die SQL-Injection verhindern (* 1).

** 1. Voraussetzung Fall **

Ich werde die im vorherigen Beitrag vorgestellte Tabelle noch einmal ansprechen.

id passwrod username email
22222 password2 Ruffy [email protected]
55555 password5 Sakuragi Hanamichi [email protected]
11111 password1 Momotaro Ken [email protected]
33333 password3 Kitzeln [email protected]

Informationen erhalten Sie durch Angabe der Benutzer-ID und des Kennworts aus dieser Tabelle. Die ID kennt jedoch "11111", setzt jedoch "'OR' A '=' A" anstelle von JJJ von PASSWORT Betrachten Sie den Fall der Ausgabe von SQL. SQL sieht so aus.

SELECT * FROM USERTABLE WHERE ID=11111 AND PASSWORD='' OR 'A' = 'A';

Mal sehen, was das Ergebnis mit und ohne die Bindungsvariable sein wird.

** 2. Wenn Sie keine Bindevariablen verwenden **

Wenn Sie keine Bindevariablen verwenden, wird das oben ausgegebene SQL wie folgt interpretiert:

Weiter 1. Oder 2. Wenn eine der Bedingungen erfüllt ist, werden alle Informationen aus USERTABLE extrahiert.
Bedingung 1.
USERID ist 11111 und PASSWORD ist leer (entspricht "ID = 11111 AND PASSWORD = ''" in der WHERE-Klausel).


Bedingung 2.
Der Wert "A" und der Wert "A" sind gleich (entsprechend "'A' = 'A'" in der WHERE-Klausel).

Diese Tabelle enthält keine Benutzerinformationen mit der ID 11111 und dem leeren PASSWORT, also erste Bedingung 1. Trifft nicht auf ... zu. Zweitens gilt Bedingung 2 für alle. Übrigens wird der in Last Post eingeführte Java-Code wie folgt geändert / hinzugefügt und SQL ausgegeben.

System.out.println("***** main method start *****");
・ ・ ・(Details weggelassen)・ ・ ・
//Bereiten Sie eine Erklärung vor.
statement = connection.createStatement();
//SQL deklarieren. Konfigurieren Sie SQL mit der Variablen-ID und dem Kennwort.
String sql = "select * from app.usertable where id = 11111 and password = '' OR 'A' = 'A'";
//Holen Sie sich das Ergebnis.
resultSet = statement.executeQuery(sql);
//Zeigen Sie das Ergebnis an.
while(resultSet.next()) {
                System.out.println("ID: " + resultSet.getInt(1));
                System.out.println("Vollständiger Name:" + resultSet.getString(3));
                System.out.println("Mail Adresse:" + resultSet.getString(4));
}

・ ・ ・(Details weggelassen)・ ・ ・
System.out.println("***** main method end *****");

Das Ergebnis ist wie folgt. Ich habe DBMS mit Derby (JavaDB) und MySQL ausprobiert und das gleiche Ergebnis erzielt.

***** main method start *****
ID: 22222
Name: Ruffy
E-Mail-Adresse: [email protected]
ID: 55555
Name: Sakuragi Hanamichi
E-Mail-Adresse: [email protected]
ID: 11111
Name: Momotaro Ken
E-Mail-Adresse: [email protected]
ID: 33333
Name: Kinni kitzeln
E-Mail-Adresse: [email protected]
***** main method end *****

Hoppla! ?? Ich konnte alle Informationen in der Tabelle abrufen. Normalerweise müssen Sie die richtigen Werte in ID und PASSWORD eingeben, um die entsprechenden Informationen von USERTABLE zu erhalten. Durch Eingabe von "'OR' A '=' A" in PASSWORD ist USERTABLE jedoch illegal Sie können alle Informationen abrufen. Hier ist ein Beispiel für die SQL-Injection.

** 3. Bei Verwendung von Bindevariablen **

Was passiert also, wenn Sie Bindevariablen für diese SQL verwenden? Der in Last Post eingeführte Java-Code wurde wie folgt geringfügig geändert.

System.out.println("***** main method start *****");
・ ・ ・(Details weggelassen)・ ・ ・
//SQL deklarieren. Für Spalten-ID und Passwort:?Durch Einfügen von "werden diese als Bindungsvariablen deklariert.
String sql = "select * from app.usertable where id = ? and password = ?";
//Bereiten Sie ein PreparedStatement vor, um die SQL auszugeben, in der die Bindevariablen gespeichert sind.
preparedStatement = connection.prepareStatement(sql);
//Weisen Sie einen Wert für id zu. Diese "1" bezieht sich auf die erste Bindungsvariablen-ID.
preparedStatement.setInt(1, 11111);
//Weisen Sie dem Passwort einen Wert zu. Diese "2" bezieht sich auf das zweite Kennwort für die Bindungsvariable.
preparedStatement.setString(2, "'' OR 'A' = 'A'");
//Holen Sie sich das Ergebnis.
resultSet = preparedStatement.executeQuery();
//Zeigen Sie das Ergebnis an.
while(resultSet.next()) {
                System.out.println("ID: " + resultSet.getInt(1));
                System.out.println("Vollständiger Name:" + resultSet.getString(3));
                System.out.println("Mail Adresse:" + resultSet.getString(4));
}

・ ・ ・(Details weggelassen)・ ・ ・
System.out.println("***** main method end *****");

Wenn Sie den obigen Code ausführen, wird SQL ausgegeben. Das Ergebnis ist jedoch: Ich habe auch DBMS mit Derby (JavaDB) und MySQL ausprobiert, und die Ergebnisse waren dieselben.

***** main method start *****
***** main method end *****

Oh? Wird nicht nichts angezeigt? Was zur Hölle ist passiert?

Der folgende Ablauf zeigt, was passiert, wenn SQL mit Bindevariablen ausgegeben wird.

(1) Der Wert der Bindevariablen und der SQL ohne ihn werden separat an das DBMS ausgegeben. (2) Der Wert der Bindevariablen wird interpretiert, bevor er in SQL zusammengeführt wird, und "'" wird maskiert. Mit anderen Worten, da "'" als das Zeichen "'" interpretiert wird, wird es mit zwei einfachen Anführungszeichen als "''" konvertiert. (3) Der Wert der in (2) verarbeiteten Bindungsvariablen und der SQL werden zusammengeführt und ausgeführt.

バインド変数SQLが発行されるイメージ.png

Die in ③ ausgeführte SQL ist SELECT * FROM USERTABLE WHERE ID=11111 AND PASSWORD=''' OR ''A'' = ''A'; Es wird wie folgt sein. Wie ist das? Sie können sehen, dass es sich von SQL unterscheidet, als es durch Injektion angegriffen wurde. Korrekt. PASSWORT wird interpretiert als "'' ODER '' A '' =" A "". Ein Benutzer mit einem solchen Kennwort ist in USERTABLE nicht vorhanden, sodass nicht alle Informationen abgerufen werden können.

Das Obige ist ein Beispiel. Es gibt auch eine Möglichkeit, nicht nur "'", sondern auch ">" und "<" zu entkommen. Weitere Informationen finden Sie im Datenbankhandbuch usw. (* 2).

** 4. Fazit **

Übrigens möchte ich beim nächsten Mal am Ende dieser Reihe über den zweiten Vorteil von Bindevariablen sprechen.

Fußnote

(※1) Weitere Informationen zur SQL-Injection finden Sie unter der folgenden URL. https://ja.wikipedia.org/wiki/SQL%E3%82%A4%E3%83%B3%E3%82%B8%E3%82%A7%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3

(※2) Klicken Sie hier für Oracle Database. http://www.oracle.com/technetwork/jp/database/articles/pickup/index-1622026-ja.html

(※3) Ich habe beim Erstellen dieses Artikels auch auf die folgende URL verwiesen.

IPA Information Processing Promotion Organization "So rufen Sie sicheres SQL auf" http://www.ipa.go.jp/files/000017320.pdf

Hatena Diary [Sicherheit] Escape in Oracle http://d.hatena.ne.jp/teracc/20071230

Recommended Posts

Sprechen Sie über die Vorteile von Datenbankbindungsvariablen (② Verdienst: Verhinderung der SQL-Injection)
Über die Vorzüge von Datenbankbindungsvariablen sprechen ((1) Einführung)
[Ausgabe] Informationen zur Datenbank
[Java] Ich habe über die Vorzüge und Verwendungen von "Schnittstelle" nachgedacht.
Über den Umgang mit Null
Informationen zur Beschreibung von Docker-compose.yml
Lassen Sie uns über die vorübergehende Erfahrung von Java SE 8 Programmer II sprechen
[Rails] Sprechen Sie darüber, wie Sie auf den Rückgabewert von where achten