🔹 What is SQL Injection?
SQL Injection happens when an attacker inserts malicious SQL code into queries through
unvalidated input. This can allow unauthorized data access, data modification, or even full system
compromise.
🔹 Common Types of SQL Injection Attacks
1. Tautology Attack
👉 Injects a condition that is always true to bypass authentication.
❌ Vulnerable code:
String sql = "SELECT * FROM users WHERE username = '" + user + "' AND password =
'" + pass + "'";
Input:
user = admin
pass = ' OR '1'='1
Resulting query:
SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1'
✅ Always true → attacker logs in without password.
2. Union-Based Attack
👉 Uses UNION to retrieve extra data from other tables.
Input:
' UNION SELECT credit_card, cvv FROM payments --
Resulting query:
SELECT name, email FROM users WHERE id = ''
UNION SELECT credit_card, cvv FROM payments --
✅ Attacker gains credit card data.
3. Error-Based Attack
👉 Forces the database to reveal details via error messages.
Input:
' AND 1=CONVERT(int, 'abc') --
Error message may reveal:
Conversion failed when converting the varchar value 'abc' to data type int.
✅ Leaks DB structure → helps attacker craft further injections.
4. Blind SQL Injection
👉 No error messages → attacker infers results from application behavior.
Example:
' AND 1=1 -- (page loads normally)
' AND 1=2 -- (page fails)
✅ Attacker guesses database values bit by bit.
5. Inferential (Time-Based) SQL Injection
👉 Uses delays to infer data.
Input:
' OR IF(1=1, SLEEP(5), 0) --
✅ If response is delayed, attacker confirms condition is true.
6. Second-Order SQL Injection
👉 Malicious input is stored in DB and later executed.
Example:
• Attacker registers username:
test' OR '1'='1
• Later, app uses this value unsafely in a query:
String query = "SELECT * FROM users WHERE username = '" + storedUsername + "'";
✅ Stored injection is triggered when data is reused.
🔹 Mitigation Techniques
✔ Use Prepared Statements / Parameterized Queries
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement ps = [Link](sql);
[Link](1, username);
[Link](2, password);
✔ Use Stored Procedures with parameters
✔ Validate & sanitize all user inputs
✔ Prefer Spring Data JPA or JdbcTemplate with parameters
✅ Summary Table
Attack Type Example Input Goal
Tautology ' OR '1'='1 Bypass login
Union-Based ' UNION SELECT cc,cvv FROM payments Extract sensitive data
Error-Based ' AND 1=CONVERT(int,'abc')-- Leak DB structure
Blind ' AND 1=1 -- vs ' AND 1=2 -- Guess data step by step
Time-Based ' OR IF(1=1,SLEEP(5),0)-- Infer data via delay
Second-Order Malicious username stored & reused Trigger stored injection
🔹 1. Spring Data JPA
Spring Data JPA automatically uses prepared statements under the hood when you use repository
methods.
✅ Secure Example (parameterized, safe):
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u FROM User u WHERE [Link] = :username")
User findByUsername(@Param("username") String username);
}
❌ Insecure Example (string concatenation → vulnerable):
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u FROM User u WHERE [Link] = '" + username + "'")
User findByUsername(String username); // ⚠ vulnerable to SQLi
}
Rule of thumb: Always use @Param or method params instead of concatenating strings.
🔹 2. JdbcTemplate
JdbcTemplate supports parameterized queries with ? placeholders.
✅ Secure Example (prepared statement):
@Autowired
private JdbcTemplate jdbcTemplate;
public void saveUser(String username, String city) {
String sql = "INSERT INTO users (username, city) VALUES (?, ?)";
[Link](sql, username, city);
}
❌ Insecure Example (string concatenation → vulnerable):
public void saveUser(String username, String city) {
String sql = "INSERT INTO users (username, city) VALUES ('" + username + "',
'" + city + "')";
[Link](sql); // ⚠ vulnerable to SQLi
}
Rule of thumb: Always use placeholders (?) with update, queryForObject, etc.
🔹 3. Native SQL Queries (EntityManager)
Sometimes you need complex queries not possible with JPQL. You should always use
setParameter().
✅ Secure Example (parameterized):
@PersistenceContext
private EntityManager entityManager;
public User findByUsername(String username) {
String sql = "SELECT * FROM users WHERE username = :username";
return (User) entityManager
.createNativeQuery(sql, [Link])
.setParameter("username", username)
.getSingleResult();
}
❌ Insecure Example (unsafe string concatenation):
public User findByUsername(String username) {
String sql = "SELECT * FROM users WHERE username = '" + username + "'";
return (User) entityManager
.createNativeQuery(sql, [Link])
.getSingleResult(); // ⚠ vulnerable
}
Rule of thumb: Never build queries by concatenating raw input strings.
🔹 Summary Table
Approach Secure Usage Insecure Usage
Spring Data JPA @Param in queries / repository methods String concatenation in @Query
JdbcTemplate ? placeholders with update/query execute(sql) with raw input
Native SQL Queries setParameter() String concatenation in SQL