설명
SQL 인젝션은 외부 입력이 데이터가 아니라 SQL 문법의 일부로 해석될 때 발생합니다. 공격자는 쿼리의 조건이나 동작을 바꿀 수 있으며, 영향은 데이터베이스 계정의 권한과 사용 가능한 기능에 따라 달라집니다.
잠재적 영향
- 무단 코드 실행: 데이터베이스 기능과 계정 권한이 허용하는 환경에서는 시스템 명령 실행으로 이어질 수 있습니다.
- 애플리케이션 데이터 읽기: SQL 데이터베이스에 저장된 민감한 정보를 읽을 수 있습니다.
- 권한 상승: 다른 사용자의 신분으로 시스템에 접근할 수 있습니다.
- 보호 메커니즘 우회: 인증 및 접근 제어를 우회할 수 있습니다.
- 데이터 수정: 데이터베이스의 정보를 읽거나 수정, 삭제할 수 있습니다.
해결 방법
PreparedStatement나JdbcTemplate의 매개변수 바인딩으로 값과 SQL 문법을 분리하세요. 입력을 연결한 뒤 준비하는 것만으로는 충분하지 않습니다.- ORM에서도 문자열로 조합하는 SQL·JPQL·HQL은 같은 위험이 있습니다. 지원되는 바인딩 API를 사용하세요.
- 테이블명·열명·정렬 방향처럼 값 매개변수로 표현할 수 없는 요소는 서버가 관리하는 허용 목록에서 선택하세요.
- 입력 형식과 길이를 검증하고 데이터베이스 계정에 필요한 최소 권한만 부여하세요.
예시
다음은 JdbcTemplate으로 사용자 레코드를 조회하는 발췌이며 로그인 구현이 아닙니다. 비밀번호 검증과 조회 권한 확인은 별도로 수행하세요.
변경 전
java
String query = "SELECT id, username FROM users WHERE username = '" + username + "'";
jdbcTemplate.queryForList(query);
변경 후
java
String query = "SELECT id, username FROM users WHERE username = ?";
jdbcTemplate.queryForList(query, username);
변경 전에는 username을 쿼리 문자열에 연결합니다. 변경 후에는 조회용 queryForList()에 값을 별도로 전달하므로 username이 SQL 문법으로 해석되지 않습니다.
관련 CVE
- CVE-2023-32530: SQL injection in security product dashboard using crafted certificate fields
- CVE-2021-42258: SQL injection in time and billing software, as exploited in the wild per CISA KEV.
- CVE-2021-27101: SQL injection in file-transfer system via a crafted Host header, as exploited in the wild per CISA KEV.