Java JDBC SQL Injection

Critical Risk SQL Injection
sql-injectionjavajdbcdatabase

What it is

SQL injection vulnerability in Java applications using JDBC where user input is directly concatenated into SQL queries using Statement instead of PreparedStatement.

import java.sql.*;

public class UserDAO {
    private Connection connection;

    public User getUserById(String userId) throws SQLException {
        // VULNERABLE: String concatenation
        String query = "SELECT * FROM users WHERE id = " + userId;

        Statement stmt = connection.createStatement();
        ResultSet rs = stmt.executeQuery(query);

        if (rs.next()) {
            return new User(
                rs.getInt("id"),
                rs.getString("username"),
                rs.getString("email")
            );
        }
        return null;
    }
}
import java.sql.*;

public class UserDAO {
    private Connection connection;

    public User getUserById(int userId) throws SQLException {
        // SECURE: Using PreparedStatement
        String query = "SELECT * FROM users WHERE id = ?";

        try (PreparedStatement pstmt = connection.prepareStatement(query)) {
            pstmt.setInt(1, userId);
            ResultSet rs = pstmt.executeQuery();

            if (rs.next()) {
                return new User(
                    rs.getInt("id"),
                    rs.getString("username"),
                    rs.getString("email")
                );
            }
        }
        return null;
    }

    // Method with input validation
    public User getUserByIdSafe(String userIdStr) throws SQLException, IllegalArgumentException {
        // Validate and convert input
        int userId;
        try {
            userId = Integer.parseInt(userIdStr);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("Invalid user ID format");
        }

        if (userId <= 0) {
            throw new IllegalArgumentException("User ID must be positive");
        }

        return getUserById(userId);
    }
}

💡 Why This Fix Works

PreparedStatement in Java automatically handles parameter escaping and prevents SQL injection. The method also shows proper input validation.

Why it happens

Using Statement.executeQuery with string concatenation instead of PreparedStatement with parameters is the primary cause of SQL injection in Java applications.

Root causes

Using Statement with String Concatenation

Using Statement.executeQuery with string concatenation instead of PreparedStatement with parameters is the primary cause of SQL injection in Java applications.

Preview example – JAVA
// Vulnerable
String query = "SELECT * FROM users WHERE id = " + userId;
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);

Dynamic Query Building without Validation

Building SQL queries dynamically using user input without proper validation or parameterization creates injection vulnerabilities.

Preview example – JAVA
// Vulnerable
String query = String.format("SELECT * FROM users WHERE name = '%s'", userName);
Statement stmt = connection.createStatement();

Fixes

1

Use PreparedStatement with Parameters

Always use PreparedStatement with ? placeholders instead of Statement with string concatenation for SQL queries in Java.

View implementation – JAVA
// Secure
String query = "SELECT * FROM users WHERE id = ?";
try (PreparedStatement pstmt = connection.prepareStatement(query)) {
    pstmt.setInt(1, userId);
    ResultSet rs = pstmt.executeQuery();
}
2

Implement Input Validation

Validate and sanitize user input before using it in database queries. Use type checking and range validation.

View implementation – JAVA
public User getUserByIdSafe(String userIdStr) throws IllegalArgumentException {
    int userId = Integer.parseInt(userIdStr);
    if (userId <= 0) {
        throw new IllegalArgumentException("User ID must be positive");
    }
    return getUserById(userId);
}

Detect This Vulnerability in Your Code

Sourcery automatically identifies java jdbc sql injection and many other security issues in your codebase.