2015년 10월 13일 화요일

Snort 분석(DNS excessive outbound NXDOMAIN replies)

오늘 살펴볼 Snort 룰은 다음과 같다.

alert udp $HOME_NET 53 -> $EXTERNAL_NET any 
(msg:"DNS excessive outbound NXDOMAIN replies - possible spoof of domain run by local DNS servers"; 
byte_test:1,&,2,3; 
  • 네번째 byte(byte offset 3)를 2와 AND 비트 연산
byte_test:1,&,1,3; 
  • 네번째 byte(byte offset 3)를 1과 AND 비트 연산
byte_test:1,&,128,2; 
  • 세번째 byte(byte offset 2)를 128과 AND 비트 연산
detection_filter:track by_dst, count 200, seconds 30; 
  • 30초간 200개의 패킷이 동일 목적지로 들어오면 탐지
metadata:policy security-ips drop, service dns; 
reference:cve,2008-1447; reference:cve,2009-0233; 
reference:url,www.kb.cert.org/vuls/id/800113;
reference:url,www.microsoft.com/technet/security/bulletin/MS09-008.mspx; 
classtype:misc-attack; sid:13949; rev:5;)

해당 룰은 과다한 NXDOMAIN(Non-Existent Domain) 응답 트래픽을 탐지하는데, 이러한 트래픽을 통해 DNS 서버에 대한 도메인 스푸핑 공격, 즉 DNS Cache Poisoning 공격의 가능성을 알려준다. 일반적으로 DNS Cache Poisoning 공격은 다음과 같은 순으로 이루어진다.
  1. 공격자는 Poisoning을 원하는 도메인(victim.com)의 서브도메인으로 조합한 대량의 질의(1.victim.com 등)를 대상 DNS 서버에 전송. 
  2. 대상 DNS 서버는 질의받은 도메인에 대한 Authority를 가지고 있는 victim.com DNS 서버에게 재질의 및 응답 대기.
  3. 공격자는 대상 DNS 서버가 victim.com DNS 서버로부터 응답을 받기 전에 Transaction ID, 포트 정보를 위조한 응답을 전송.
  4. 대상 DNS 서버는 먼저 받은 응답을 Caching 함.

참고로 해당 룰은 DNS 증폭 DDoS 공격 트래픽을 탐지할 수도 있다.


일단 해당 룰은 특정 위치의 byte를 다양한 조건으로 비교할 수 있는 'byte_test' 옵션만으로 이루어져 있다. 트래픽의 특정 구조 검사만으로 탐지가 이루어진다는 뜻.

참고로 'byte 시작 위치'는 '0부터 시작하는 byte offset 단위'로 계산한다. 왜 2 -> 3 -> 1 순서로 만들었을까? 매번 헷갈린다


'detection_filter'란 옵션도 사용되었는데, '로그 발생 타입'만을 정의하지 못할 뿐, 이전에 소개한 'threshold' 옵션과 동일하다. (Snort는 룰 옵션이 너무 다양해서 중복, 유사 성격의 옵션들이 꽤 된다.) 이제 실제 탐지 내역을 확인해보자. 해당 룰이 탐지한 트래픽은 다음과 같다.


'byte_test' 검사의 의미를 파악해보자. 먼저 'byte_test:1,&,2,3' 옵션은 'byte offset 3에서 시작하는 1byte를 10진수 2와 AND 비트 연산'을 하겠다는 뜻이다.


DNS 페이로드 중 네번째(byte offset 3부터 1byte) byte는 '16진수 83'이며 10진수 2와 AND 비트 연산을 한 결과는 다음과 같다.

10000011 (16진수 83)
00000010 (10진수 2)
00000010

AND 연산은 두 값이 모두 1일때만 참이며, Snort는 결과가 참이면 탐지한다. 두번째 'byte_test' 옵션도 마찬가지.

10000011 (16진수 83)
00000001 (10진수 1)
00000001

byte 83을 10진수 2, 1과 연달아 AND 비트 연산을 한 이유는 무엇일까? DNS 페이로드 중 Flags 영역은 16bit(2byte)로 구성되어 있는데, 그 중 두번째 byte에 'Reply code' 정보가 할당되어 있다.

두번째 byte 83의 2진수는 '10000011'이며, 'No such name', 즉 NXDOMAIN임을 알려주는 'Reply code'의 2진수는 '11'이다. 해당 룰 개발자는 'Reply code'가 2진수 '10'과 '1'로 조합됐는지를 확인함으로써 'NXDOMAIN' 트래픽만을 탐지하고자 한 것.


Flags 영역의 첫번째 byte에는 DNS 질의/응답 여부가 구분되어 있으며, 2진수 '10000000'은 해당 패킷이 DNS 응답임을 의미한다.

10000001 (16진수 81)
10000000 (10진수 128)
10000000

결국 해당 룰 개발자는 DNS 페이로드 중 Flags 영역의 'Response'와 'Reply code'에 할당된 2진수를 검사해서 'NXDOMAIN 응답' 트래픽만을 탐지하고자 했으며, 해당 룰은 의도대로 동작했다.

하나 특이한 점은 탐지된 트래픽이 전부 도메인의 IP 질의가 아닌, IP의 도메인(PTR 레코드) 질의에 대한 NXDOMAIN 응답이란 점.


그렇다면 DNS Cache Poisoning과는 거리가 멀다. 웹서핑하면서 DNS 트래픽을 좀 살펴봤더니 도메인에 대한 IP 주소를 받아온 후, 다시 해당 IP에 대한 PTR 질의를 하는 트래픽이 매우 자주 발생한다. 크롬, IE 모두 증상은 똑같다. 왜 이러지? 정상인가?


참고로 해당 룰은 다음과 같이 수정해도 결과는 똑같다.

alert udp any 53 -> any any (content:"|81 83|; offset:2; depth:2;)

목적이나 결과가 같다면 단순하고 쉽게 만드는 것이 룰 관리나 성능 차원에서 더 좋지 않을까 한다. (물론 복잡하고 어렵게 만들면 있어 보이긴 함)

쉬운 룰 따위는 안 만드는 차가운 도시 남자

댓글 없음:

댓글 쓰기

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