[CS] SQL Injection

히수·2023년 3월 29일
1

CS

목록 보기
6/13

SQL Injection

해커에 의해 조작된 SQL 쿼리문이 데이터베이스에 그대로 전달되어 비정상적 명령을 실행시키는 공격 기법, 공격이 비교적 쉬운 편이고 공격에 성공할 경우 큰 피해를 입힐 수 있는 공격이다.

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




🟠 공격 목적

  1. 저장된 데이터 유출 및 조작

  2. 정보 유출

  3. 원격 코드 실행

  4. 인증 우회




🔵 공격 종류 및 방법

  1. Error based SQL Injection
    논리적 에러를 이용한 SQL Injection

논리적 에러를 이용한 SQL Injection은 가장 많이 쓰이고, 대중적인 공격 기법이다.

공격자가 동일한 통신 구간(ex : 브라우저)에서 공격을 시도하고 결과를 얻을 수 있다.

사용자가 Parasite를 검색어로 하여 결과를 출력했을때
WHERE 절 내에 바로 삽입되는것을 확인하고 공격을 시도한다.

DB에 어떤 데이터가 있는지 모르는 상태에서 WHERE 절을 항상 참으로 만족시키는 OR '1'='1'-- 구문을 삽입한다

DB는 쿼리로 실행하여 모든 데이터가 출력되는 것을 확인할 수 있다.

그리고 -- 를 넣어줌으로 뒤의 구문을 모두 주석 처리해버린다.

SELECT * 
FROM USER
WHERE username='username' AND password='password'

이런 형태의 구문에 공격을 시도하면

SELECT * 
FROM USER
WHERE username='username' OR 1=1 -- 'AND password='password'

이렇게 주석처리를 통해 모두 의미없는 문자열로 만들어서 공격한다.

매우 간단한 구문이지만, 결론적으로 Users 테이블에 있는 모든 정보를 조회할 수 있게 되고, 보통은 관리자 계정을 맨 처음 만들기 때문에 관리자 계정에 로그인 할 수 있게 된다.

관리자의 권한을 이용해 또 다른 2차피해를 발생 시킬 수 있다.


  1. Union based SQL Injection
    Union 명령어를 이용한 SQL Injection

SQL 에서 Union 은 두 개의 쿼리문을 통합해서 하나의 테이블로 보여주게 한다. 정상적인 쿼리문에 Union 을 사용하여 인젝션에 성공하면, 원하는 쿼리문을 실행할 수 있게 된다.

Union Injection을 성공하기 위해서는 두 가지의 조건이 있다.

두 테이블의 집합을 결합하기 때문에 Union 하는 두 테이블의 컬럼 수가 같아야 하고, 데이터 유형이 같아야 한다.


  1. Blind SQL Injection
    Boolean based SQL

Blind SQL Injection은 데이터베이스로부터 특정한 값이나 데이터를 전달받지 않고, 단순히 참과 거짓의 정보만 알 수 있을 때 사용한다.

로그인 폼에 SQL Injection이 가능하다고 가정 했을 때, 서버가 응답하는 로그인 성공과 로그인 실패 메시지를 이용하여, DB의 테이블 정보를 추출해 낼 수 있다.

임의로 가입한 abc123이라는 아이디와 함께 뒤의 구문을 주입한다. 해당 구문은 테이블 명을 조회하는 구문으로 limit 키워드를 통해 하나의 테이블만 조회하고, SUBSTR 함수로 첫 글자만, ASCII를 통해서 ascii 값으로 변환한다. 만약 조회되는 테이블 명이 Users 라면 'U' 자가 ascii 값으로 조회가 될 것이고, 뒤의 100이라는 숫자 값과 비교하게 된다.

거짓이면 로그인 실패가 될 것이고, 참이 될 때까지 뒤의 100이라는 숫자를 변경해 가면서 비교하면 된다. 공격자는 이 프로세스를 자동화 스크립트로 만들어 단기간 내에 테이블 명을 알아낼 수 있다.


  1. Blind SQL Injection
    Time based SQL

Blind와 마찬가지로 에러가 발생되지 않는 조건에서 사용하며, 참 혹은 거짓이라는 결과값이 나오지 않으므로 시간을 재는 것이다.

궁극적으로는 DB 구조를 파악하기 위함이다.

Time based SQL Injection을 사용하여 현재 사용하고 있는 데이터베이스의 길이를 알아내는 방법이다. abc123’ OR (LENGTH(DATABASE())=1 AND SLEEP(2)) – 이라는 구문을 주입하였을때 여기서 LENGTH 함수는 문자열의 길이를 반환하고, DATABASE 함수는 데이터베이스의 이름을 반환한다.

주입된 구문에서, LENGTH(DATABASE()) = 1 가 참이면 SLEEP(2) 가 동작하고, 거짓이면 동작하지 않는다. 이를 통해서 숫자 1 부분을 조작하여 데이터베이스의 길이를 알아 낼 수 있다.



🟢 대응방안

1. 블랙리스트 & 화이트 리스트 기반 필터링

블랙리스트는 SQL 쿼리의 구조를 변경하는 특수문자, SQL 예약어 등을 미리 등록해놓고 입력을 제한하는 방식이다.

해당 문자가 입력되었을 때 에러 메시지를 반환하거나, 미리 준비한 문자열로 치환하는 방법이 있다.

(특수문자) ' , " , = , & , | , ! , ( , ) , { , } , $ , % , @ , #, -- 등
(예 약 어) UNION, GROUP BY, IF, COLUMN, END, INSTANCE 등
(함 수 명) DATABASE(), CONCAT(), COUNT(), LOWER() 등

2. 오류 메시지 출력 제한

DB 오류 메시지의 노출은 공격자에게 2차 공격을 할 수 있는 정보를 제공하므로 오류 메시지의 출력을 금지한다.

DB 버전정보, DB 종류 등을 포함하여 로그인 시 ID, Password 오류 여부도 불필요한 경우 노출하지 않는다.

3. DB 보안 적용

관리자 DB 계정과 웹애플리케이션 운영 계정의 권한을 분리하여 운영한다. DDL, DML 등 사용하는 구문 별 계정을 구분하여 운영한다.

이외에도 웹 방화벽 사용, 주기적 로그 점검, 취약점 점검 등을 적용할 수 있다.



참고포스팅
링크
링크

profile
🔥

3개의 댓글

comment-user-thumbnail
2023년 3월 30일

재미있는 주제로 가독성있게 글이 쓰여있어서 끝까지 풀집중으로 읽었네요

답글 달기
comment-user-thumbnail
2023년 3월 30일

재밌게 잘 읽었습니다!

답글 달기
comment-user-thumbnail
2023년 3월 30일

벨로그 마크업 활용력이 더 좋아져서 글 읽는게 한결 더 수월했습니다.

답글 달기