SQL Injection

itonse·2024년 5월 30일
0

CS 스터디

목록 보기
45/56

해당 주제 관련 기술면접 질문 미리보기

Q1. SQL Injection에 대해서 설명해주세요.
Q2. SQL Injection을 방어하기 위한 방법을 말해주세요.


SQL 인젝션이란?

  • 공격자가 악의적인 의도를 갖는 구문을 삽입하여 공격자가 원하는 SQL을 실행하도록 하는 웹해킹 기법입니다.
  • 이를 통해 DB의 데이터를 탈취하거나, 수정, 삭제할 수 있습니다.

예시)

String query = 
"SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";
SELECT * FROM users WHERE username = '' OR '1'='1' -- ' AND password = ''

username과 password에 항상 참이 되는 구문을 삽입하여 공격자는 로그인에 성공하게 됩니다.



SQL Injection 대응

Spring Boot, JPA를 사용하고 있는 상황이라면, 다음과 같이 SQLI에 대응을 하게 됩니다.

용어 정리

Prepared Statements

  • SQL 쿼리를 미리 컴파일하여 쿼리의 구조를 고정합니다.
  • 쿼리 실행 시점에 Parameter Binding을 하여 SQL Injection을 방지합니다.

Parameter Binding

  • Prepared Statements의 중요한 특징 중 하나입니다.
  • 파라미터 바인딩을 통해 사용자 입력값이 쿼리 문자열에 안전하게 포함됩니다.
  • SQL 쿼리와 입력값을 분리하여 쿼리의 구조를 변형하지 않고 실행합니다.

1. Spring Data JPA

JPA는 Hibernate를 통해 Prepared Statements를 사용하여 SQL Injection을 방지하고, 이를 통해 Parameter Binding을 수행합니다.

public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByUsername(String username);
}

이 코드에서는 findByUsername 메서드가 Hibernate에 의해 안전하게 처리됩니다.

2. JPQL

JPQL에서도 Parameter Binding을 통해 SQL Injection을 방지할 수 있습니다.

@Query("SELECT u FROM User u WHERE u.username = :username")
List<User> findByUsername(@Param("username") String username);

여기서 :username은 파라미터 바인딩을 통해 안전하게 값이 대입됩니다.

3. 네이티브 쿼리

네이티브 쿼리는 직접 SQL 구문을 작성하기 때문에 SQL Injection의 위험이 상대적으로 높습니다. 그러나 Parameter Binding을 통해 이 위험을 줄일 수 있습니다.

String sql = "SELECT * FROM users WHERE username = :username";
Query query = entityManager.createNativeQuery(sql, User.class);
query.setParameter("username", username);
List<User> users = query.getResultList();

여기서 :username은 파라미터 바인딩을 통해 안전하게 값이 대입됩니다.

4. QueryDSL

QueryDSL은 타입 안전한 동적 쿼리를 메서드 체이닝으로 작성하며, 입력값을 안전하게 바인딩하여 컴파일 타임에 SQL Injection을 방지합니다.

JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
QUser user = QUser.user;

List<User> users = queryFactory.selectFrom(user)
    .where(user.username.eq(username))
    .fetch();

정리

JPA: 기본적으로 Prepared Statements를 사용하여 안전함.
JPQL: Parameter Binding을 통해 안전함.
네이티브 쿼리: 직접 SQL을 작성하기 때문에 위험성이 높지만, Parameter Binding을 통해 안전하게 사용할 수 있음.
QueryDSL: 타입 안전한 쿼리 작성 방식을 사용하여 매우 안전함.



SQL Injection 관련 기술면접 질문들

Q1. SQL Injection에 대해서 설명해주세요.

SQL Injection은 공격자가 웹 애플리케이션의 입력 필드에 악의적인 SQL 구문을 삽입하여 데이터베이스를 조작하는 공격 기법입니다. 이를 통해 공격자는 데이터베이스의 데이터를 탈취하거나, 수정, 삭제할 수 있으며, 인증을 우회할 수도 있습니다.


Q2. SQL Injection을 방어하기 위한 방법을 말해주세요.

첫째, Spring Data JPA와 같은 ORM 프레임워크를 사용하는 것입니다. 이 프레임워크는 내부적으로 Prepared Statements를 사용하여 SQL Injection을 방지합니다. Prepared Statements는 SQL 쿼리를 미리 고정하고, 실행 시점에 파라미터를 안전하게 바인딩하여 입력값이 쿼리를 변조하지 않도록 합니다.

둘째, 네이티브 쿼리를 사용할 때는 파라미터 바인딩을 꼭 사용해야 합니다. 네이티브 쿼리는 직접 SQL 구문을 작성하기 때문에 SQL Injection의 위험이 더 높습니다. 파라미터 바인딩을 통해 입력값이 쿼리 문자열에 직접 포함되지 않게 하여 SQL Injection을 방지할 수 있습니다.


ref.
https://mangkyu.tistory.com/88
https://developer-ping9.tistory.com/545

0개의 댓글