SQL Injection은 해커가 악의적인 SQL 문을 삽입하여 데이터베이스를 조작하는 공격 방식입니다. 오늘은 MyBatis, JPA, JDBC에서 SQL Injection을 방지하는 방법에 대해 알아보겠습니다.
MyBatis는 PreparedStatement(바인딩 파라미터) 를 사용하면 SQL Injection을 방어할 수 있습니다.
#{} 사용)<select id="getUserById" parameterType="int" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
${} 사용 시 취약)<select id="getUserByName" parameterType="String" resultType="User">
SELECT * FROM users WHERE name = '${name}'
</select>
🚨 ${}를 사용하면 입력값이 그대로 SQL에 삽입되므로 공격 가능!
✅ 해결 방법: #{} 바인딩 파라미터 사용!
JPA에서도 바인딩 파라미터를 사용하면 안전합니다.
@Query + :파라미터 사용)@Query("SELECT u FROM User u WHERE u.id = :id")
User findById(@Param("id") Long id);
@Query(value = "SELECT * FROM users WHERE name = '" + name + "'", nativeQuery = true)
User findByName(String name);
🚨 문자열 연결(+)을 사용하면 SQL Injection 가능!
✅ 해결 방법: 바인딩 파라미터 :파라미터명 사용!
Statement stmt = connection.createStatement();
String sql = "SELECT * FROM users WHERE username = '" + username + "'";
ResultSet rs = stmt.executeQuery(sql);
사용자가 username에 '; DROP TABLE users; -- 같은 값을 입력하면, 데이터베이스 테이블이 삭제될 수도 있습니다.
✅ 해결 방법: PreparedStatement 사용!
String sql = "SELECT * FROM users WHERE username = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, username);
ResultSet rs = pstmt.executeQuery();
? 바인딩을 사용하면 SQL과 입력값이 분리되므로 SQL Injection이 방어됩니다.
✅ MyBatis: ${} 대신 #{} 사용!
✅ JPA: 문자열 연결하지 말고 @Query의 :파라미터 사용!
✅ JDBC: Statement 대신 PreparedStatement 사용!
이 원칙만 지키면 SQL Injection을 방어할 수 있습니다! 💪