본문 바로가기

정보보안/침해사고 분석 및 대응

[보안장비 운영] 침입탐지시스템

침입탐지시스템
(Snort: SNiffer and mORe)

① 개념

  • 개발년도: 1998년
  • 개발자 : 마틴 로시
  • 네트워크 트래픽을 더 많이 감시하고 분석한다는 의미
  • 주요기능
    • 패킷 스니퍼(sniffer) : 네트워크상의 패킷을 스니핑하여 보여주는 기능
    • 패킷 로거(logger) : 모니터링한 패킷을 저장하고 로그에 남기는 기능
    • 네트워크 IDS/IPS : 네트워크 트래픽을 분석해 공격을 탐치/차단하는 기능

② Snort Rule 설정

  1. 룰 헤더(header) 설정
    • 형식 :[action] [protocol] [ip address] [port] [direction] [ip address2] [port2] 
      • Rule Actions : 패킷 탐지 시(룰에 매칭 시), 처리방식
        ACTION 설명
        alert generate an alert using the selected alert methd, and then log the packet
        alert 발생, 로그 남김
        log log the packet
        로그 남김
        pass ignoer the packet
        패킷 무시
        activate alert and then turn on another dynamic rule
        alert 발생, 대응하는 dynamic rule 활성화
        drop block and log the packet
        패킷 차단, 로그 남김
        reject block the packet, log it, and then send a TCP reset if the protocol is TCP or an ICMP port unreachable message if the protocol is UDP
        패킷 차단, 로그 남김
        TCP일 경우 : TCP Reset 전송
        UDP일 경우 : ICMP Port unreachable 전송
        sdrop block the packet but do no log it
        패킷 차단, 로그에 안남김(silent)
      • Protocols : 탐지할 프롵토콜 (4개 지원)
        • TCP,UDP,ICMP,IP
      • IP Addresses : 출빌지/목적지 IP
        • 단일 IP, IP 대역(CIDR 표기), IP 리스트 지정 가능
        • (리스트 지정) [IP주소,IP주소..]
        • (any) 모든 IP를 의미. 일반적으로 출발지 정보는 공격자의 IP를 알지 못하는 경우가 대부분이라 any로 지정.
        • !(부정연산자)  '~를 제외한' 주소표현 가능 (ex.!192.168.159.10: 192.168.159.10을 제외환 모든 IP)
      • Port Numbers : 출발지/목적지 Port
        • 단일 Port, 포트 범위(Port Range), Port 리스트 지정 가능
        • (범위 지정) :(콜론) 이용해 표시 (ex. 1:1023 - 1부터1023사이의 포트)
        • (리스트 지정) [포트,포트,포트..]
      • Direction Operator : 방향 지시자
        • (단방향) -> : 왼쪽에 출발지, 오른쪽에 목적지
        • (양방향) <> : 출발지와 목적지 사이에 오가는 모든 패킷
        • <- 라는 지시자는 없다.
  2. 룰 바디(body) 설정
    1. 일반옵션 설정
      옵션 설명
      msg msg 옵션에 기록된 내용이 alert 발생 시 이름으로 사용
      reference rule과 관련된 외부 취약점 정보 참조 시 사용
      sid snort rule id
      99 이하 : 시스템에 예약된 sid
      100 - 1,000,000 이하 : snort(www.snort.org)에서 배포하는 룰셋(ruleset)에서 사용하는 sid
      1,000,001 이상 : 사용자 정의 rule에서 사용하는 sid
      classtype snort는 사용자가 어떤 유형의 공격인지 쉽게 이해하고 우선순위를 결정할 수 있도록 공격 유형과 기본 우선순위(위험도)를 정의
      우선순위 : 1(높음) 2(중간) 3(낮음)
      priority rule의 우선순위(위험도)에 대해 숫자로 표기. 
      지정시, classtype의 기본 우선순위를 덮어 씀
      rev rule 버전번호. 수정(revision) 횟수 표기(수정 할때마다 +1)
    2. 페이로드(Payload) 범위 관련 옵션
      action 설명
      content 페이로드에서 검사할 문자열 지정
      text,binary 두 형식 모두 지원하며 혼합된 형식일 수 있다.
      (text 형식) content:"pattern", 해당 pattern 문자열 검사
      (birany 형식) content:"|FF FF|", 파이프 기호 사이에 헥사값으로 표현
      (! 부정연산자 사용) content:!"pattern", 해당 pattern 문자열이 없는지 검사
      (; \ ") 세 가지 특수문자는 escape 처리해서 사용 (; 문자를 규칙 내에서 일반 텍스트로 쓰고 싶다면 \;로 표시하여 Snort가 이를 특수한 구분자로 인식하지 않고 문자로 인식하게 할 수 있음)
      uricontent content 문자열을 전체 패킷과 비교하는 대신 HTTP 클라이언트 요청 URI 정보를 검사할 문자열을 지정
      *offset The offset keyword allows the rule writer to specify where to start seaching for a pattern within a packet
      페이로드에서 content 패턴을 검사할 시작위치
      페이로드의 첫 번째 바이트 위치가 0부터 시작
      *depth The depth keyword allows the rule writer to specify how far into a packet Snort should seach for the specified pattern form a given offset
      offset부터 몇 바이트까지 검사할 것인지 지정
      *distance The distance keyword allows the rule writer to specify how far into a packet Snort should ignore before starting to search for the specified pattern relative to the end of the previous pattern match
      이전 content 패턴에 매칭된 경우, 매칭된 이후 바이트부터 몇 바이트 떨어진 위치에서 다음 content를 검사할 것인지 지정
      *within The within keyword is a content modifier that makes sure that at most N bytes are between pattern matches using the content keyword
      이전 content 패턴에 매칭된 경우, distance부터 몇 바이트 범위 내에서 다음 content를 검사할 것인지 지정
      nocase 페이로드 검사 시 대/소문자 구분 x(binary 형식도 동일하게 구분x)
      • offset, depth, distance, within 등 범위를 지정해주는 옵션 사용 이유 : 페이로드 전체에 대해서 패턴 매칭을 수행하는 것보다 페이로드 일부분에 대해서 패턴 매칭을 수행하는 것이 성능향상과 오탐을 줄여줌
      • 범위 지정의 경우, 미탐(False negative)이 발생하지 않도록 적절한 범위 설정 필요
    3. 페이로드 정규표현식 관련 옵션
      메타 문자 설명
      \ 특수문자 기능을 제거하는 이스케이프 문자
      ^ ^바로 다음에 오는 문자가 문자열의 시작
      $ $바로 앞에 오는 문자가 문자열의 끝을 의미
      . 임의의 문자 1개
      [] 집합 안에 지정한 문자들 중 하나와 일치
      [ㄱㄴㄷ] : ㄱㄴㄷ 문자 중 하나
      [a-zA-Z] : a에서 z사이 또는 A-Z 사이의 문자중 하나
      [0-9] : 0에서 9사이의 숫자 중 하나
      [^] 집합 안에 지정한 문자들을 제외한 임의의 문자 하나와 일치
      [^0-9] : 숫자를 제외한 임의의 문자 하나
      | | 앞에 오는 문자열과 뒤에 오는 문자열 중 하나와 일치
      일반적으로 항목을 묶어주는 ()와 같이 사용
      (one|two|three) : one, two, three 문자열 중 하나
      수량자 설명
      * * 앞에 오는 문자가 0회 이상 나타남
      He*llo : Hello(o),Hello(o),Heello(o),Hallo(x),ello(x)
      + + 앞에 오는 문자가 1회 이상 나타남
      ? ? 앞에 오는 문자가 0또는 1회 나타남
      {x} {x} 앞에 오는 문자가 정확히 x회 나타남
      He{3}llo : Heeello (o), Hello(x), Heello(x), Heeeello(x)
      {x,} {x,} 앞에 오는 문자가 x회 이상 나타남
      He{3,}llo : Heeello (o), Heeeello(o), Hello(x), Heello(x)
      {x,y} {x,y} 앞에 오는 문자가 정확히 x회 이상, y회 이하 나타남
      • snort는 pcre(Perl Compatible Regular Expression:Perl 기반의 정규표현식 문법)을 지원한다. pcre 옵션은 슬래시(/) 기호 사이에 정규 표현식을 입력한다.
    4. HTTP 관련 옵션
      옵션 설명 / 해당 옵션 지정 시, content에 명시된 내용을 해당 옵션 범위 내에서 (필터링)찾는다.
      http_method HTTP method 부분 검사
      GET /index.php HTTP/1.1
      http_uri
      (http_raw_uri)
      HTTP URI 부분 검사
      GET /index.php HTTP/1.1
      http_header
      (http_raw_header)
      HTTP Header 부분 검사, 요청(request)/응답(response) 모두 사용
      http_cookie
      (http_raw_cookie)
      HTTP cookie 부분 검사
      http_client_body HTTP 클라이언트 요청의 Body 부분 검사(POST요청에 대한 검사)
      http_stat_code HTTP 응답의 status_code 부분 검사
      HTTP/1.1. 200 OK
      http_stat_msg HTTP 응답의 status_message 부분 검사
      HTTP/1.1. 200 OK
      • snort는 HTTP 패킷에 대해 패킷 전체가 아닌 특정 필드에서 패턴을 검사하는 기능을 지원하며 이는 오탐을을 줄이고 성능을 향상해주는 효과가 있다.
      • raw가 붙어있는 옵션은 URL 디코딩을 하지 않은 상태로 검사한다는 의미이다.
    5. 이벤트 제한(Event Threshold) 관련 옵션
      • 특정 시간동안 발생하는 이벤트 수를 제한하기 위한 옵션. 과도하게 중복된 많은 이벤트가 발생하는 것을 방지한다.
      • (형식) threshold:type <limit|threshold|both>, track <by_src|by_dst>, count <c>, seconds <s>
        • type
          • limit(까지) : 매 s초 동안 c 번째 이벤트까지 action 수행(연속)
          • threshold(마다) : 매 s초 동안 c 번째 이벤트마다 action 수행(띄엄띄엄 빈도)
          • both(한번) : 매 s초 동안 c 번 이상 이벤트가 발생할 시 한번 action 수행
        • track
          • by_src : 출발지 IP 기준으로 추적
          • by_dst : 목적지 IP를 기준으로 추적

 

③ 공격 패킷 탐지 예시 

    • root 로그인 시도/성공 탐지
      1. FTP root 로그인 탐지
        1. wireshark를 통해 FTP 메시지를 분석해보면 FTP 클라이언트 접속 시 USER 명령을 통해 ID 정보가 평문으로 전달되는 것을 확인할 수 있다. 
          450 106.621298 10.10.10.10 47724 10.10.10.20 21 FTP Request: USER root\r\n
        2. 이를 snort 룰 작성 시 content 옵션에 적용해 root계정의 FTP 접속을 탐지한다.
          alert tcp any any -> 10.10.10.0/24 21 (msg:"FTP root user access"; content:"USER root"; nocase; sid:100100;
          TCP 프로토콜을 이용하고 21번 포트를 목적지로 하고있는 FTP 클라이언트로부터 요청 데이터를 탐지하기 위한 것이며, content 옵션을 통해 root계정 로그인 시 요청데이터에 포함되는 "USER root" 문자열을 검사하고 있다.
        3. root 계정으로 FTP 접속 시 alert 액션에 의해 alert메시지가 남았으며 snort rule에서 지정한 sid(100100), msg(FTP root user access) 정보와 함께 출발지(10.10.10.10:47724) 주소, 목적지 주소(10.10.10.20:21) 주소, TCP 헤더 정보 등을 보여주고 있다.
          #snort > tail -f alert
          [**] [1:100100:0] FTP root user access [**]
          [Priority: 0]
          11/18-15:43:00.000000 10.10.10.10:47724 -> 10.10.10.20:21 
          TCP TTL:64 TOS:0x10 ID:17974 IpLen:20 DgmLen:63 DF
          ***AP*** Seq: 0xB4B89E03 Ack: 0x494132FD Win: 0xE5 TcpLen: 32
          TCP Options (3) => NOP NOP TS: 11852365 72157517
          1. 경고 제목 및 정보
            • [] [1:100100:0] FTP root user access []:
              • [1:100100:0]: Snort 규칙 ID로, 1은 생성자 ID, 100100은 규칙 ID, 0은 리비전 번호입니다.
              • FTP root user access: Snort 규칙에 의해 기록된 경고 메시지로, FTP 서비스에 root 계정 접근 시도가 있었음을 의미합니다.
            • [Priority: 0]: 경고 우선순위가 0으로 매우 높음을 나타내며, 즉각적인 주의가 필요할 수 있습니다.
          2. 발생 시간
            • 11/18-15:43:00.000000: 11월 18일 오후 3시 43분에 이벤트가 발생했습니다.
          3. 소스 및 대상 IP 주소와 포트
            • 10.10.10.10:47724 -> 10.10.10.20:21:
              • 10.10.10.10:47724: 소스 IP 주소와 포트(47724)로, 접근을 시도한 클라이언트입니다.
              • 10.10.10.20:21: 대상 IP 주소와 포트(21)로, FTP 서버입니다.
              • FTP 서버의 포트 21에 소스 IP 10.10.10.10이 47724 포트에서 연결을 시도했음을 의미합니다.
          4. TCP 패킷 정보
            • TCP TTL:64: **TTL(Time To Live)**은 64로, 패킷이 네트워크를 통해 전달될 수 있는 최대 홉 수를 나타냅니다.
            • TOS:0x10: 서비스 유형(ToS)의 값으로, 패킷의 우선순위나 서비스 특성을 나타냅니다.
            • ID:17974: 패킷의 고유 ID로, 같은 세션에서 다수의 패킷을 구분하는 데 사용됩니다.
            • IpLen:20: IP 헤더의 길이(20바이트)입니다.
            • DgmLen:63: 전체 IP 데이터그램의 길이(63바이트)입니다.
            • DF: Don't Fragment 플래그가 설정되어 있어 패킷이 분할되지 않도록 설정되었습니다.
          5. TCP 플래그 및 시퀀스 정보
            • AP: ACKPUSH 플래그가 설정된 패킷입니다.
              • Seq: 0xB4B89E03: 패킷의 시퀀스 번호입니다.
              • Ack: 0x494132FD: 패킷의 응답 번호입니다.
              • Win: 0xE5: TCP 윈도우 크기 값입니다.
              • TcpLen: 32: TCP 헤더 길이입니다.
          6. TCP 옵션
            • TCP Options (3) => NOP NOP TS: 11852365 72157517:
              • TCP 옵션으로 **NOP(No Operation)**가 두 번 사용되었습니다.
              • TS: 11852365 72157517: 타임스탬프(TS) 옵션이 설정되어 있으며, 11852365와 72157517은 타임스탬프 값입니다.
        4. (관련 취약점 분석,평가 항목) ftpusers 파일 설정 : FTP 서비스는 평문으로 송수신하기 때문에 아이디나 패스워드가 쉽게 노출될 수 있다. 따라서 FTP 서비스 사용을 제한(SFTP 대체)하거나 불가피하게 사용할 경우에는 중요 계정인 root계정의 직접 접속을 제한하여 root 계정의 패스워드가 노출되지 않도록 한다.
      2. Telnet root 로그인 성공 탐지
        1. wireshark를 통해 Telnet 메시지를 분석해보면 Telnet 클라이언트 로그인 성공 시 서버 응답 데이터로 login키워드와 쉘 프롬프트([root@Fedora ~]#) 정보가 평문으로 전달되는 것을 알 수 있다.
          217 37.588520 10.10.10.20 23 10.10.10.1 3044 TELNET TelnetData ... Last login :.... [root@Fedorall ~]#
        2. 이를 snort 룰 작성 시 content 옵션에 적용해 root계정의 Telnet 접속을 탐지한다.
          alert tcp 10.10.10.0/24 23 -> any any (msg:"Telnet root login success"; content:"login"; pcre:"/root@.*#/ nocase; sid:100110;
          tcp 프로토콜을 이용하고 23번 포트를 출발지로 하고 있어 telnet 서버로부터 응답 데이터를 탐지하기 위한 것이며 content 옵션을 통해 login 문자열이 포함되어 있는지 먼저 검사하고 pcre 옵션의 정규표형식을 통해 추가 검사를 하고 있다. 정규 표현식을 살펴보면 로그인 성공 시 응답 데이터에 포함되는 쉘 프롬프트를 탐지하기 위해 "root@" 문자열 다음에 임의의 문자(.)가 0개 이상(*) 포함되어 있고 그 다음에 #을 포함하고 있는 문자열을 검사하고 있다.
        3. root 계정으로 Telnet 접속 시 alert 액션에 의해 alert메시지가 남았으며 snort rule에서 지정한 sid(100110), msg(FTelnet root login success) 정보와 함께 출발지(10.10.10.20:23) 주소, 목적지 주소( 10.10.10.1:3082)  주소, TCP 헤더 정보 등을 보여주고 있다.
          #snort > tail -f alert
          [**] [1:100110:0] Telnet root login success [**]
          [Priority: 0]
          11/18-15:43:00.000000 10.10.10.20:23 -> 10.10.10.1:3082 
          ...
        4. (관련 취약점 분석,평가 항목) root 계정의 원격 접속 제한 : root 계정은 시스템을 관리하는 중요 계정이므로 외부에서 Telnet,SSH 등으로 직접 로그인이 가능하면 불법적인 침입자의 목표가 될 수 있다. 따라서 Root계정에 대한 원격 접속을 허용하지 않도록 설정한다.
    • 온라인 패스워드 크래킹 공격 탐지
      1.  Brute Force/Dictionary Attack 공격 탐지 
        1. (Telnet 로그인 기준) snort 룰 작성. tcp 프로토콜을 이용하고 23번 포트를 출발지로 하고 있어 Telnet 서버로부터 응답데이터 탐지하기 위한 것. content옵션을 통해 Telnet 로그인 실패 시 응답데이터에 포함되는 Login incorrect 문자열을 검사하고 있다. threshold 옵션을 살펴보면, 매 5초동안 1번째 이벤트까지만 alert 액션을 수행하도록 하고 있다.
          alert tcp 10.10.10.0/24 23 -> any any (msg:"Telnet Login Brute Force attack"; content:"Login incorrect";  nocase; threshold:type limit, track by_dist, count 1, seconds 5; sid:100120;
        2. (관련 취약점 분석/평가 항목) 계정잠금 임계값 설정 : 공격자에 의한 패스워드 무작위 대입 공격이나 사전 대입공격 발생 시 암호입력 실패 횟수를 적절하게 제한하고 공격 시간을 지체시켜 패스워드 유출 위험을 줄인다.
        3. FTP 로그인의 경우 출발지 포트가 21로 바뀌고 응답데이터에 대하여 Login incorrect 문자열 검사(content: "Login incorrect", threshold: ... track by_dst...)
        4. SSH로그인의 경우 (출발지 기준 요청 데이터 탐지) any any -> 10.10.10.0/24 22 로 변경됨 (content: "SSH-2.0" , threshold: ... track by_src...)
    • Flooding 계열 공격 탐지
      1. HTTP GET Flooding 공격 탐지
        • snort rule 
          • content: "GET / HTTP/1."; depth:13; ...; threshold:type threshold, track by_src, count 100, seconds 1
          • 출발지 주소를 기준으로 매 1초동안 100번째 이벤트마다 alert 액션을 수행하도록 하며, HTTP 버전에 상관없이 모든 버전으로 오는 HTTP GET 요청 탐지
      2. TCP SYN Flooding 공격 탐지
        • snort rule
          • flags:S; threshold:type threshold, track by_src, count 5, seconds 1;..
          • flags 옵션을 통해 TCP 연결 요청 시 사용하는 SYN 플래그 검사.
          • threshold 옵션에서 출발지 주소를 기준으로 매 1초동안 5번의 이벤트 발생마다 alert 액션을 수행하도록 하고 있다.
      3. UDP/ICMP Flooding 공격탐지
        • snort rule
          • alert udp .... 
          • alert icmp...

 

④ 비정상 패킷 탐지 : 비정상 패킷이란 RFC(Request for Command) 문서에 정의된  프로토콜 표준에 위배되는 패킷들을 말하며, 공격자가 공격 도는 취약점 스캔을 위해 사용한다.

  • 비정상적인 패킷을 제대로 처리하지 못하는 침입탐지/방지시스템 또는 침입차단시스템을 우회하긴 목적 또는 시스템이 비정상적인 패킷을 제대로 처리하지 못하여 장애나 오류가 발생하도록 하기 위한 목적으로 사용한다.

 

  • 비정상 IP 패킷
    1. 인터넷 구간의 사설 IP
      • 사설 IP로 예약된 주소는 인터넷 구간에서는 볼 수 없는 IP 주소로 대부분 공격자에 의해 조작된 IP 주소이다.
      • 사설 IP 대역
        • [대규모 네트워크] 10.0.0.0 ~ 10.255.255.255(10.0.0.0/8)
        • [중규모 네트워크] 172.16.0.0 ~ 172.31.255.255(172.16.0.0/12)
        • [소규모 네트워크] 192.168.0.0 ~ 192.168.255.255(192.168.0.0/16)
      • snort rule
        • alert udp 10.0.0.0/8 any -> $HME_NET any ..
        • alert udp 172.16.0.0/12 any -> $HME_NET any ..
        • alert udp 192.168.0.0/16 any -> $HME_NET any ..
    2. 출발지 = 목적지 IP
      • 출발지와 목적지 IP 주소가 동일한 형태의 공격을 Land Attack이라 하며, 시스템의 장애를 유발할 수 있으므로 탐지/차단한다.
      • snort rule
        • alert ip any any -> $HOME_NET any ... sameip;
        • sameip 옵션: ip 프로토콜의 출발지 ip 주소와 목적지 IP 주소가 일치하는 패킷 탐지

 

  • 비정상 TCP 패킷
    1. 정상적인 TCP 플래그 조합
      • (3-way handshake) : SYN,SYN_ACK,ACK
        • 초기 SYN을 제외하면 연결을 맺은 모든 패킷은 ACK 플래그 설정
      • (4-way handshake) : FIN_ACK,ACK
        • 연결 정상 종료
      • (연결 즉시 종료) :RST_ACK
      • (연결 후 송수신 패킷) 디폴트로 ACK 포함, 필요시 PSH,URG 포함
    2. 비정상적인 TCP 플래그
      • SYN_FIN 플래그 조합 
        • 구형 제품들은 FIN 플래그를 포함한 패킷을 허용한 경우가 있고, 연결을 종료하는 플래그로 일부 시스템에서는 이러한 플래그 패킷에 대해 로그를 남기지 않는 특성이 있어 스캐닝 도구들이 SYN_FIN 패킷을 많이 사용함.
        • snortrule
          • flags:SF; 설정 추가
          • 연산자 설정
            • SF : SYN,FIN만 설정된 경우 탐지
            • SF+: SYN,FIN은 반드시 포함할 때 탐지, 이 조건을 만족하며 다른 플래그도 포함한 경우 탐지
            • SF*: SYN, FIN, SYN_FIN 중 하나를 포함할 때 탐지, 이 조건을 만족하며 다른 플래그도 포함한 경우 탐지
            • !SF: SF를 포함하지 않은 설정 탐지
      • SYN_FIN 플래그 변형
        • SYN_FIN 플래그만 탐지하는 장비를 우회하기 위해 SYN_FIN에 다양한 조합을 추가해 탐지
        • snort rule 
          • flags:SF+; 추가
      • FIN 플래그만 설정된 패킷
        • 정상적인 연결종료 패킷은 FIN_ACk 플래그 조합이며 FIN 플래그만으로 설정이 불가. 스텔스 스캐닝 기법 중 FIN 스캔으로 이용
        • snort rule
          • flags:F 추가
      • 플래그가 설정되지 않은 패킷(NULL 패킷)
        • 모든 패킷은 플래그가 설정되며 플래그가 설정되지 않은 패킷은 비정상 패킷으로 이러한 패킷을 NULL 패킷이라고 한다. 스텔스 스캐닝 기법중 NULL tmzosdmfh ghkfdydgksek.
        • snortrule
          • flags:!UAPRSF; 추가
        • 응답은 tcp 헤더 정보에 ****** 로 출력