[DB] SQL Injection이란?

giggle·2023년 8월 13일
0

📌 SQL Injection이란 무엇일까?

해커에 의해 조작된 SQL 쿼리문이 데이터베이스에 그대로 전달되어 비정상적 명령을 실행시키는 공격 기법

SQL Injection은 사용자의 입력값이 서버측에서 코드로 실행되는 '코드 인젝션' 공격 기법 중 하나이며, 서버의 데이터베이스를 대상으로 하는 공격입니다.

사용자 입력값을 제대로 필터링, 이스케이프 하지 않아 발생합니다. 2017년 3월 발생한 "여기어때" 고객 정보 및 고객 투숙 정보 노출 사고, 2015년 "뽐뿌" 개인정보 노출 사고가 SQL Injection 공격이 원인이었습니다.

공격의 핵심은 클라이언트 측에서 SQL 쿼리에 신뢰할 수 없는 데이터가 입력되었을 때, 데이터가 쿼리 로직의 일부로 해석되어 DB에서 실행될 때 발생합니다.

📌 공격 목적?

SQL Injection 공격 목적은 다음과 같다. SQL 구문에 추가 절을 삽입하게 되면 쿼리의 의미가 변경되고 의도하지 않은 데이터의 유출, 변조가 가능합니다.

  1. 정보 유출(Information Leakage)

  2. 저장된 데이터 유출 및 조작(Disclosure & Manipulation of stored Data)

  3. 원격 코드 실행(Remote Code Excution)

    • 일부 데이터베이스의 경우 확장 프로시저를 이용하여 원격으로 시스템 명령의 실행이 가능합니다.
    • 시스템 명령의 실행은 원격 자원 접근 및 데이터 유출, 삭제가 가능합니다.
  4. 인증 우회(Bypassing authorisation controls)

    • 공격의 대표적인 경우로 로그인 폼 등에서 발생합니다.
    • 상위 권한을 가진 사용자의 권한으로 인증 절차를 우회하여 로그인 정보 없이 로그인할 수 있습니다.

📌 공격 방법

1. 인증 우회

보통 로그인을 할 때, 아이디와 비밀번호를 input 창에 입력하게 된다. 쉽게 이해하기 위해 가벼운 예를 들어보자. 아이디가 abc, 비밀번호가 만약 1234일 때 쿼리는 아래와 같은 방식으로 전송될 것입니다.

SELECT * FROM USER WHERE ID = "abc" AND PASSWORD = "1234";

SQL Injection으로 공격할 때, input 창에 비밀번호를 입력함과 동시에 다른 쿼리문을 함께 입력하는 것입니다.

1234; DELETE * USER FROM ID = "1";

보안이 완벽하지 않은 경우, 이처럼 비밀번호가 아이디와 일치해서 True가 되고 뒤에 작성한 DELETE 문도 데이터베이스에 영향을 줄 수도 있게 되는 치명적인 상황입니다.

이 밖에도 기본 쿼리문의 WHERE 절에 OR문을 추가하여 '1' = '1'과 같은 true문을 작성하여 무조건 적용되도록 수정한 뒤 DB를 마음대로 조작할 수도 있습니다.

2. 데이터 노출

시스템에서 발생하는 에러 메시지를 이용해 공격하는 방법입니다. 보통 에러는 개발자가 버그를 수정하는 면에서 도움을 받을 수 있는 존재입니다. 해커들은 이를 역이용해 악의적인 구문을 삽입하여 에러를 유발시킵니다.

즉 예를 들면, 해커는 GET 방식으로 동작하는 URL 쿼리 스트링을 추가하여 에러를 발생시킨다. 이에 해당하는 오류가 발생하면, 이를 통해 해당 웹앱의 데이터베이스 구조를 유추할 수 있고 해킹에 활용합니다.

📌 방어 방법

1. 특수문자 검사 및 필터링

  • 입력값을 받을 때 미리 설정한 특수문자를 필터링하여 검증하는 방법입니다. 이를 통해 악의적인 SQL 쿼리를 포함한 입력값이 들어오는 것을 막을 수 있습니다.
  • 예를 들어, 로그인 전에 사용자 입력값을 검증하는 로직을 추가하여 허용되지 않는 특수문자가 들어왔을 때 요청을 거부합니다.

2. SQL 서버 오류 메시지 감추기

  • 데이터베이스 테이블에 직접 접근하는 대신, 뷰(View)를 활용하여 접근 권한을 조절할 수 있습니다.
  • 일반 사용자는 뷰를 통해서만 데이터에 접근할 수 있고, 원본 테이블에 접근할 수 없도록 설정합니다.
  • 이렇게 하면 데이터베이스 오류 메시지를 감추거나 정보 노출을 최소화할 수 있습니다.

3. Prepared Statement 사용

  • Prepared Statement는 SQL 쿼리와 사용자 입력값을 분리하여 쿼리문에 직접 값을 삽입하는 것이 아니라 매개 변수로 처리합니다.
  • 이 때문에 사용자 입력값이 자동으로 이스케이프(Escape)되어 SQL Injection 공격을 방지할 수 있습니다.
  • 사용자 입력값을 직접 삽입하는 대신, 쿼리문에는 물음표(?)로 표시하고, 이후에 매개 변수를 설정하여 실행합니다.

4. ORM 사용


참고


피드백 및 개선점은 댓글을 통해 알려주세요😊

profile
배움을 글로 기록하는 개발자가 되겠습니다.

0개의 댓글