SQL Injection & IDS

Casper·2023년 8월 9일
0
post-thumbnail

(간단한 개념 숙지를 위한 과거 포스팅 내용입니다.)

  • SQL Injection?
    응용 프로그램 보안 상의 허점을 의도적으로 이용해, 데이터를 변경, 추가하는 등 악의적인 SQL문을 실행되게 함으로써 데이터베이스를 비정상적으로 조작하는 코드 인젝션 공격 방법입니다.

  • 실습 환경

    • Web Server : Apache2
    • DB : mysql
    • 공격자 IP : 192.168.1.129
    • 희생자 IP : 192.168.1.130

공격자 브라우저에서 희생자 IP로 접속한 후 

Username : foo' or 1#

와 Password를 아무거나 입력해주면 로그인이 성공하는 것을 확인할 수 있습니다.
전달되는 쿼리는 다음과 같습니다.

SELECT * FROM users WHERE username='foo' or 1#' AND password='1234'

->mysql에서 #은 주석을 뜻하므로 foo' or 1 뒤로 주석처리가 되고 where절은 참이 되어 로그인에 성공할 수 있습니다.

이 후 게시판 글을 확인해보면 view.php의 id매개변수로 DB에서 데이터를 불러오는 것을 추측할 수 있습니다.

이를 사용하여 URL에

http://192.168.1.130/view.php?id=1 union select 1#

을 입력한다면 union으로 인한 제약으로 연결된 두 개의 select문의 필드 수가 같아야 하지만
select 1만으로는 맞지 않아 Invalid access page라는 응답이 오게 됩니다.

http://192.168.1.130/view.php?id=3 union select 1,2,3,4,5,6#

하나씩 증가시켜보다 위와 같이 입력하게 된다면
앞의 select문과 필드 수가 일치하게 되어 참이 되므로 결과가 나오게 되고
공격자는 이로 인해 데이터를 저장하는 테이블의 필드 수가 6개임을 알 수 있습니다.

희생자 PC에서 mysql에 접속하여 필드 수를 확인해보면 일치함을 알 수 있다

또한 'show databases;'를 통해 메타 데이터가 저장되어있는 DB인 information_schema를 확인할 수 있습니다.

공격자 브라우저에서

http://192.168.1.130/view.php?id=-1 UNION SELECT 1,(SELECT table_name FROM information_schema.tables LIMIT 0,1), 3,4,5,6#

을 입력합니다.
id=-1뿐이라면 invalid access page라고 경고가 뜨겠지만
필드 수를 맞추기 위한 1,3,4,5,6과 함께 select문으로 인해 데이터가 출력되게 됩니다.
LIMIT 0,1으로 인해 tables 테이블에서 0번째부터 1개의 table_name을 board의 두번째 필드로 출력해줍니다.

LIMIT을 1,1로 변경해서 다시 입력한다면 다음 table_name을 얻을 수 있으며 이처럼 모든 테이블의 이름을 알 수 있습니다.

86번째의 user 테이블 (LIMIT 81,1)

http://192.168.1.130/view.php?id=-1 UNION SELECT 1,(SELECT column_name FROM information_schema.column WHERE table_name = "board" LIMIT 0,1),3,4,5,6#

을 입력하면 board테이블의 0번째 필드를 출력할 수 있습니다.

공격자 브라우저에서 메인페이지로 돌아가 

username : ' or (SELECT length(username) FROM users LIMIT 0,1) = 1#

을 입력한다면 위와 같이 경고창이 뜨게됩니다.

이번에는

username : ' or (SELECT length(username) FROM users LIMIT 0,1) = 8#

을 입력한다면 users의 0번째 username의 길이는 8(humanist)이므로 length(username)이 참이 되어 로그인에 성공하게 됩니다.
이같이 쿼리가 참,거짓인지 하나씩 시도하여 정보를 추출하는 방법을 Blind SQL INJECTION이라고 합니다.
이 Blind sql injection공격에 있어 중요한 함수 두 가지는 매개변수의 ASCII코드 값을 반환해주는

ascii(str) 함수와

문자열을 원하는 만큼 잘라내어 반환해주는

substr(str,pos,len)이 있습니다

공격자 PC에서

#sqlmap -u "http://192.168.1.130/view.php?id=1" -b

을 입력해주면 희생자의 DBMS 배너를 출력해주며 위와 같이 희생자 OS,웹 서버 버전, DBMS버전, 배너정보를 얻을 수 있습니다.

이번에는 희생자 PC에서 이를 탐지하기 위해

#vi /etc/snort/rules/local.rules

을 열고

alert tcp any any -> 192.168.1.130 80 (msg: "SQL INJECTION DETECTED";content:"select";nocase:content"from";nocase;content:"union";nocase;sid:1;)

을 입력해주어 SQL INJECTION탐지 정책을 만듭니다.

[CONTENT OPTION]

nocase : 대소문자 구분 안 함
offset : 검사 시작 지점의 절대 위치
depth : offset으로 시작된 검사의 종료 위치 지정 (검사 종료 절대 위치)
distance : 이전 패턴 검사가 종료된 지점을 기준으로 검사 시작 위치 지정 (검사  시작 상대 위치)
within : distance로 시작된 검사의 종료 위치 지정
rawbytes : 헥사코드 수준에서 검사
http_client_body : 패턴 검사 범위를 웹 요청 메시지 본문으로 제한
http_cookie : 패턴 검사 범위를 웹 요청 또는 응답 메시지 헤더 영역으로 제한
http_header : 패턴 검사 범위를 웹요청 또는 응답 메시지 헤더 영역으로 제한
http_method : **패턴 검사 범위를 웹요청 Method로 제한**
http_uri : **패턴 검사 범위를 웹요청 uri로 제한**
http_stat_code : **패턴 검사 범위를 웹응답 코드 번호 영역으로 제한**
http_stat_msg : **패턴 검사 범위를 웹응답 코드 메시지 영역으로 제한**
fast_pattern : content옵션이 두 개 이상 사용될 때 기본적으로 길이가 긴 문자열의 우선순위가 높으나, 해당 옵션을 이용해서 우선순위를 조정

#snort -q -A console -i eth0 -c /etc/snort/snort.conf

희생자 PC에서 위와 같이 SNORT정책을 활성화합니다.

공격자 PC에서 희생자 DB 'sample'에서 table 목록과 내용을 출력합니다.

sqlmap -u "http://192.168.1.130/view.php?id=1" -D sample --tabes --columns

공격자 pc에서 희생자의 db목록을 출력합니다.

sqlmap -u "http://192.168.1.130/view.php?id=1" --dbs --current-db

하지만 이제는 snort정책으로 인해 이러한 공격들이 위와 같이 모두 탐지되게 됩니다.

profile
Emotional Developer

0개의 댓글