Java 웹 애플리케이션에서 문자열 userId를 조건으로 회원을 조회한다. 다음 구현 중 SQL 구조와 입력값을 분리해 SQL Injection을 가장 직접적으로 방지하는 것은?
1
String sql = "SELECT * FROM users WHERE id='" + userId + "'";
오답 이유사용자 입력을 SQL 문자열에 직접 이어 붙이므로 입력이 SQL 구문 구조를 바꿀 수 있다.
2
PreparedStatement ps = con.prepareStatement("SELECT * FROM users WHERE id=?"); ps.setString(1, userId);
정답 근거플레이스홀더가 있는 PreparedStatement와 setString 바인딩은 SQL 코드와 데이터 값을 분리하므로 정답이다.
3
userId = userId.replace("'", ""); String sql = "SELECT * FROM users WHERE id='" + userId + "'";
오답 이유특정 문자 하나를 삭제하는 블랙리스트 방식은 인코딩·DB 문법·숫자형 조건 등 다양한 우회를 막지 못하며 문자열 결합도 남아 있다.
4
String sql = "CALL find_user('" + userId + "')";
오답 이유저장 프로시저 호출이라도 사용자 입력을 동적 호출문에 연결하면 SQL Injection 위험이 사라지지 않는다.
정답·상세해설
정답 2번
매개변수화된 질의는 SQL 문장을 먼저 정의하고 사용자 입력을 별도 값으로 바인딩한다. 따라서 입력에 따옴표나 SQL 키워드가 있어도 DB는 이를 명령 구조가 아닌 데이터로 처리한다. 단순 문자 치환이나 저장 프로시저라는 이름만으로는 동적 문자열 결합의 위험을 제거할 수 없다.