Snort meta-handout: a detailed intro to snort TOC 1. intro 2. how to run it 3. rules, rules, rules 4. preprocessor/postprocessor (output modules) 5. summary pros/cons what are the challenges Acknowledgements to snort manual writers, which is the basis of a lot of this. ------------------------------------------------ Intro: snort an open-source IDS system: snort at: http://www.snort.org bibliography: snort manual (on-line in pdf) snort FAQ (ascii) several books: Snort 2.1 Intrusion Detection: Brian Caswell, Jay Beale, Foster/Faircloth (editors) Syngress, May. 2004, Intro chapter in Anti-Hacker's Toolkit snort mailing lists (users and sigs) Note: snort rules at: http://www.snort.org/vrt Also see: emergingthreats.net for another free rule set: and e.g., http://www.emergingthreats.net/rules/emerging-botcc.rules ------------------------------------------------------------------------- How to run it: 3 modes for snort 1. packet sniffer 2. logger 3. IDS ------------------------------------------------------------------------- as a packet sniffer: # snort -v icmp (bpf-expression is last arg) 01/25-11:40:42.269964 67.168.231.153 -> 131.252.120.50^M ICMP TTL:64 TOS:0x0 ID:757 IpLen:20 DgmLen:84^M Type:8 Code:0 ID:14014 Seq:0 ECHO^M =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+^M ^M 01/25-11:40:42.285837 131.252.120.50 -> 67.168.231.153^M ICMP TTL:243 TOS:0x0 ID:5044 IpLen:20 DgmLen:84 DF^M Type:0 Code:0 ID:14014 Seq:0 ECHO REPLY^M # snort -vd icmp 01/25-11:40:54.393743 67.168.231.153 -> 131.252.120.50^M ICMP TTL:64 TOS:0x0 ID:769 IpLen:20 DgmLen:84^M Type:8 Code:0 ID:14014 Seq:3072 ECHO^M C6 1B 14 40 DA 01 06 00 08 09 0A 0B 0C 0D 0E 0F ...@............^M 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F ................^M 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F !"#$%&'()*+,-./^M 30 31 32 33 34 35 36 37 01234567^M ^M =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+^M ^M 01/25-11:40:54.409929 131.252.120.50 -> 67.168.231.153^M ICMP TTL:243 TOS:0x0 ID:5056 IpLen:20 DgmLen:84 DF^M Type:0 Code:0 ID:14014 Seq:3072 ECHO REPLY^M C6 1B 14 40 DA 01 06 00 08 09 0A 0B 0C 0D 0E 0F ...@............^M 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F ................^M 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F !"#$%&'()*+,-./^M 30 31 32 33 34 35 36 37 01234567^M add -e to get MAC info ------------------------------------------------------------------------ snort as logger # snort -dev -l ./log -h optional host network but # snort -dev -l gives us in ./log: 131.252.120.50 255.255.255.255 67.168.231.153 ARP 131.252.120.50 has ICMP_ECHO_REPLY (ascii file with 1 packet) 255.255.255.255 has local DHCP requests so things are broken up. ------------------------------------ snort as IDS 1. input is rules from conf file 2. output is log file # snort -d -h -l /some/log/dir -c snort.conf this generates output to the console note: -b puts packets in binary mode (tcpdump -w) binary is probably a good idea for speed, as console i/o is slow. -D runs as a daemon. snort prints stats at exit. ------------------------------------ snort setup in more detail: snort generates alerts. has different logging options. has preprocessors. e.g., make telnet data readable, make portscan check has postprocessors. syslog or unix socket for alerts? has ordering for how rules are processed ------------------------------------ default setup: log in ASCII use full alerts (rule match... beware!) print out alert message as well as full pkt hdr ------------------------------------ alert options: (-A fast on command-line) full fast unsock - send alerts to unix socket none - turn off console - send to console cmg - cmg-style -s switch: send to syslog packet logging: -N to turn off. ------------------------------------------------------------- Sample snort run: # snort -s -d -h 67.0.0.0/24 -l /usr/snort/log -c /usr/local/etc/snort.conf On cable modem network, from one host POV (not seeing other traffic, barring broadcast): 1. alerts go to /var/log/auth.log, as syslog setup is: auth.info;authpriv.info /var/log/auth.log 2. logging goes to ASCII log in /usr/snort/log ------------------------------------------------------------- MS-sql packet: So what does an alert and its log entry look like: alert: Jan 25 12:26:40 homebrew snort: [1:2003:2] MS-SQL Worm propagation attempt [Classification: Misc Attack] [Priority: 2]: {UDP} 221.3.232.39:1046 -> 67.168.231.153:1434 log entry: homebrew# pwd /usr/snort/log/67.168.231.153 homebrew# ls UDP:1434-1046 homebrew# cat UDP* [**] MS-SQL Worm propagation attempt [**] 01/25-12:26:40.192265 221.3.232.39:1046 -> 67.168.231.153:1434 UDP TTL:113 TOS:0x0 ID:48783 IpLen:20 DgmLen:404 Len: 376 04 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................ 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 ................ 01 DC C9 B0 42 EB 0E 01 01 01 01 01 01 01 70 AE ....B.........p. 42 01 70 AE 42 90 90 90 90 90 90 90 90 68 DC C9 B.p.B........h.. B0 42 B8 01 01 01 01 31 C9 B1 18 50 E2 FD 35 01 .B.....1...P..5. 01 01 05 50 89 E5 51 68 2E 64 6C 6C 68 65 6C 33 ...P..Qh.dllhel3 32 68 6B 65 72 6E 51 68 6F 75 6E 74 68 69 63 6B 2hkernQhounthick 43 68 47 65 74 54 66 B9 6C 6C 51 68 33 32 2E 64 ChGetTf.llQh32.d 68 77 73 32 5F 66 B9 65 74 51 68 73 6F 63 6B 66 hws2_f.etQhsockf B9 74 6F 51 68 73 65 6E 64 BE 18 10 AE 42 8D 45 .toQhsend....B.E D4 50 FF 16 50 8D 45 E0 50 8D 45 F0 50 FF 16 50 .P..P.E.P.E.P..P BE 10 10 AE 42 8B 1E 8B 03 3D 55 8B EC 51 74 05 ....B....=U..Qt. BE 1C 10 AE 42 FF 16 FF D0 31 C9 51 51 50 81 F1 ....B....1.QQP.. 03 01 04 9B 81 F1 01 01 01 01 51 8D 45 CC 50 8B ..........Q.E.P. 45 C0 50 FF 16 6A 11 6A 02 6A 02 FF D0 50 8D 45 E.P..j.j.j...P.E C4 50 8B 45 C0 50 FF 16 89 C6 09 DB 81 F3 3C 61 .P.E.P........ $HOME_NET 1434 (msg:"MS-SQL Worm propagation attempt"; content:"|04|"; depth:1; content:"|81 F1 03 01 04 9B 81 F1 01|"; content:"sock"; content:"send"; reference:bugtraq,5310; classtype:misc-attack; reference:bugtraq,5311; reference:url,vil.nai.com/vil/content/v_99992.htm; sid:2003; rev:2;) ------------------------------------------------------------------ Another example: NACHI/Welchia alert: Jan 25 15:20:53 homebrew snort: [1:10000008:1] ALERT!!! NACHI Infection!! [Classification: A Network Trojan was detected] [Priority: 1]: {ICMP} 67.169.207.107 -> 67.168.231.153 log: [**] ALERT!!! NACHI Infection!! [**] 01/25-14:18:42.112372 67.168.223.131 -> 67.168.231.153 ICMP TTL:123 TOS:0x0 ID:18910 IpLen:20 DgmLen:92 Type:8 Code:0 ID:512 Seq:42401 ECHO AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ................ AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ................ AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ................ AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ................ =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ rule: # This rule is for tracking Nachi infections alert icmp $HOME_NET any -> any any (msg: "ALERT!!! NACHI Infection!!"; content: "|aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa|"; dsize:64; itype: 8; icode: 0; classtype:trojan-activity; sid: 10000008; rev: 1;) How much confidence should we have in this one? ------------------------------------------------------------------ Snort dataflow: 1. grab data from libpcap with full payload (unlike tcpdump) 2. packet decode, fill out L2 info, find ip/tcp/udp basic info. 3. packets pass thru preprocessors ... as configured in. 4. packets then go thru detection engine (with its set of rules) 5. outputs (syslog, logging, etc). 6. output plugins -- see barnyard project ------------------------------------------------------------------ Rules: Default order of rules application is: 1. alerts first 2. pass rules, then 3. log rules. This order can be changed if desired. (reduce false positives) ------------------------------------------------------------------ where are the rules? (acc to the snort.conf file) homebrew# cd /usr/local/share/snort homebrew# ls attack-responses.rules local.rules shellcode.rules backdoor.rules misc.rules smtp.rules bad-traffic.rules multimedia.rules snmp.rules chat.rules mysql.rules sql.rules classification.config netbios.rules telnet.rules classification.config-sample nntp.rules tftp.rules ddos.rules oracle.rules virus.rules deleted.rules other-ids.rules web-attacks.rules dns.rules p2p.rules web-cgi.rules dos.rules policy.rules web-client.rules experimental.rules pop2.rules web-coldfusion.rules exploit.rules pop3.rules web-frontpage.rules finger.rules porn.rules web-iis.rules ftp.rules reference.config web-misc.rules icmp-info.rules reference.config-sample web-php.rules icmp.rules rpc.rules x11.rules imap.rules rservices.rules info.rules scan.rules ------------------------------------------------------------------ rule syntax: 1st-level breakdown: rule -> header (options) header -> action protocol from_ip/mask from_port -> to_ip/mask to_port options -> signature message alert tcp any any -> 192.168.1.0/24 111 (content: "|00 01 86 a5|"; msg:"mountd access";) alert is an action any is a wildcard content: and msg: are option keywords ------------------------------------------------------------------ meta-syntax of rule files: includes: includes used to organize: include from snort.conf file include $RULE_PATH/exploit.rules variables: variables may be set (as with $RULE_PATH above) syntax: var VAR MY_NET [192.168.1.0/24,10.1.1.0/24] syntax of config file: directives exist for telling snort what preprocessors/postprocessors to use so you don't have to provide command-line switches where to find rule files order of rule processing (e.g., you want pass rules BEFORE alert rules) Let's break down this rule: alert udp $EXTERNAL_NET any -> $HOME_NET 1434 (msg:"MS-SQL Worm propagation attempt"; content:"|04|"; depth:1; content:"|81 F1 03 01 04 9B 81 F1 01|"; content:"sock"; content:"send"; reference:bugtraq,5310; classtype:misc-attack; reference:bugtraq,5311; reference:url,vil.nai.com/vil/content/v_99992.htm; sid:2003; rev:2;) Rules start with actions: alert - generate an alert acc. to alert method, then log the packet log - generate a log entry pass - ignore the packet activate - alert and turn on dynamic rule dynamic - 1st must be actived by activate rule, then act as a log rule new actions may be created: ruletype suspicious { type log output log_tcpdump: suspicious.log } protocol field is next ---------------------- ip, udp, tcp, icmp ip address and direction ------------------------ any may be used. ip address/netmask a negation operator exists (!) so !192.168.1.0/24 means any other OTHER than 192.168.1.0/24 assume we are 192.168.1.0/24 alert tcp !192.168.1.0/24 any -> 192.168.1.0/24 111 ... etc. means any external access to portmapper using tcp lists may be specified with [ip/mask,ip/mask] and no spaces. port addresses: single port: 111 range: 1:1024 :1024 any <= 1024 (inclusive) 500: >= 500 !111 anything but 111 direction operator: src -> dst any any <> any any - bidirectional <- does not exist activate/dynamic are to be replaced by "tagging" one rule may activate another rule activate rules have required option field dynamic rules are log log rules, but must first be activated possible uses: match triggers next 50 packets recorded with same filter spec. activate tcp !$HOME_NET any -> $HOME_NET 143 (flags: PA; \ content: "|E8C)FFFFFF|/bin"; activates: 1; \ msg: "IMAP buffer overflow!";) dynamic tcp !$HOME_NET any -> $HOME_NET 143 (activated_by: 1; count: 50;) given IMAP exploit, capture and log the next 50 packets. ----------------------------------------------------------------------- Rule Options: -------------- separated by ; typically: keyword: value; categories of rule options: meta-data - info but no runtime affect payload - look for data inside packet payload payload means above the tcp/ip headers, L7 data non-payload - look for data outside payload post-detection - rule has triggered, now do something else meta-data ---------- msg: some string/message about the rule, escape with \ (e.g., \;) reference: reference to external attack system. bugtraq: http://www.securityfocus.com/bid CVE: http://cve.mitre.org/cgi-bin/cvename.cgi?name= Arachnids:(down?) McAfee: http://vil.nai.com/vil/dispVirus.asp?virus_k= url: http:// ... snort has a system for indexing alerts from the snort sid: Can search for sid on main snort page. e.g.,: ftp-wuftp exploit ... reference: bugtraq,1387; reference: cve,CAN-2000-1574; ... sid: used to uniquely id snort rules. allows output plugins to id rules. should also be used with rev keyword. < 100: reserved 100-1000000: rules included with snort >1000000: local rules (you made them) sid-msg.map contains a mapping of alerts to sids. rev: sid, rev is 2-tuple (major/minor code) classtype: categorize alerts into groups. user can prioritize alerts as a consequence. If you have a classification, you have a default priority. This is defined in the config file and (related files, classification.config) defaults exist. E.g., shellcode-detect (means executable code) high-priority (1) attempted-dos medium (2) icmp-event low (3) priority values are 1-4. Our attack exists in distributed snort rules as "misc-attack", but its priority is medium. priority: assign integer priority to rule. overrides classtype: payload detection rule options: ------------------------------- content: Boyer-Moore pattern/match function is used. test is case sensitive data must match exactly option data can contain mixed text and binary data. |binary data in hex| multiple rules may be supplied in one content rule must escape the following chars : ; \ " rule match may be negative using ! Look at SQL content has modifier keywords including: nocase: ignore case content: "USER root"; nocase; rawbytes: ignore preprocessors if any, e.g., telnet preprocessor. depth: how far into the payload to go; e.g., 5 means in the first 5 bytes. offset: skip N bytes, then search. E.g., offset: 4; depth: 20 - skip 4 bytes, then search next 20 bytes. distance: similar to depth, but distance from a previous pattern match. within: pattern match must be within N bytes of previous pattern match. uricontent: search normalized URI(http/url) info: isdataat: veryify that data is at a certain position pcre: Great zot!. rules can be written using perl regular expressions. byte_test: test a byte field against a specific value. byte_jump: grab some bytes, convert to numbers, and jump accordingly. non-payload detection rule options: ----------------------------------- overview: various fields for making assertions about ip headers ip: fragoffset: fragment offset value fragbits: fragmentation flags, M, D, R ttl: ttl value tos: type of service field ip_id: ip_id value, note: 31337 is popular with hacker-dom. ipopts: check various ip options ip_proto: check for specific ip protocol (ip_proto: igmp;) sameip: is src and dst the same general: dsize: size of packet payload tcp: flags: F S R P A U 1 2 (reserved bits) 0 (no flags at all) flow: stream reassembly, options can apply to 1 direction of flow to_client to_server from_client from_server established stateless no_stream only_stream seq: sequence number ack: ack number window: window number icmp: itype: icmp type icode: icmp code icmp_id: specific icmp id value icmp_seq: specific icmp sequence value rpc: check Sun rpc, application, version, proc# in CALL requests post-detection rule options: ---------------------------- logto: log this rule to a special log file. logto: "filename" session: in tcp sessions either do: session: all - substitute non-printables with hex session: printable - show what user would see exactly resp: dynamically respond to various events with packets rst_snd: send TCP reset to sender rst_rcv: send TCP reset to recv. rst_all: send TCP reset to both parties. icmp_net: send icmp net unreachable to sender icmp_host: send icmp host unreachable to sender icmp_port: send icmp port unreachable to sender icmp_all: send all 3 unreachables to sender note: this must be configured/compiled into snort, not the default. react: higher-level response, e.g., block http accesses. block: close connection and send notice warn: send notice (not sure if this implemented yet?) msg: include msg text (react: block, msg;) proxy: use a proxy port to send the message react-comments: not configured in by default. Could cause a network loop. tag: overview: once rule is triggered, remaining packets in flow are tagged based on ip src, dst. tag: type, count, metric, [direction] type: session or host (from host that caused rule to trigger) count: number of units, see metric metric: packets or seconds preprocessors ------------- plugins can be put into snort to change its behavior run after packet decode run before detection engine, hence preprocessor snort in general is stateless, here we may do 1. data formatting 2. try to make snort more stateful include: 1. portscan detector 2. portscan ignorehosts 3. frag2 4. stream4 5. flow 6. flow-portscan 7. telnet decode 8. rpc decode 9. performance monitor (for snort) 10. HTTP inspect 11. back orifice detector Others may exist and latest version of snort should be checked out. load them in the config file: preprocessor name: options # detect back orifice preprocessor bo 1. portscan detector log start and end of portscan from single IP to logging. if log file is specified, logs dest ips and ports as well as scan type does single to single and single to many UDP or TCP port scans (not icmp host scans) portscan: