Snort 룰셋 핵심 옵션 가이드

룰 구조부터 탐지 옵션, 관리 옵션, Snort 2·Snort 3·Suricata 문법 차이까지

① Rule 구조→② 네트워크 변수→③ Content→ ④ Sticky Buffer→⑤ Flow→⑥ Flowbits→ ⑦ 기타 옵션→⑧ 관리 옵션
① Rule 구조

룰은 Header와 Options로 구성

괄호 앞은 어떤 트래픽을 볼지 정하고, 괄호 안은 어떤 조건으로 탐지할지 정합니다.

alert http $EXTERNAL_NET any -> $HOME_NET any (
    msg:"HTTP POST Login";
    flow:established,to_server;
    http_method;
    content:"POST";
    sid:2000001;
    rev:1;
)
alert
Action
http
Protocol
$EXTERNAL_NET any
Source
→
Direction
$HOME_NET any
Destination
( ... )
Rule Options
구분역할예시
Action매칭 시 수행할 동작alert, drop, pass
Protocol검사할 프로토콜tcp, udp, http
Source / Destination출발지·목적지 IP와 포트$EXTERNAL_NET any -> $HOME_NET 80
Options문자열, 방향, 상태, 식별 정보content, flow, sid
② HOME_NET / EXTERNAL_NET

보호 대상과 외부 네트워크 정의

alert tcp $EXTERNAL_NET any -> $HOME_NET 80 (
    msg:"HTTP Access";
    sid:2000001;
    rev:1;
)
$HOME_NET

보호하려는 내부망, 서버망 또는 DMZ 대역입니다.

$EXTERNAL_NET

외부 인터넷 또는 HOME_NET을 제외한 네트워크입니다.

Snort 3 설정

/usr/local/snort/etc/snort/snort.lua

HOME_NET = '6.10.64.0/24'
EXTERNAL_NET = 'any'

include 'snort_defaults.lua'

Security Onion / Snort 2 설정

/etc/nsm/[센서명-인터페이스]/snort.conf

ipvar HOME_NET 6.10.64.0/24
ipvar EXTERNAL_NET !$HOME_NET
ipvar HTTP_SERVERS 6.10.64.30
핵심: EXTERNAL_NET any는 내부 통신도 포함할 수 있습니다. 외부만 의미하게 하려면 !$HOME_NET 구성이 더 명확합니다.
③ Content

현재 검사 버퍼에서 문자열 검색

alert tcp $EXTERNAL_NET any -> $HOME_NET 80 (
    msg:"POST String Detected";
    content:"POST";
    sid:2000002;
    rev:1;
)

content는 현재 선택된 버퍼에서 문자열 또는 16진수 패턴을 찾습니다. 별도 Sticky Buffer를 선택하지 않으면 일반 패킷 데이터가 기준입니다.

문자열

content:"POST";

16진수

content:"|50 4F 53 54|";

혼합 표현

content:"Location|3A 20|";

content:"POST";와 content:"|50 4F 53 54|";는 같은 바이트를 탐지합니다.
④ Sticky Buffer

HTTP에서 필요한 영역만 선택

alert http $EXTERNAL_NET any -> $HOME_NET any (
    msg:"HTTP POST";
    http_method;
    content:"POST";
    sid:2000003;
    rev:1;
)
http_method

GET, POST 등 메서드

http_uri

/dvwa/login.php 등 URI

http_header

Host, Cookie, User-Agent 등 헤더

http_client_body

POST 요청 본문

http_stat_code

200, 302, 404 등 응답 코드

Snort 3 예시

http_method;
content:"POST";

http_uri;
content:"/dvwa/login.php";
버전 주의: Snort 2는 content 뒤에 HTTP modifier를 붙이고, Snort 3는 Sticky Buffer를 먼저 선언합니다. Suricata는 점 표기법을 사용합니다.
⑤ Flow

세션 상태와 통신 방향 제한

alert http $EXTERNAL_NET any -> $HOME_NET any (
    msg:"HTTP Request";
    flow:established,to_server;
    sid:2000004;
    rev:1;
)
established

연결이 성립된 TCP 세션에 속한 패킷만 검사합니다.

to_server

클라이언트에서 서버로 가는 요청 방향입니다.

to_client

서버에서 클라이언트로 가는 응답 방향입니다.

Client Server SYN -------------------------> <-------------------- SYN/ACK ACK -------------------------> HTTP Request = to_server HTTP Response = to_client

Snort의 TCP 세션 추적기는 SYN, SYN/ACK, ACK와 양방향 패킷을 바탕으로 세션 상태와 클라이언트·서버 방향을 관리합니다.

SPAN에서 한쪽 방향만 수집하거나 세션 중간부터 보기 시작하면 established 판단이 제한될 수 있습니다.
⑥ Flowbits

같은 TCP 세션에서 앞선 상태 기억

Rule 1 — 로그인 시도 저장

alert http $EXTERNAL_NET any -> $HOME_NET any (
    msg:"Login Attempt";
    flow:established,to_server;
    http_method;
    content:"POST";
    flowbits:set,dvwa.login;
    flowbits:noalert;
    sid:2000005;
    rev:1;
)

Rule 2 — 로그인 실패 응답 확인

alert http $HOME_NET any -> $EXTERNAL_NET any (
    msg:"Login Failed";
    flow:established,to_client;
    flowbits:isset,dvwa.login;
    http_stat_code;
    content:"302";
    flowbits:unset,dvwa.login;
    sid:2000006;
    rev:1;
)
옵션역할
set현재 세션에 상태를 저장
isset상태가 저장되어 있는지 확인
unset저장된 상태 제거
noalert상태만 저장하고 첫 번째 룰의 Alert는 숨김
POST 로그인 시도 → set 302 응답 → isset 확인 → Alert → unset
⑦ 기타 탐지 옵션

문자열 조건을 더 정확하게 제한

nocase

영문 대소문자를 구분하지 않습니다.

content:"admin"; nocase;

pcre

정규표현식으로 복잡한 패턴을 검사합니다.

pcre:"/user(name)?=/i";

offset

버퍼 시작점에서 몇 바이트 뒤부터 검색할지 지정합니다.

content:"POST"; offset:0;

depth

검색 시작점부터 최대 몇 바이트까지 볼지 제한합니다.

content:"POST"; depth:4;

distance

이전 content가 끝난 지점에서 몇 바이트 뒤부터 다음 검색을 시작할지 지정합니다.

distance:0;

within

이전 content 이후 몇 바이트 안에서 다음 content를 찾을지 지정합니다.

within:100;

offset / depth 예시

content:"POST";
offset:0;
depth:4;

버퍼의 첫 번째 바이트부터 4바이트 범위 안에서 POST를 찾습니다.

distance / within 예시

content:"Location|3A 20|";
content:"login.php";
distance:0;
within:100;

Location: 이 끝난 직후부터 100바이트 안에서 login.php를 찾습니다.

구분: offset/depth는 버퍼 시작점을 기준으로 하고, distance/within은 이전 content 매칭 지점을 기준으로 합니다.
⑧ 관리 옵션

Alert 식별과 룰 버전 관리

alert tcp any any -> any 80 (
    msg:"HTTP Access Detected";
    classtype:web-application-activity;
    sid:2000101;
    rev:2;
)
옵션의미운영 방법
msgAlert에 표시되는 설명무엇을 탐지했는지 한눈에 알 수 있게 작성
sid룰의 고유 식별 번호다른 룰과 중복되지 않게 관리
rev룰 수정 버전룰 내용 변경 시 1씩 증가
classtype공격 유형 분류Alert 우선순위와 분류에 활용
예시 정책: 1xxxxxx 일반 상황 · 2xxxxxx 웹 서버 · 3xxxxxx 네트워크 탐지
⑨ Snort 2 / Snort 3 / Suricata

같은 의미, 다른 HTTP 버퍼 문법

가장 큰 차이는 HTTP 전용 버퍼의 이름과 content 앞뒤 순서입니다.

POST Method 탐지

Snort 2.9
alert tcp any any -> any 80 (
    content:"POST";
    http_method;
    sid:1001;
    rev:1;
)
Snort 3
alert http any any -> any any (
    http_method;
    content:"POST";
    sid:1001;
    rev:1;
)
Suricata
alert http any any -> any any (
    http.method;
    content:"POST";
    sid:1001;
    rev:1;
)

URI 탐지

엔진문법
Snort 2content:"/dvwa/login.php"; http_uri;
Snort 3http_uri; content:"/dvwa/login.php";
Suricatahttp.uri; content:"/dvwa/login.php";

HTTP 상태 코드 탐지

엔진문법
Snort 2content:"302"; http_stat_code;
Snort 3http_stat_code; content:"302";
Suricatahttp.stat_code; content:"302";

요청 Body 탐지

엔진문법
Snort 2content:"username="; http_client_body;
Snort 3http_client_body; content:"username=";
Suricatahttp.request_body; content:"username=";
외우는 법:
Snort 2 = content 먼저, modifier 나중
Snort 3 = 언더바 Sticky Buffer 먼저
Suricata = 점(.) Sticky Buffer 먼저

로그인 POST 룰 전체 비교

Snort 2.9
alert tcp $EXTERNAL_NET any -> $HOME_NET 80 (
    flow:established,to_server;
    content:"POST"; http_method;
    content:"/dvwa/login.php"; http_uri;
    sid:2100001; rev:1;
)
Snort 3
alert http $EXTERNAL_NET any -> $HOME_NET any (
    flow:established,to_server;
    http_method; content:"POST";
    http_uri; content:"/dvwa/login.php";
    sid:2100001; rev:1;
)
Suricata
alert http $EXTERNAL_NET any -> $HOME_NET any (
    flow:established,to_server;
    http.method; content:"POST";
    http.uri; content:"/dvwa/login.php";
    sid:2100001; rev:1;
)