SQL Injection

Cura·2023년 12월 16일
0

기타 정보

목록 보기
2/6

SQL Injection 이란?

SQL Injection 공격은 사용자의 입력을 SQL문과 연결하여 웹 어플리케이션의 취약성을 악용합니다.
-IBM Docs

  • SQL Injection은 사용자의 악의적인 입력으로 인해 본래 프로그래머가 의도한 SQL문이 아닌 악의적SQL문이 동작하는 것을 의미합니다.
  • 이는 외부 입력값을 내부 처리에 사용하면서 SQL처리를 조작하는 문자열포함 여부를 확인하지 않고 사용할 때 나타납니다.

공격 종류 및 방법

1. Error Based SQL Injection

  • 입력값에 오류를 유발하는 값을 전달, 출력되는 에러의 내용을 보고 필요한 정보를 수집, 구체적인 공격 계획을 수립합니다.
  • 일반적으로 '(홑 따옴표) 또는 "(쌍 따옴표)를 사용하여 에러를 유발하고 이후 or 1 = 1과 같은 항상 참이되는 값을 입력하여 공격을 이어갑니다

- 회원정보 조회 공격 예시

  • Id가 123이고 Password가 456인 회원의 정보를 조회할 때
select * form member where id = 123 and password = 456
  • 오류를 발생하는 값을 전달하여 오류 메세지 확인
select * form member where id = 123' and password = 456
  • 이후 항상 참이 되는 입력을 통해 password 없이 회원정보를 조회
select * form member where id = 123 or 1 = 1 -- password = 890
  • password를 모르더라도 password확인 구문이 주석처리되어 사용자 정보를 확인 가능하게 됨

2. Union base SQL Injection

  • UNION 문구를 이용하여 공격자가 알고자 하는 정보 요청 쿼리문을 결합하여 실행합니다.
  • 원래 제공되는 정보와 함께 공격자가 요구하는 데이터가 제공됩니다
  • 공격자가 알고자 하는 테이블과 컬럼의 이름을 알아야 합니다.

- 게시판 검색 공격 예시

  • 게시판 검색을 할때 Title name을 받아 검색을 한다 할때
select * from Board where title = 'Title name' 
  • user 테이블에 id, pw, age를 조회하도록 입력
select * from Board where title = 'a' UNION select id, pw, age form user --' 
  • UNION 을 이용하여 3개 정보를 검색하고 혹시 모를 에러를 방지하기 위해 -- 으로 뒷 구문 주석처리
  • 해당 공격을 통해 사용자의 개인정보를 게시글과 함께 볼 수 있게 된다.

3. Stored Procedure call SQL Injection

  • 데이터베이스에서 제공하는 Stored Procedure를 실행하는 구문을 입력값으로 전송하여 실행합니다.
  • 데이터베이스에 직접적은 제어권을 탈취하여 조작하는것이 가능해집니다.

- Stored Procedure 공격 예시

select * from member where id = 123 ; exec xp_cmdshell 'cmd.exe /c dir'
  • ; 은 쿼리문의 종결을 의미. exec 이후로 Stored Procedure 실행
  • xp_cmdshell - MS-SQL에서 제공하는 Stored Procedure로 매개변수로 전달된 값을 DBMS 쉘에서 실행하고 결과를 반환
  • 'cmd.exe /c dir' - 현재 디렉토리의 내용을 반환

4. Blind SQL Injection

  • 쿼리 실행 결과에 따라 서버에서 전송하는 에러 메세지가 출력되는 경우 실행할 수 있습니다.
  • 공격자가 원하는 내용을 조회하는 쿼리를 작성해서 전송하고 쿼리가 참이면 페이지가 정상적으로 출력되고, 그렇지 않은 경우 에러메세지가 출력되는 것으로 전송한 내용의 참 거짓을 판별합니다.

- Boolean 기반 공격 예시

  • 계정 조회 페이지 기본 쿼리문
select * from users where id = 'userId' and pw = 'userPw'
  • asdf 라는 유저가 있을 때 info 테이블에서 age값이 20 초과인지 확인하기 위한 쿼리문 작성
select * from users where id = 'asdf' and (select age from info where  uid = 'asdf')  > 20 --' and pw = 'userPw'
  • uid가 asdf인 info테이블의 age가 20 초과이면 정상 조회
  • uid가 asdf인 info테이블의 age가 20 이하이면 조회 실패

안전한 형태의 구문 작성 요령

1. 입력값 검증

  • 사용자의 입력값을 검증 후 사용합니다.
    • ' , " , # , -- , = 등의 특수문자를 필터링
    • 입력값의 길이를 제한

2. 구조화된 쿼리문을 이용

  • 쿼리문의 구조를 정의하고 정의 쿼리문에 값을 바인딩 하는 형식으로 실행합니다
    • PreparedStatement 객체를 사용

3. iBatis, myBatis와 같은 프레임워크를 사용하는 경우 외부 입력값을 쿼리맵에 적용할 때 반드시 # 기호를 사용한다.

  • $기호가 아닌 # 기호를 사용합니다

4. 오류메세지에 시스템 중요 정보가 포함되지 않도록 한다.

  • 시스템 오류 발생 시 오류에 대한 구체적인 내용이 아닌 일반화된 메세지가 출력되도록 합니다.
  • 오류는 로그로 관리하고 외부에 노출되지 않도록 하여 추가 공격의 단서가 되지 않도록 합니다.

5. 어플리케이션에서 사용하는 DB 사용자 권한을 최소한으로 한다.

  • 시스템 테이블, 뷰, Stored Procedure에 접근할 수 없도록 제한합니다.
  • 시스템 관리에 관한 권한을 제한하여 UNION Based SQL Injection과 같은 공격을 방지할 수 있습니다.

1, 2, 3번은 SQL Injection을 직접적으로 방지하고

4, 5번은 공격이 심화, 확산되는 것을 방지합니다.

profile
우리는 울지 않는 부엉이요, 발자국 없는 범이다.

0개의 댓글