SQL 인젝션에 대하여
SQL 삽입공격이라고 하는 SQL 인젝션(SQL Injection)은 웹 애플리케이션에서 발생하는 보안 취약점 중 하나로, 악의적인 사용자가 애플리케이션의 입력 폼 등을 통해 악의적인 SQL 문을 삽입하는 공격 기법입니다. 이를 통해 공격자는 데이터베이스에 대한 액세스 권한을 얻거나, 데이터베이스의 데이터를 조작하거나 삭제하는 등의 악의적인 행위를 할 수 있습니다.
SQL 인젝션 취약점
- 데이터베이스 정보 노출: 인젝션 공격을 통해 악의적인 사용자는 데이터베이스의 정보를 노출시킬 수 있습니다. 예를 들어, SQL 인젝션을 이용하여 데이터베이스의 테이블 이름, 칼럼 이름, 데이터 등을 조회할 수 있습니다.
- 데이터베이스 데이터 조작: 악의적인 사용자는 인젝션을 통해 데이터베이스의 데이터를 조작할 수 있습니다. 예를 들어, 사용자 인증을 우회하여 로그인 절차 없이 액세스할 수 있거나, 데이터를 삭제하거나 변경할 수 있습니다.
- 시스템 명령 실행: SQL 인젝션을 통해 악의적인 사용자는 데이터베이스 서버가 실행하는 시스템 명령을 조작할 수 있습니다. 이를 통해 서버의 운영 체제 명령을 실행하거나, 파일을 업로드하거나 다운로드할 수 있습니다.
- 서비스 거부 공격(DoS): 인젝션을 통해 악의적인 사용자가 데이터베이스의 리소스를 과도하게 사용하거나 악성 쿼리를 실행할 수 있습니다. 이로 인해 서비스 거부 공격이 발생하여 시스템이 느려지거나 다운될 수 있습니다.
SQL 인젝션 방어 기법
- 입력 값의 유효성 검사: 사용자 입력 값에 대해 유효성 검사를 수행하여 허용되지 않은 문자나 패턴을 걸러내는 필터링 과정을 구현합니다.
- Prepared Statements 또는 Parameterized Queries 사용: SQL 쿼리에서 사용자 입력을 동적으로 생성하는 경우, Prepared Statements 또는 Parameterized Queries를 사용하여 입력 값을 파라미터로 전달합니다. 이를 통해 입력 값이 SQL 쿼리의 일부로 해석되는 것을 방지할 수 있습니다.
- 권한 및 접근 제어: 데이터베이스 사용자에게는 최소한의 권한만 부여하여 인젝션 공격 시 데이터 유출 및 수정을 최소화합니다.
- 웹 애플리케이션 방화벽 (WAF) 사용: 웹 애플리케이션 방화벽을 사용하여 악의적인 SQL 쿼리를 탐지하고 차단할 수 있습니다.
SQL 인젝션은 주로 사용자의 입력을 동적으로 생성된 SQL 쿼리에 포함시키는 경우에 발생할 수 있습니다. 예를 들어, 사용자로부터 입력받은 값을 기반으로 SQL 쿼리를 실행하는 경우, 악의적인 사용자가 입력 필드에 다음과 같은 값을 입력할 수 있습니다.
SQL인젝션의 예
' OR '1'='1
'1'='1'은 항상 참이므로, 해당 쿼리는 사용자 테이블의 모든 행을 반환할 수 있습니다. 이렇게 인증 과정을 우회하거나, 데이터베이스의 데이터를 불법적으로 조회, 수정, 삭제하는 등의 악의적인 동작이 가능해집니다.
악의적인 사용자가 입력한 값이 SQL 쿼리에 그대로 포함되므로 다음과 같은 쿼리가 실행될 수 있습니다.
SELECT * FROM users WHERE username='' OR '1'='1' AND password=''
위와 같이 SQL 명령을 변형시켜 의도하지 않은 값을 집어 넣을 수 있습니다.
SQL 취약점 코드
<%
String userInput = request.getParameter("username");
// 사용자 입력을 그대로 쿼리에 포함시킴
String query = "SELECT * FROM users WHERE username='" + userInput + "'";
Statement stmt = connection.createStatement();
// 쿼리 실행
ResultSet rs = stmt.executeQuery(query);
// 결과 처리
while (rs.next()) {
// 사용자 정보를 읽어오는 로직
}
// 리소스 정리
rs.close();
stmt.close();
%>
위의 코드에서 userInput은 사용자로부터 입력받은 값입니다. 그러나 입력값을 그대로 SQL 쿼리에 문자열로 포함시키는 방식을 사용하고 있습니다. 이는 SQL 인젝션 취약점을 내포하고 있으며, 악의적인 사용자가 입력 필드에 악의적인 SQL 코드를 삽입할 수 있습니다.
SQL 인젝션 방지 코드
<%
String userInput = request.getParameter("username");
// SQL 쿼리를 파라미터화된 형태로 작성
String query = "SELECT * FROM users WHERE username = ?";
PreparedStatement pstmt = connection.prepareStatement(query);
// 입력값을 파라미터로 설정
pstmt.setString(1, userInput);
// 쿼리 실행
ResultSet rs = pstmt.executeQuery();
// 결과 처리
while (rs.next()) {
// 사용자 정보를 읽어오는 로직
}
// 리소스 정리
rs.close();
pstmt.close();
%>
pstmt.setString(1, userInput) 코드를 사용하여 "?" 자리에 사용자 입력 값을 설정합니다. 이렇게 함으로써 입력값이 쿼리의 일부로 해석되는 것을 방지합니다. setString(1, userInput)은 첫 번째 ? 자리에 userInput 값을 문자열로 설정한다는 의미입니다.
이렇게 Prepared Statements를 사용하면 사용자 입력을 안전하게 처리할 수 있고, SQL 인젝션 공격으로부터 애플리케이션을 보호할 수 있습니다.
'개발 지식' 카테고리의 다른 글
코드 리팩토링(Refactoring)이란? | 민민의 하드디스크 - 티스토리 (1) | 2023.06.26 |
---|---|
[개발 지식] Spring과 Spring boot란? | 민민의 하드디스크 - 티스토리 (1) | 2023.06.16 |
[개발 지식] var와 let에 대하여 | 민민의 하드디스크 - 티스토리 (0) | 2023.05.11 |
[개발 지식] 연산자 "=="와 "==="의 차이 | 민민의 하드디스크 - 티스토리 (0) | 2023.05.09 |
[개발 지식] 환경 변수란 ?? | 민민의 하드디스크 - 티스토리 (0) | 2023.05.02 |