SQL Injection - MyBatis, JPA, JDBC

김재윤·2025년 2월 27일

MyBatis, JPA, JDBC에서 SQL Injection 방지하는 법

SQL Injection은 해커가 악의적인 SQL 문을 삽입하여 데이터베이스를 조작하는 공격 방식입니다. 오늘은 MyBatis, JPA, JDBC에서 SQL Injection을 방지하는 방법에 대해 알아보겠습니다.


✅ MyBatis와 JPA는 SQL Injection에 안전할까?

MyBatis에서 안전한 코드

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에서 안전한 코드

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 가능!

해결 방법: 바인딩 파라미터 :파라미터명 사용!


⚠ JDBC에서 SQL Injection이 발생하는 경우

❌ 취약한 코드 (Statement 사용 시 위험)

Statement stmt = connection.createStatement();
String sql = "SELECT * FROM users WHERE username = '" + username + "'";
ResultSet rs = stmt.executeQuery(sql);

사용자가 username'; DROP TABLE users; -- 같은 값을 입력하면, 데이터베이스 테이블이 삭제될 수도 있습니다.

해결 방법: PreparedStatement 사용!

✅ 안전한 코드 (PreparedStatement 사용)

String sql = "SELECT * FROM users WHERE username = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, username);
ResultSet rs = pstmt.executeQuery();

? 바인딩을 사용하면 SQL과 입력값이 분리되므로 SQL Injection이 방어됩니다.


🔥 안전한 SQL 사용을 위한 3가지 원칙

MyBatis: ${} 대신 #{} 사용!
JPA: 문자열 연결하지 말고 @Query:파라미터 사용!
JDBC: Statement 대신 PreparedStatement 사용!

이 원칙만 지키면 SQL Injection을 방어할 수 있습니다! 💪

profile
그럼에도 불구하고, Do it.

0개의 댓글