데이터베이스

SQL 인젝션(Injection) 보안 상의 허점

스윙스윙 2021. 9. 9. 21:49

▣ SQL 인젝션(Injection) 보안 상의 허점

SQL 인젝션
(Injection)
잘못 만들어진 웹어플리케이션에서 사용자로부터 입력받은 데이터를 SQL문에 붙여서 처리할 때
해커는 임의로 SQL문을 변경하여 사용자 인증을 우회하거나 데이터베이스 정보를 취득하는 공격
Blind SQL Injection, Mass SQL Injection, CSRF(Cros-site request forgery)
대응 방법 : 사용자 입력의 필터링
                SQL 에러메시지를 사용자에게 보여주지 않도록 설정
                웹어플리케이션 사용하는 DB유저의 권한을 제한

<SQL injection 취약점>

- 사용자 인증을 비정상적으로 통과할 수 있다.

- 데이터베이스에 저장된 데이터를 임의로 열람할 수 있다.

- 데이터베이스의 시스템 명령을 이용하여 시스템 조작이 가능하다.

 

<SQL injection 보호 대책>

- 데이터베이스와 연동을 하는 스크립트의 모든 파라미터들을 점검하여 사용자의 입력 값이 SQL injection을 발생시키지 않도록 수정한다.

- 사용자 입력이 SQL injection을 발생시키지 않도록 사용자 입력 시 특수문자( ' " / \ ; : Space -- + 등)가 포함되어 있는지 검사하여 허용되지 않은 문자열이나 문자가 포함된 경우에는 에러로 처리한다.

- SQL 서버의 에러 메시지를 사용자에게 보여주지 않도록 설정한다. 공격자는 리턴되는 에러 메시지에 대한 분석을 통하여 공격에 성공할 수 있는 SQL injection 스트링을 알아낼 수 있다. 따라서 SQL 서버의 에러 메시지를 외부에 제공하지 않도록 한다.

- 웹 애플리케이션이 사용하는 데이터베이스 사용자의 권한을 제한한다. 가능하면 일반 사용자 권한으로는 모든 서버 저장 프로시저에 접근하지 못하도록 하여, 웹 애플리케이션의 SQL Injection 취약점을 이용하여 데이터베이스 전체에 대한 제어권을 얻거나 운용중인 데이터베이스 서버에 대하여 접근하는 것을 방지해야 한다.

 

 

SQL Injection을 예방하기 위한 prepared statement 에 대하여 다음 물음에 답하시오.

(1) prepared statement 의 개념

(2) prepared statement가 SQL injection 공격을 막을 수 있는 이유

답:

(1) 최초에 한번 쿼리를 분석해 최적화 수행 후 메모리에 저장해 두고, 다음 요청 부터는 저장된 결과를 재사용하여 쿼리를 수행하는 방식이다. 성능 측면의 효율이 높고, SQL 인젝션 방지가 가능하다. 참고로 일반 statement 방식은 실행시마다 쿼리를 분석해 최적화 수행후 실행하는 방식이라 효율이 낮고 SQL Injection 공격에 취약함.

 

Statement를 사용하여 SELECT 쿼리를 입력했을 때에는 매번 parse부터 fetch까지 모든 과정을 수행한다. (HARD Parsing)

Prepared Statement를 사용하는 경우 parse과정을 최초 1번만 수행하고 이후는 생략할 수 있다. (Soft Parsing)

Parse 과정을 모두 거친 후에 생성된 결과는 메모리 어딘가에 저장 해두고 필요할 때마다 사용한다.

반복적으로 트리를 사용하기 위해서 자주 변경되는 부분을 변수로 선언하고 매번 다른 값을 대입(바인딩)하여 사용한다.

바인딩 데이터는 SQL문법이 아닌 내부의 인터프리터나 컴파일 언어로 처리하기 때문에 문법적인 의미를 가질 수 없다

따라서 바인딩 변수에 SQL공격 쿼리를 입력할지라도 의미있는 쿼리로 동작하지 않는 이유이다.

Prepared Statement에서 바인딩 변수를 사용하였을 때 쿼리의 문법 처리과정이 미리 선 수행되기 때문에 바인딩 데이터는 문법적인 의미를 가질 수 없다.

그래서 Prepared Statement를 사용하면 SQL 인젝션 공격에 안전하게 구현 할 수 있는 이유이다

 

(2) 사용자가 입력한 값이 SQL 명령의 일부가 아닌 매개 변수로 처리되기 때문에 SQL 인젝션 공격을 막을 수 있음.

예) statement 방식

String query = "INSERT into student VALUES('" + user + "')";

Statement stmt = conn.createStatement();

stmt.executeQuery(query);

user에 Robert');DROP table students;-- 값을 입력면 다음과 같이 SQL명령문의 일부로 처리되어 students 테이블이 drop되게 됨.

INSERT into student VALUES('Robert');DROP table students;--')

예) preparedstatement 방식

PreparedStatement stmt = conn.prepareStatement("INSERT into student VALUES(?)");

stmt.setString(1,user);

stmt.execute();

user에 Robert');DROP table students;-- 값을 입력하더라도 해당 값이 그대로 매개변수로 user 컬럼에 입력이 됨.

​* Prepared Statement 문에 대한 이해가 없으면, 답변하기 까다로운 문제 입니다. 교재에 있는 예문을 최대한 끄집어 내어, statement 방식과 비교를 통해 설명을 한다면 좀 더 효과적인 답변이 될 수 있습니다.

 

 


2017년 56번

저장 프로시저를 사용하는 경우 쿼리를 구성하는 변수를 매개변수로 전달하므로 응용프로그램에서 AD-HOC 쿼리를 생성하는 것 보다 안전하다. 그래서 사용을 권장한다.

 


2017년 118번

정답 : 1번