Hier ist SQL zum Einrichten eines Beispiels:
CREATE TABLE employee(name varchar, paymentType varchar, amount bigint);
INSERT INTO employee VALUES('Aaron', 'salary', 100);
INSERT INTO employee VALUES('Aaron', 'bonus', 50);
INSERT INTO employee VALUES('Bob', 'salary', 50);
INSERT INTO employee VALUES('Bob', 'bonus', 0);
Die Inject-Klasse ist anfällig für SQL-Injection. Die Abfrage wird dynamisch zusammen mit Benutzereingaben eingefügt. Die Abfrage sollte Informationen über Bob anzeigen. Entweder Gehalt oder Bonus, basierend auf Benutzereingaben. Der böswillige Benutzer manipuliert jedoch die Eingabe, die die Abfrage beschädigt, indem er das Äquivalent eines 'oder true' zur where-Klausel anheftet, sodass alles zurückgegeben wird, einschließlich der Informationen über Aaron, die ausgeblendet werden sollten.
import java.sql.*;
public class Inject {
public static void main(String[] args) throws SQLException {
String url = "jdbc:postgresql://localhost/postgres?user=user&password=pwd";
Connection conn = DriverManager.getConnection(url);
Statement stmt = conn.createStatement();
String sql = "SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType='" + args[0] + "'";
System.out.println(sql);
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
System.out.println(rs.getString("paymentType") + " " + rs.getLong("amount"));
}
}
}
Wenn Sie dies ausführen, ist der erste Fall bei normaler Verwendung und der zweite bei böswilliger Injektion:
c:\temp>java Inject salary
SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType='salary'
salary 50
c:\temp>java Inject "salary' OR 'a'!='b"
SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType='salary' OR 'a'!='b'
salary 100
bonus 50
salary 50
bonus 0
Sie sollten Ihre SQL-Anweisungen nicht mit einer Zeichenfolgenverkettung von Benutzereingaben erstellen. Es ist nicht nur anfällig für Injection, sondern hat auch Auswirkungen auf das Caching auf dem Server (die Anweisung ändert sich, sodass es weniger wahrscheinlich ist, dass ein SQL-Anweisungscache getroffen wird, während im Bindungsbeispiel immer dieselbe Anweisung ausgeführt wird).
Hier ist ein Beispiel für die Bindung, um diese Art der Injektion zu vermeiden:
import java.sql.*;
public class Bind {
public static void main(String[] args) throws SQLException {
String url = "jdbc:postgresql://localhost/postgres?user=postgres&password=postgres";
Connection conn = DriverManager.getConnection(url);
String sql = "SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType=?";
System.out.println(sql);
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, args[0]);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("paymentType") + " " + rs.getLong("amount"));
}
}
}
Wenn Sie dies mit derselben Eingabe wie im vorherigen Beispiel ausführen, funktioniert der Schadcode nicht, da kein Zahlungstyp vorhanden ist, der dieser Zeichenfolge entspricht:
c:\temp>java Bind salary
SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType=?
salary 50
c:\temp>java Bind "salary' OR 'a'!='b"
SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType=?