diff --git a/src/main/java/org/owasp/webgoat/lessons/sqlinjection/introduction/SqlInjectionLesson8.java b/src/main/java/org/owasp/webgoat/lessons/sqlinjection/introduction/SqlInjectionLesson8.java index fb417e8..0112939 100644 --- a/src/main/java/org/owasp/webgoat/lessons/sqlinjection/introduction/SqlInjectionLesson8.java +++ b/src/main/java/org/owasp/webgoat/lessons/sqlinjection/introduction/SqlInjectionLesson8.java @@ -46,20 +46,18 @@ public class SqlInjectionLesson8 implements AssignmentEndpoint { protected AttackResult injectableQueryConfidentiality(String name, String auth_tan) { StringBuilder output = new StringBuilder(); - String query = - "SELECT * FROM employees WHERE last_name = '" - + name - + "' AND auth_tan = '" - + auth_tan - + "'"; + // Both WHERE values are bound as data, so an injected tautology cannot widen the result set. + String query = "SELECT * FROM employees WHERE last_name = ? AND auth_tan = ?"; try (Connection connection = dataSource.getConnection()) { try { - Statement statement = - connection.createStatement( - ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); - log(connection, query); - ResultSet results = statement.executeQuery(query); + PreparedStatement statement = + connection.prepareStatement( + query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + statement.setString(1, name); + statement.setString(2, auth_tan); + log(connection, "lookup: " + name + " / " + auth_tan); + ResultSet results = statement.executeQuery(); if (results.getStatement() != null) { if (results.first()) { @@ -129,17 +127,18 @@ public class SqlInjectionLesson8 implements AssignmentEndpoint { } public static void log(Connection connection, String action) { - action = action.replace('\'', '"'); Calendar cal = Calendar.getInstance(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String time = sdf.format(cal.getTime()); - String logQuery = - "INSERT INTO access_log (time, action) VALUES ('" + time + "', '" + action + "')"; + // Parameterized INSERT — the logged action is stored as data, preventing second-order + // injection into access_log even when the action text contains SQL metacharacters. + String logQuery = "INSERT INTO access_log (time, action) VALUES (?, ?)"; - try { - Statement statement = connection.createStatement(TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE); - statement.executeUpdate(logQuery); + try (PreparedStatement statement = connection.prepareStatement(logQuery)) { + statement.setString(1, time); + statement.setString(2, action); + statement.executeUpdate(); } catch (SQLException e) { System.err.println(e.getMessage()); }