SQL Injection

웹 사이트의 보안상 허점을 이용해 특정 SQL 쿼리문을 전송하여
공격자가 원하는 데이터베이스의 중요한 정보를 가져오는 해킹 기법이다.

대부분 클라이언트가 입력한 데이터를 제대로 필터링하지 못하는 경우에 발생한다.

공격이 쉬운 난이도에 비해 피해가 상당하기 때문에
보안 위협 1순위로 불릴만큼 중요한 기법이다.

 

 

 

 

간략한 공격 시나리오


예를 들어 회원이 자신의 일련번호를 조회할 수 있는 상황이 있다고 가정하자.

기본적인 SQL 진행은 클라이언트가 일련번호 조회를 클릭하여 웹서버에 이름이 들어가고 DB에 입력한 값이 있는지 확인 후 존재한다면 번호 DB를 출력해준다.

 

예를 들어 번호 조회를 클릭하면 url이 http://numbersearch.com/mysearch?=ohyaelim 이 된다고 가정하자.

그럼 공격자의 조회는 http://numbersearch.com/mysearch?=blackhat  에서 탈취하고 싶은 정보의 유저인 ohyaelim으로 변경해줘야하는데, 그냥 변경하는 것으로는 현재 로그인 된 자신과는 다르기 때문에 웹서버에서 인정하지 않는다. 

 

그러므로 특정 쿼리문을 넣어준다. 'ohyaelim' or '1' = '1' 과 같이 넣어부념 1과 1은 같다라는 구문이 참이므로 결과를 출력해준다.

 

이러한 SQL Injection의 공격 범위는 매우 다양하다.

bypass
data access
content change
db delete

 

 

 

 

 

공격 종류 및 방법


Error based SQL Injection

- 논리적 에러를 이용한 SQL Injection

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

앞서 살펴봤던 공격 시나리오가 여기에 해당된다. 

 

select * from client where name='ohyaelim' and password='1122'

 

가 올바른 로그인의 예라면 

 

select * from client where name='ohyaelim' and password=' or '1'='1

 

와 같이 작성해 or 앞의 값과 뒤에 값 중 하나라도 참이면 참이므로 이 구문 자체가 참으로 인식되어 로그인에 성공하게 된다.

 

 

 

UNION based SQL Injection = UNION

- 명령어를 이용한 SQL Injection

SQL UNION이란, 여러개의 SQL문을 합쳐 하나의 SQL문으로 만들어주는 방법이다. 
쿼리를 날리기에 앞서 사전 조건이 필요하다. Union 하는 두 테이블의 컬럼 수가 같아야 하고 데이터 형이 같아야 한다.

UNION과 UNION ALL로 나뉘는데 중복 값을 제외 하고 안하고의 차이다. 

UNION - 중복 값을 제외한다.

UNION ALL - 중복 값을 제외하지 않고 전체를 합친다.

 

입력값을 title  contents 컬럼의 데이터랑 비교한 뒤 비슷한 글자가 있는 게시글을 출력한다.

여기서 입력값으로 Union 키워드와 함께 컬럼 수를 맞춰서 SELECT 구문을 넣어주게 되면 두 쿼리문이 합쳐서서 하나의 테이블로 보여지게 된다.

현재 인젝션 한 구문은 사용자의 id passwd를 요청하는 쿼리문으로 인젝션이 성공하게 되면, 사용자의 개인정보가 게시글과 함께 화면에 보여지게 된다.

 

( * 물론 패스워드를 평문으로 데이터베이스에 저장하지는 않겠지만 인젝션이 가능하다는 점에서 이미 그 이상의 보안위험에 노출되어 있습니다. 이 공격도 역시 입력값에 대한 검증이 없기 때문에 발생하게 되었다. )

 

 

 

 

Blind SQL Injection 

- Boolean based Blind SQL Injection

Blind SQL Injection은 데이터베이스로부터 특정한 값이나 데이터를 전달받지 않고, 단순히 참과 거짓의 정보만 알 수 있을 때 사용한다. 로그인 폼에 SQL Injection이 가능하다고 가정 했을 때, 서버가 응답하는 로그인 성공과 로그인 실패 메시지를 이용하여, DB의 테이블 정보 등을 추출해 낼 수 있다.

 

위 사진과 같은 예시를 살펴보면 limit 키워드를 통해 하나의 테이블만 조회하고, SUBSTR 함수로 첫 글자만, 그리고 마지막으로 ASCII 를 통해서 ascii 값으로 변환해준다. 만약에 조회되는 테이블 명이 Users 라면 ‘U’ 자가 ascii 값으로 조회가 될 것이고, 뒤의 100 이라는 숫자 값과 비교를 하게 된다. 거짓이면 로그인 실패가 될 것이고, 참이 될 때까지 뒤의 100이라는 숫자를 변경해 가면서 비교를 하면 된다.  공격자는 이 프로세스를 자동화 스크립트를 통하여 단기간 내에 테이블 명을 알아 낼 수 있다.

 

한글자씩 끊어온 값을 아스키코드로 변환시키고 임의의 숫자와 비교하여 참과 거짓을 비교하는 과정을 거쳐가며 계속 질의를 보내어 일치하는 아스키코드를 찾아내는데 이러한 과정을 반복하여 결과들을 조합하여 원하는 정보를 얻어냄으로써 공격을 이루어지게 한다. 많은 비교 과정을 요하므로 악의적 목적을 가진 크래커들은 자동화된 툴을 사용하여 공격한다. 

 

 

Blind SQL Injection

- Time based SQL

Time Based SQL Injection 도 마찬가지로 서버로부터 특정한 응답 대신에 참 혹은 거짓의 응답을 통해서 데이터베이스의 정보를 유추하는 기법이다. 사용되는 함수는 MySQL 기준으로 SLEEP  BENCHMARK 이다.

 

위의 그림의 예시에서 로그인 폼에 주입이 되었으며 임의로 abc123 이라는 계정을 생성해 두었는데 악의적인 사용자가 abc123’ OR (LENGTH(DATABASE())=1 AND SLEEP(2)) – 이라는 구문을 주입한 상황이다. 

 주입된 구문에서, LENGTH(DATABASE()) = 1 가 참이면 SLEEP(2) 가 동작하고, 거짓이면 동작하지 않는다. 이를 통해서 숫자 1 부분을 조작하여 데이터베이스의 길이를 알아 낼 수 있다. 만약에 SLEEP 이라는 단어가 치환처리 되어있다면, 또 다른 방법으로 BENCHMARK  WAIT 함수를 사용 할 수 있다

BENCHMARK 는
BENCHMARK(1000000,AES_ENCRYPT('hello','goodbye'));
이런 식으로 사용하고 이 구문을 실행 하면 약 4.74초가 걸린다. 

 

 

Stored Procedure SQL Injection

- 저장된 프로시저에서의 SQL Injection

stored procedure는 일련의 쿼리들을 모아 하나의 함수처럼 사용하기 위한것이다.

공격에 사용되는 대표적인 저장 프로시저는 MS-SQL 에 있는 xp_cmdshell로 윈도우 명령어를 사용할 수 있게 된다. , 공격자가 시스템 권한을 획득 해야 하므로 공격난이도가 높으나 공격에 성공한다면, 서버에 직접적인 피해를 입힐 수 있는 공격이다.

 

 

Mass SQL Injection

- 다량의 SQL Injection 공격

 2008년에 처음 발견된 공격기법이다.

기존 SQL Injection 과 달리 한번의 공격으로 다량의 데이터베이스가 조작되어 큰 피해를 입히는 것을 의미한다. 보통 MS-SQL을 사용하는 ASP 기반 웹 애플리케이션에서 많이 사용되며, 쿼리문은 HEX 인코딩 방식으로 인코딩 하여 공격한다. 보통 데이터베이스 값을 변조하여 데이터베이스에 악성스크립트를 삽입하고, 사용자들이 변조된 사이트에 접속 시 좀비PC로 감염되게 하는데 이렇게 감염된 좀비 PC들은 DDoS 공격에 사용됩니다.

 

 

 

 

대응방안


  • 입력 값에 대한 검증 
  • Prepared Statement 구문 사용
  • Error Message 노출 금지
  • 웹 방화벽 사용

 

입력 값에 대한 검증

SQL Injection 에서 사용되는 기법과 키워드는 엄청나게 많습니다. 사용자의 입력 값에 대한 검증이 필요하다. 서버 단에서 화이트리스트 기반으로 검증해야 한다. 블랙리스트 기반으로 검증하게 되면 수많은 차단리스트를 등록해야 하고, 하나라도 빠지면 공격에 성공하게 되기 때문이다. 공백으로 치환하는 방법도 많이 쓰이는데, 이 방법도 취약한 방법이다. 예를 들어 공격자가 SESELECTLECT 라고 입력 시 중간의 SELECT가 공백으로 치환이 되면 SELECT 라는 키워드가 완성되게 된다. 공백 대신 공격 키워드와는 의미 없는 단어로 치환되어야 한다.

 

 

Prepared Statement 구문사용

 Prepared Statement 구문을 사용하게 되면, 사용자의 입력 값이 데이터베이스의 파라미터로 들어가기 전에DBMS가 미리 컴파일 하여 실행하지 않고 대기하는데 그 후 사용자의 입력 값을 문자열로 인식하게 하여 공격쿼리가 들어간다고 하더라도, 사용자의 입력은 이미 의미 없는 단순 문자열 이기 때문에 전체 쿼리문도 공격자의 의도대로 작동하지 않는다.

 

 

Error Message 노출 금지

공격자가 SQL Injection을 수행하기 위해서는 데이터베이스의 정보(테이블명, 컬럼명 등)가 필요하다. 데이터베이스 에러 발생 시 따로 처리를 해주지 않았다면, 에러가 발생한 쿼리문과 함께 에러에 관한 내용을 반환헤 주는데 여기서 테이블명 및 컬럼명 그리고 쿼리문이 노출이 될 수 있기 때문에, 데이터 베이스에 대한 오류발생 시 사용자에게 보여줄 수 있는 페이지를 제작 혹은 메시지박스를 띄우도록 하여야 한다.

 

웹 방화벽 사용

웹 공격 방어에 특화되어있는 웹 방화벽을 사용하는 것도 하나의 방법. 웹 방화벽은 소프트웨어 형, 하드웨어 형, 프록시 형 이렇게 세가지 종류로 나눌 수 있는데 소프트웨어 형은 서버 내에 직접 설치하는 방법이고, 하드웨어 형은 네트워크 상에서 서버 앞 단에 직접 하드웨어 장비로 구성하는 것이며 마지막으로 프록시 형은 DNS 서버 주소를 웹 방화벽으로 바꾸고 서버로 가는 트래픽이 웹 방화벽을 먼저 거치도록 하는 방법이다.

 

 

 

 

 


참고

link1 link2

+ Recent posts