2015년 7월 22일 수요일

Snort 분석(packet 발생량 기반 탐지)

문자열 패턴만 분석하니 지겨운 듯 해서 다른 걸 좀 해볼까 한다. Snort 룰은 크게 문자열 패턴 검사와 패킷 발생량 검사, 두가지로 나눌 수 있는데, 일반적으로 패턴 검사는 (아무나 읽지 못하게 하는) 기밀성과 (아무나 쓰지 못하게 하는) 무결성 침해 행위를, 발생량 검사는 (자원의 정상적 사용 가능 정도인) 가용성 침해 행위를 탐지하고자 한다.

출퇴근 시간의 도로에서 가용성 침해 사례를 쉽게 경험할 수 있다. 제아무리 넓은 도로도 이용 차량이 늘어나면 교통체증에 시달리기 마련인데, 바로 가용성에 침해를 받는 경우. 그렇기 때문에 차량 이용량은 교통체증의 경중, 즉 도로 가용성의 수준을 파악할 수 있는 중요한 척도가 된다.


  • 교통체증 사례에서 대역폭을 소진하는 DDoS 대응의 힌트를 얻을 수 있다. 도로가 막히면 차량이 막힌 구간을 다 통과할 때까지 정체는 풀리지 않는다. 당장 효과를 보는 방법은 도로를 넓히거나, 목적지까지 우회로를 만드는 것. 
  • 마찬가지로 보안장비에서 공격자를 차단하고, 패킷을 Drop 해봐야 대역폭 점유가 풀리지 않는 이상 무조건 공격자의 승리다. 그나마 피해를 줄이는 방법은 잽싸게 다른 회선으로 갈아타는 방법뿐이다.

한정된 트래픽 대역폭을 이용하는 패킷의 발생량 역시 트래픽의 가용성을 파악할 수 있는 척도가 된다. 그렇다면 패킷 발생량을 측정하는 룰은 어떻게 만들까? 다음 룰은 정해진 시간 동안 특정 물리적 특성을 지닌 패킷이 정해진 양만큼 동일 목적지로 들어오는 경우를 탐지하고자 한다.

alert tcp any any -> any any 
(msg:"tcp syn flooding"; 
flags:S; <- TCP Syn flag 패킷만
threshold:type threshold, track by_dst, count 10000, seconds 2; 
  • 2초간 10,000개의 패킷이 동일 목적지로 들어오면 탐지
sid:1000000;)

Snort는 'threshold'란 옵션을 이용해서 패킷 발생량을 검사하는데, 세부 옵션은 다음과 같다.

  • track by_[src|dst]
track by_src는,
  1. 동일한 출발지에서 
  2. 정해진 시간 동안 정해진 패킷량이 들어오는 경우를 탐지하며
  3. 결과적으로 1:1이 모인 1:N의 IP 발생 구조를 탐지한다. 

반면 track by_dst는,
  1. 동일한 목적지로 
  2. 정해진 시간 동안 정해진 패킷량이 들어오는 경우를 탐지하며 
  3. 결과적으로 1:1이 모인 N:1의 IP 발생 구조를 탐지한다. 

보통 SCAN 트래픽은 1:N, DDoS 트래픽은 N:1의 IP 발생 구조를 이루므로, 탐지하고자 하는 트래픽의 성격에 따라 선택하면 된다.

IP 발생 구조 비교

  • threshold:type [threshold|limit|both]
로그 발생 타입을 결정한다. threshold:type threshold는 패킷량, threshold:type limit는 임계시간내 정해진 패킷 개수만을, threshold:type both는 임계시간 단위를 로그 발생 기준으로 삼는다.

다음 표를 보면 threshold만이 패킷 발생량을 정확히 측정할 수 있으며(결과적으로 발생 추이를 정확히 측정할 수 있다), limitboth는 정확한 패킷 발생량 측정이 어렵다. 물론 이 설명이 아주 정확하지는 않지만, 전반적으로 이런 경향을 보인다(..)


특히 both는 로그 축약에 목적이 있는데, 그 이유는 부정확한 탐지로그가 대량 발생하면 정작 공격이 발생했을 때, 제대로 된 대응이 어려워지기 때문이다. 한마디로 쓸데없는 일을 붙잡고 있느라 해야 할 일을 못하게 만든다.


오탐이 오죽 많았으면 이런 옵션까지 만들었을까?-_- 그러나 오탐이 많다고 해서 로그를 축약하기 시작하면 정작 공격이 발생해도 발생 양상이 왜곡되어 정확한 상황 파악은 물 건너 가고, 신속한 대응은 꿈도 못 꾸는 처지에 놓이게 된다. 정확한 측정을 시도하면서 오탐을 줄여나가는 방향을 선택해야 할 것이다.

threshold 옵션에 대해서 알아야 할 게 하나 더 있다. IP 발생 구조를 결정하는 track by_[src|dst] 옵션은 출발/목적지 기준으로 로그 발생 여부를 결정한다. 동일한 트래픽임에도 출발지와 목적지를 따로 검사할 수 있다는 것. 실제 사례를 보자.

다음 룰은 동일한 UDP 트래픽을 검사하여 똑같이 2초간 2개의 패킷이 발생하면 탐지한다. IP 발생 구조만 다르다.

local.rules

다음 그림처럼 snort.conf와 별도로 local.rules만 정의된 snort-local.conf를 만들어 두면 사용자룰만 테스트할 때 편하다.

snort-local.conf

snort-local.conf 를 이용한 Snort 실행

Snort 를 실행한 후, DNS 질의 패킷을 발생시켜보자. 하나의 DNS 질의에 의해 두 개의 패킷이 발생했다. 하나는 A 레코드(IPv4), 하나는 AAAA 레코드(IPv6).

nslookup 테스트

DNS 질의 패킷

그런데 테스트 결과는 서로 다른 유형인 'flood test(track by_dst)'와 'scan test(track by_src)' 로그가 각각 하나씩 발생했다. 동일한 패킷을 출발지와 목적지 기준으로 따로 검사한 결과다.

발생 탐지로그

IP 발생 구조를 제외하면 결국 같은 트래픽을 검사하는 룰을 이용한 테스트 자체에 문제가 있을 수도 있지만, 하나의 패킷에 대해 서로 다른 검사 결과를 보여주는, 개인적으로 이해가 잘 안 가는 결과다. 이런 경우를 예방하고 싶다면 패킷의 물리적 특성이나 임계시간, 발생량 등을 구분해서 차별화를 해줄 필요가 있어 보인다.

댓글 없음:

댓글 쓰기

크리에이티브 커먼즈 라이선스