SQL Injection이란?
SQL Injection은 웹의 취약점을 이용한 해킹기법 입니다.
SQL = 데이터베이스에 명령을 내리는 언어
Injection = 주입
그래서 SQL Injection은 데이터베이스에 명령을 내리는 언어를 악의적으로 주입해서 실행시켜 데이터베이스가 비정상적인 동작을 하도록 만드는 것을 의미합니다.
SQL Injection의 원리와 여러 공격방식
그럼 SQL인젝션은 어떤 방식으로 어떤 구조로 주입이 이뤄질까요?
아래 사진을 보겠습니다.
이 사진은 로그인 페이지에서 아이디 비밀번호를 입력하고 로그인버튼을 눌렀을 때 실행과정이 그려져 있는데 위쪽에는 SQL언어가 자리잡고 있습니다. 저렇게 아이디와 비밀번호에 입력한 문자열값이 그대로 입력되게 됩니다.
만약 저대로 AAAA' -- 문자를 아이디 값에 입력하면 어떻게 될까요?
그렇다면 아래 사진과 같은 상태가 됩니다.
SQL문법에서 -- 이것 즉 하이픈두개와 스페이스는 뒷 내용한줄을 모두 주석처리해달라는 뜻입니다.
이런식으로 입력이 처리되면 유저의 아이디 정보만 알고있어도 해당유저의 계정으로 로그인이 가능해집니다.
아주 치명적인 보안이슈입니다. 이 방법 외에도 여러 SQL문을 입력하면 여러가지 공격이 가능해집니다. 예를들어
이런 공격
이 코드에서는 1=1 or요청으로 무조건 참이 나오기 때문에 테이블내 모든 컬럼중 가장 윗 값을 가져와서 로그인을 시켜줍니다.
그리고 가장 윗 값은 어드민이나 테스트용 계정인 경우가 많습니다. 해커한테 어드민 계정접속이 가능해진다니...
그 외엔 이렇게 테이블명만 알아내면 해당 테이블을 통채로 날려버릴 수도 있는 무서운 공격방식 입니다.
이렇게 로그인 화면에서 이뤄지는 주입 외에도 만약 쿼리스트링으로 값을 받고 있는 SQL Injection 방어가 안 되어있는 사이트가 있다면
UNION SELECT라는 공격 방식도 유효해 집니다.
이 방식이 UNION SELECT라는 공격방식인데, UNION이 나오기 전까지가 원래 서버가 쿼리스트링으로 DB에 요청을 보내던 정상적인 로직 입니다. 번호와 맞는 컬럼의 정보를 뱉어주고 있는 모습인데요. 그 뒤의 UNION은 SELECT문 뒤에 이어서 SELECT문 요청을 하나 더 보내겠다는 요청입니다.
위 사진의 요청은 컬럼 갯수를 알아내서 해당 테이블의 test라는 uname값을 가진 컬럼의 모든 정보를 빼내오는 코드입니다.
SQL Injection 방어법/예방법
하지만 이렇게 강력하고 치명적인데 반해 방어법은 간단한데요.
첫째로 간단하게 해야할 것은 서버의 에러메세지를 클라이언트에 노출시키는 상황을 없애는 것입니다.
이러한 에러메세지를 노출시키는 것은 해커에게 아주 좋은 정보가 되어 취약점이 드러날 수 있습니다.
두번째로
이렇게 입력값 제한을 걸어 특수문자를 차단해버리는 방법 입니다.
아니면 받아온 값을 서버측에서
문자를 필터링해서 새로운 문자열로 초기화 해주는 방법도 예방법이 되겠습니다.
마지막으로 ORM 즉 JPA나 QueryDSL같은 SQL쿼리문 작성을 보조해주는 라이브러리를 사용하는 방법입니다.
위에서 언급한 라이브러리들은 모두 Perepared Statement 방법을 통해 들어오는 값들이 파라미터 바인딩 되므로 SQL Injection에 안전할 수 있습니다.
파라미터 바인딩이 일어나는 과정을 보면
SQL문 ? 자리에 들어온 값을 파라미터 바인딩 해주고 있음을 알 수 있습니다.
setString 내부로 들어가면
이렇게 문자를 검사해서 새로운 문자로 만들어서 Escape해주고 있는 것을 볼 수 있습니다.
JPA 요청을 보면
이렇게 ?가 들어가 있는걸 볼 수 있는데 파라미터 바인딩이 제대로 동작하고 있는것을 알 수 있습니다.