zoukankan      html  css  js  c++  java
  • 【转】snort

    转自《snort

    http://www.oschina.net/p/snort

    http://blog.csdn.net/zhoubl668/article/details/7321376

    http://www.xfocus.net/releases/200509/a824.html

    一、工作模式:(可以通过oschina.net下载《Snort 中文手册》

    • 嗅探器模式:
      • 仅仅是从网络上读取数据包并作为连续不断的流显示在终端上
      • ./snort -dev -i"网卡index"
    • 数据包记录器模式:
      • 把数据包记录到硬盘上
      • ./snort -dev -l ./log -h 192.168.1.0/24 -i"网卡index"
      • ./snort -dev -l ./log -b -i"网卡index"
      • ./snort -dv -r packet.log icmp -i"网卡index"
      • 抓获的报文,自动存储在./log下面,可以使用tcpdump,wireshark,snort等读取!(可以修改后缀为.cap,则可以直接打开了)
    • 网络入侵检测模式:
      • 分析网络数据流以匹配用户定义的一些规则,并根据检测结果采取一定的动作;
      • 引擎和规则是分别发布的;
      • 针对“rule”,使用AC多模匹配算法,AC算法可以保证对于给定的长度为n的文本,和模式集合P{p1,p2,...pm},在O(n)时间复杂度内,找到文本中的所有目标模式,而与模式集合的规模m无关;
      • ./snort -dev -l ./log -b -i"网卡index" -c 配置文件
      • 如windows上.snort.exe -dev -l ..log -b -i1 -c ..etcsnort.conf

    二、安装windows snort:(参考http://www.sybell.com.cn/jszx/296.html)

    • 下载*.exe版本的snort并安装;
    • 执行c:snortinsnort -W查看可以使用的ethernet网卡;
    • 此时可以使用“嗅探器模式”和“数据包记录器模式”;
    • 注册并下载试用版本的rules,解压的到rules和so_rules文件夹;
    • 在rules下添加了两个空文件white_list.rules和black_list.rules;
    • 修改C:Snortetc下的snort.conf文件,修改完成后可以使用“网络入侵检测模式”;
    修改snort.conf文件:
    1. 修改目录;
    2. 把执行出错的暂时注释掉!
    var RULE_PATH ../rules
    var SO_RULE_PATH ../so_rules
    var PREPROC_RULE_PATH ../preproc_rules
    var WHITE_LIST_PATH ../rules
    var BLACK_LIST_PATH ../rules
    dynamicpreprocessor directory /usr/local/lib/snort_dynamicpreprocessor/
    dynamicengine /usr/local/lib/snort_dynamicengine/libsf_engine.so
    dynamicdetection directory /usr/local/lib/snort_dynamicrules
    preprocessor normalize_ip4
    preprocessor normalize_tcp: ips ecn stream
    preprocessor normalize_icmp4
    preprocessor normalize_ip6
    preprocessor normalize_icmp6
    whitelist $WHITE_LIST_PATH/white_list.rules,
    blacklist $BLACK_LIST_PATH/black_list.rules
     
    var RULE_PATH c:snort ules
    var SO_RULE_PATH c:snortso_rules
    var PREPROC_RULE_PATH C:Snortpreproc_rules
    var WHITE_LIST_PATH c:snort ules
    var BLACK_LIST_PATH c:snort ules
    dynamicpreprocessor directory C:Snortlibsnort_dynamicpreprocessor
    dynamicengine C:Snortlibsnort_dynamicenginesf_engine.dll
    #dynamicdetection directory /usr/local/lib/snort_dynamicrules
    #preprocessor normalize_ip4
    #preprocessor normalize_tcp: ips ecn stream
    #preprocessor normalize_icmp4
    #preprocessor normalize_ip6
    #preprocessor normalize_icmp6
    whitelist $WHITE_LIST_PATHwhite_list.rules,
    blacklist $BLACK_LIST_PATHblack_list.rules

     三、snort参数

    FPUTS_BOTH ("Options: ");

    FPUTS_BOTH (" -A Set alert mode: fast, full, console, test or none "

    " (alert file alerts only) ");

    FPUTS_UNIX (" "unsock" enables UNIX socket logging (experimental). ");

    FPUTS_BOTH (" -b Log packets in tcpdump format (much faster!) ");

    FPUTS_BOTH (" -B <mask> Obfuscated IP addresses in alerts and packet dumps using CIDR mask ");

    FPUTS_BOTH (" -c <rules> Use Rules File <rules> ");

    FPUTS_BOTH (" -C Print out payloads with character data only (no hex) ");

    FPUTS_BOTH (" -d Dump the Application Layer ");

    FPUTS_UNIX (" -D Run Snort in background (daemon) mode ");

    FPUTS_BOTH (" -e Display the second layer header info ");

    FPUTS_WIN32(" -E Log alert messages to NT Eventlog. (Win32 only) ");

    FPUTS_BOTH (" -f Turn off fflush() calls after binary log writes ");

    FPUTS_BOTH (" -F <bpf> Read BPF filters from file <bpf> ");

    FPUTS_UNIX (" -g <gname> Run snort gid as <gname> group (or gid) after initialization ");

    FPUTS_BOTH (" -G <0xid> Log Identifier (to uniquely id events for multiple snorts) ");

    FPUTS_BOTH (" -h <hn> Set home network = <hn> "

    " (for use with -l or -B, does NOT change $HOME_NET in IDS mode) ");

    FPUTS_BOTH (" -H Make hash tables deterministic. ");

    FPUTS_BOTH (" -i <if> Listen on interface <if> ");

    FPUTS_BOTH (" -I Add Interface name to alert output ");

    FPUTS_BOTH (" -k <mode> Checksum mode (all,noip,notcp,noudp,noicmp,none) ");

    FPUTS_BOTH (" -K <mode> Logging mode (pcap[default],ascii,none) ");

    FPUTS_BOTH (" -l <ld> Log to directory <ld> ");

    FPUTS_BOTH (" -L <file> Log to this tcpdump file ");

    FPUTS_UNIX (" -M Log messages to syslog (not alerts) ");

    FPUTS_UNIX (" -m <umask> Set umask = <umask> ");

    FPUTS_BOTH (" -n <cnt> Exit after receiving <cnt> packets ");

    FPUTS_BOTH (" -N Turn off logging (alerts still work) ");

    FPUTS_BOTH (" -O Obfuscate the logged IP addresses ");

    FPUTS_BOTH (" -p Disable promiscuous mode sniffing ");

    printf (" -P <snap> Set explicit snaplen of packet (default: %d) ",

    DAQ_GetSnapLen());

    FPUTS_BOTH (" -q Quiet. Don't show banner and status report ");

    #ifndef WIN32

    FPUTS_BOTH (" -Q Enable inline mode operation. ");

    #endif

    FPUTS_BOTH (" -r <tf> Read and process tcpdump file <tf> ");

    FPUTS_BOTH (" -R <id> Include 'id' in snort_intf<id>.pid file name ");

    FPUTS_BOTH (" -s Log alert messages to syslog ");

    FPUTS_BOTH (" -S <n=v> Set rules file variable n equal to value v ");

    FPUTS_UNIX (" -t <dir> Chroots process to <dir> after initialization ");

    FPUTS_BOTH (" -T Test and report on the current Snort configuration ");

    FPUTS_UNIX (" -u <uname> Run snort uid as <uname> user (or uid) after initialization ");

    FPUTS_BOTH (" -U Use UTC for timestamps ");

    FPUTS_BOTH (" -v Be verbose ");

    FPUTS_BOTH (" -V Show version number ");

    FPUTS_WIN32(" -W Lists available interfaces. (Win32 only) ");

    #if defined(NON_ETHER_DECODER) && defined(DLT_IEEE802_11)

    FPUTS_BOTH (" -w Dump 802.11 management and control frames ");

    #endif

    FPUTS_BOTH (" -X Dump the raw packet data starting at the link layer ");

    FPUTS_BOTH (" -x Exit if Snort configuration problems occur ");

    FPUTS_BOTH (" -y Include year in timestamp in the alert and log files ");

    FPUTS_BOTH (" -Z <file> Set the performonitor preprocessor file path and name ");

    FPUTS_BOTH (" -? Show this information ");

    FPUTS_BOTH ("<Filter Options> are standard BPF options, as seen in TCPDump ");

    FPUTS_BOTH ("Longname options and their corresponding single char version ");

    FPUTS_BOTH (" --logid <0xid> Same as -G ");

    FPUTS_BOTH (" --perfmon-file <file> Same as -Z ");

    FPUTS_BOTH (" --pid-path <dir> Specify the directory for the Snort PID file ");

    FPUTS_BOTH (" --snaplen <snap> Same as -P ");

    FPUTS_BOTH (" --help Same as -? ");

    FPUTS_BOTH (" --version Same as -V ");

    FPUTS_BOTH (" --alert-before-pass Process alert, drop, sdrop, or reject before pass, default is pass before alert, drop,... ");

    FPUTS_BOTH (" --treat-drop-as-alert Converts drop, sdrop, and reject rules into alert rules during startup ");

    FPUTS_BOTH (" --treat-drop-as-ignore Use drop, sdrop, and reject rules to ignore session traffic when not inline. ");

    FPUTS_BOTH (" --process-all-events Process all queued events (drop, alert,...), default stops after 1st action group ");

    FPUTS_BOTH (" --enable-inline-test Enable Inline-Test Mode Operation ");

    FPUTS_BOTH (" --dynamic-engine-lib <file> Load a dynamic detection engine ");

    FPUTS_BOTH (" --dynamic-engine-lib-dir <path> Load all dynamic engines from directory ");

    FPUTS_BOTH (" --dynamic-detection-lib <file> Load a dynamic rules library ");

    FPUTS_BOTH (" --dynamic-detection-lib-dir <path> Load all dynamic rules libraries from directory ");

    FPUTS_BOTH (" --dump-dynamic-rules <path> Creates stub rule files of all loaded rules libraries ");

    FPUTS_BOTH (" --dynamic-preprocessor-lib <file> Load a dynamic preprocessor library ");

    FPUTS_BOTH (" --dynamic-preprocessor-lib-dir <path> Load all dynamic preprocessor libraries from directory ");

    FPUTS_BOTH (" --dynamic-output-lib <file> Load a dynamic output library ");

    FPUTS_BOTH (" --dynamic-output-lib-dir <path> Load all dynamic output libraries from directory ");

    FPUTS_UNIX (" --create-pidfile Create PID file, even when not in Daemon mode ");

    FPUTS_UNIX (" --nolock-pidfile Do not try to lock Snort PID file ");

    #ifdef INLINE_FAILOPEN

    FPUTS_UNIX (" --disable-inline-init-failopen Do not fail open and pass packets while initializing with inline mode. ");

    #endif

    #ifdef TARGET_BASED

    FPUTS_UNIX (" --disable-attribute-reload-thread Do not create a thread to reload the attribute table ");

    #endif

    FPUTS_BOTH (" --pcap-single <tf> Same as -r. ");

    FPUTS_BOTH (" --pcap-file <file> file that contains a list of pcaps to read - read mode is implied. ");

    FPUTS_BOTH (" --pcap-list "<list>" a space separated list of pcaps to read - read mode is implied. ");

    FPUTS_UNIX (" --pcap-dir <dir> a directory to recurse to look for pcaps - read mode is implied. ");

    FPUTS_UNIX (" --pcap-filter <filter> filter to apply when getting pcaps from file or directory. ");

    FPUTS_UNIX (" --pcap-no-filter reset to use no filter when getting pcaps from file or directory. ");

    FPUTS_BOTH (" --pcap-loop <count> this option will read the pcaps specified on command line continuously. "

    " for <count> times. A value of 0 will read until Snort is terminated. ");

    FPUTS_BOTH (" --pcap-reset if reading multiple pcaps, reset snort to post-configuration state before reading next pcap. ");

    #if defined(SNORT_RELOAD) && !defined(WIN32)

    FPUTS_BOTH (" --pcap-reload if reading multiple pcaps, reload snort config between pcaps. ");

    #endif

    FPUTS_BOTH (" --pcap-show print a line saying what pcap is currently being read. ");

    FPUTS_BOTH (" --exit-check <count> Signal termination after <count> callbacks from DAQ_Acquire(), showing the time it "

    " takes from signaling until DAQ_Stop() is called. ");

    FPUTS_BOTH (" --conf-error-out Same as -x ");

    #ifdef MPLS

    FPUTS_BOTH (" --enable-mpls-multicast Allow multicast MPLS ");

    FPUTS_BOTH (" --enable-mpls-overlapping-ip Handle overlapping IPs within MPLS clouds ");

    FPUTS_BOTH (" --max-mpls-labelchain-len Specify the max MPLS label chain ");

    FPUTS_BOTH (" --mpls-payload-type Specify the protocol (ipv4, ipv6, ethernet) that is encapsulated by MPLS ");

    #endif

    FPUTS_BOTH (" --require-rule-sid Require that all snort rules have SID specified. ");

    FPUTS_BOTH (" --daq <type> Select packet acquisition module (default is pcap). ");

    FPUTS_BOTH (" --daq-mode <mode> Select the DAQ operating mode. ");

    FPUTS_BOTH (" --daq-var <name=value> Specify extra DAQ configuration variable. ");

    FPUTS_BOTH (" --daq-dir <dir> Tell snort where to find desired DAQ. ");

    FPUTS_BOTH (" --daq-list[=<dir>] List packet acquisition modules available in dir. Default is static modules only. ");

    FPUTS_BOTH (" --dirty-pig Don't flush packets and release memory on shutdown. ");

    FPUTS_BOTH (" --cs-dir <dir> Directory to use for control socket. ");

    FPUTS_BOTH (" --ha-peer Activate live high-availability state sharing with peer. ");

    FPUTS_BOTH (" --ha-out <file> Write high-availability events to this file. ");

    FPUTS_BOTH (" --ha-in <file> Read high-availability events from this file on startup (warm-start). ");

    #undef FPUTS_WIN32

    #undef FPUTS_UNIX

    #undef FPUTS_BOTH

    补充阅读

    http://www.xfocus.net/releases/200509/a824.html

    ----------------------------------------------------------------------------------------
    2.5.1 content选项

    content选项是Snort提供的多个选项中比较重要的一个。它可以使用户搜索数据包净载中特定的内容并相引发相应的动作。当执行一个content选项匹配时,程序调用Boyer-Moore模式匹配例程检查包内容中是否包含了此内容,如果选项中指定的数据正好包含在数据包的净载中,那么检查返回成功,规则中其他的选项会继续得以执行。需要小心的是默认的content选项匹配是关心大小写的。

    选项中指定的数据可能会比较复杂;它可能包含混和的文本和二进制数据。二进制数据通常用管道(|)符号括起来并以字节码的方式指定。字节码是以十六进制的格式表示的,这样可以很方便地描述复杂的二进制数据。示例的Snort规则中就包含了混合的文本及二进制数据。

    在一条规则可以指定多个content选项,这样可以使规则尽可能少地出现误报的情况。

    如下字符在content选项内容中出现时必须被转义(如何转义至少在这个手册里的此节没说,我补充一下,有两个方法:1. 使用前导“”字符 2. 使用字节的二进制表示方式,比如用“|3A|”表示“:”):

    : ; "

    如果content选项内容之前放置了“!”字符,则表示在数据中不包含选项内容时引发报警。

    2.5.1.1 格式

    content: [!] "<content string>";

    content选项可以带有多个修饰选项。修饰选项可以影响紧接之前的content选项的工作方式,这些修饰选项如下:

    1. 
    nocase 
    2. 
    rawbytes 
    3. 
    depth 
    4. 
    offset
    5. 
    distance 
    6. 
    within 

    2.5.1.2 示例

    alert tcp any any -> any 139 (content:"|5c 00|P||00|I|00|P|00|E|00 5c|";)
    混和了二进制数据和文本的content选项内容

    alert tcp any any -> any 80 (content:!"GET";depth:3;nocase;) 
    取反匹配,此规则匹配数据包净载的前三个字节不是“GET”的情况

    2.5.2 nocase修饰选项

    nocase选项修饰紧接之前的content选项,使之在匹配时忽略大小写。

    2.5.2.1 格式

    nocase;

    2.5.2.2 示例

    alert tcp any any -> any 21 (msg:"FTP ROOT"; content:"USER root"; nocase;)
    带有nocase修饰选项的content规则

    2.5.3 rawbytes修饰选项

    rawbytes选项修饰紧接之前的content选项,使之只匹配最原始的数据,忽略那些预处理器所做的解码。

    2.5.3.1 格式

    rawbytes;

    2.5.3.2 示例

    alert tcp any any -> any 21 (msg: "Telnet NOP"; content: "|FF F1|"; rawbytes;)
    上面的示例使content选项匹配最原始的网络流量,而不是经过telnet解码器解码后的数据。

    2.5.4 depth修饰选项

    depth选项修饰紧接之前的content选项,允许用户指定在数据区中搜索特定模式的深度。如果设置depth等于5,则表示在数据包净载中从某个起点(如果没有下面论及的另一个offset修饰选项,则默认为数据区净载的开头)开始的5个字节中匹配content选项内容指定的模式。

    2.5.4.1 格式

    depth: <字节数>;

    2.5.5 offset修饰选项

    offset选项修饰紧接之前的content选项,允许用户指定从数据包净载的哪个字节开始进行匹配。如果设置offset等于5,Snort会在数据区净载的前5个字节以后开始搜索content选项内容指定的模式。

    2.5.5.1 格式

    offset: <字节数>;

    alert tcp any any -> any 80 (content: "cgi-bin/phf"; offset:4; depth:20;)
    组合使用了content,offset,depth选项的规则,从数据包净载的第5个字节开始的20字节内查找“cgi-bin/phf”字串。

    2.5.6 distance

    distance选项修饰紧接之前的content选项,允许用户指定相对于上一个content选项匹配成功的串尾再加多少字节开始搜索distance所修饰的这个content选项指定的匹配内容。此修饰选项与offset类似,只不过是相对于上一个content选项匹配成功的串尾而不是相对于数据区净载的开头。

    2.5.6.1 格式

    distance: <字节数>;

    2.5.6.2 示例

    alert tcp any any -> any any (content:"ABC"; content: "DEF";distance:1;)
    此规则示例匹配的目的相当于正则表达式:/ABC.{1}DEF/

    2.5.7 within

    within选项修饰紧接之前的content选项,允许用户指定从上一个content选项匹配成功的串尾加上distance选项指定的字节数开始多少字节内搜索当within所修饰的这个content选项指定的匹配内容。此修饰选项与depth类似,只不过是相对于上一个content选项匹配成功的串尾加distance选项指定的字节数而不是相对于数据区净载的开头。

    2.5.7.1 格式

    within: <字节数>;

    2.5.7.2 示例

    alert tcp any any -> any any (content:"ABC"; content: "EFG"; within:10;)

    2.5.8 uricontent

    uricontent选项用于匹配正规化处理后URI字段。这意味着如果你写规则试图去匹配那些可能会被正规化处理掉的数据,比如常见用于遍历目录的“%2f”串,那么匹配就会失败。

    举例如下,URI:
    /scripts/..%c0%af../winnt/system32/cmd.exe?/c+ver
    会被正规化为:
    /winnt/system32/cmd.exe?/c+ver

    /cgi-bin/aaaaaaaaaaaaaaaaaaaaaaaaaa/..%252fp%68f?
    会被正规化为:
    /cgi-bin/phf?

    用uricontent选项写规则的时候必须指定匹配正规化以后的内容,不能包含遍历目录的字串,因为这些会被正规则化掉。如果想匹配正规化以前的数据请使用content选项。

    uricontent与HTTP检测预处理器结合使用。

    2.5.8.1 格式

    uricontent:[!]<content string>;

    2.5.9 isdataat选项

    此选项用于确认在指定的位置有多少字节的数据,有修饰选项指定相对于上一个content选项匹配成功的串尾开始。

    2.5.9.1 格式

    isdataat:<int>[,relative];

    2.5.9.2 示例

    alert tcp any any -> any 111 (content:"PASS"; isdataat:50,relative; content:!"|0a|"; distance:0;)
    此规则在数据区净载中搜索“PASS”字串,然后再确认至少在后面还有50字节的数据,并且不包含换行符。

    2.5.10 pcre选项

    pcre选项允许用户使用与PERL语言相兼容的正则表达式。相关正则表达式的具体细节参看PCRE的Web站点:http://www.pcre.org

    2.5.10.1 格式

    pcre:[!]"(/<regex>/|m<delim><regex><delim>)[ismxAEGRUB]";

    在表达式后的修饰符设置编译正则表达式的一些标志。

    Perl兼容的修饰符
    +-+---------------------------------------------+
    |i| 对大小不敏感                                |
    +-+---------------------------------------------+
    |s| 在点转义符号中包含换行符                    |
    +-+---------------------------------------------+
    | | 一般情况下被匹配的缓冲区是作为一个大字符串  |
    |m| 的,^和$分别匹配串头和串尾。当设置了m修饰   |
    | | 符,^和$匹配跟紧跟换行符和紧先导于换行符的  |
    | | 情况。                                      |
    +-+---------------------------------------------+
    |x| 要匹配的模式中的空格符被忽略,除非是被转义  |
    | | 过的或在一个字符集中。                      |
    +-+---------------------------------------------+

    PCRE兼容的修饰符
    +-+---------------------------------------------+
    |A| 模式必须在缓冲区的开头匹配到(同^)         |
    +-+---------------------------------------------+
    | | 设置指定的$必须匹配到缓冲区末尾。如果不用E  |
    |E| 修饰符,$则可能只匹配到串尾之前换行符。     |
    +-+---------------------------------------------+
    |G| 在默认情况下不使用“贪婪”模式,只有在模式后  |
    | | 面跟了“?”字符的情况下贪婪。                 |
    +-+---------------------------------------------+

    Snort特定的修饰符
    +-+---------------------------------------------+
    |R| 此匹配相对于前一个匹配成功串尾开始          |
    | | (类似于distance:0)                          |
    +-+---------------------------------------------+
    |U| 匹配解码后的URI缓冲区(类似于uricontent)   |
    +-+---------------------------------------------+
    |B| 不使用解码后的缓冲区(类似于rawbytes)      |
    +-+---------------------------------------------+

    修饰符R和B不能同时使用。

    2.5.10 示例

    alert ip any any -> any any (pcre:"/BLAH/i";)

    2.5.11 byte_test修饰符

    把数据包净载中特定位置的字串转换为数值类型与指定的值进行比较。

    2.5.11 格式

    byte_test: <bytes_to_convert>, <operator>, <value>, <offset> [, [relative],[big],[little],[string],[hex],[dec],[oct]]

    bytes_to_convert
         抽取的字节数
    operator
         要执行的操作符(<,>,=,!,&)
    value
         与从转换出来的数据进行比较的值
    relative
         相对于从上次成功匹配的串尾开始
    big
         以big endian字节序方式处理
    little
         以little endian字节序方式处理
    string
         被转换的数据在包里是以字符串方式储存的
    hex
         转换出来的数据以十六进制表示
    dec
         转换出来的数据以十进制表示
    oct
         转换出来的数据以八进制表示

    2.5.11.2 示例

    alert udp any any -> any 1237 (byte_test: 10, =, 1234567890, 0, string, dec; msg:"got 1234567890!";)
    alert udp any any -> any 1238 (byte_test: 8, =, 0xdeadbeef, 0, string, hex; msg:"got DEADBEEF!";)

    2.5.12 byte_jump选项

    byte_jump选项用来从数据包的某个位置获取一些字节,转换成数值类型,跳过数值里显示的字节数到数据包里新位置进行进一步的匹配操作。这样可以利用网络数据包里的数据进行相对位置的跳转。

    2.5.12.1 格式

    byte_jump: <bytes_to_convert>, <offset> [, [relative],[big],[little],[string],[hex],[dec],[oct],[align]]


    bytes_to_convert 
         要转换的字节数
    offset 
         从数据区净载的哪个位置开始处理
    relative 
         从上次成功匹配的串尾开始
    big 
         以big endian字节序方式处理(默认) 
    little 
         以little endian字节序方式处理
    string 
         被转换的数据在包里是以字符串方式储存的 
    hex
         转换出来的数据以十六进制表示
    dec
         转换出来的数据以十进制表示
    oct
         转换出来的数据以八进制表示
    align 
         把转换出来的数值圆整到32-bit边界的值 

    2.5.12.2 示例

    alert udp any any -> any 32770:34000 (content: "|00 01 86 b8|"; content: "|00 00 00 01|"; distance: 4; within: 4; byte_jump: 4, 12, relative, align; byte_test: 4, >, 900, 20, relative; msg: "statd format string buffer overflow";)

    2.5.13 regex

    regex选项已经被PCRE选项所代替

    2.5.14 content-list

    content-list选项已经被废弃。
    ----------------------------------------------------------------------------------------


    下面对新版Snort的规则选项作些分析。

    与之前版本的Snort相比,新版规则主要有以下几个具体的改进:

    1. 给content选项增加了distance和within修饰选项
    2. 增加了isdataat选项
    3. 增加了byte_jump选项
    4. 增加了byte_test选项
    5. 改进了正则表达式

    其增加的核心功能就是引入了数据匹配相对偏移的概念。以往写Snort规则碰上的最大限制就是对于数据包内容的匹配我们必须硬编码进模式可能在数据包净载中可能出现的位置,由于网络协议的灵活性及数据包分片的可能性,我们所要匹配的数据在数据包净载中的偏移并不容易确定,这就会引起很大的漏报或误报。

    比如对于MDaemon form2raw.cgi溢出攻击的检测,一个攻击请求的数据包净载可以用如下的正则表达来匹配:
    [GET|HEAD|POST]s+S*/form2raw.cgi[?|s]S*From=[^&]{100,}

    如果使用以前版本的Snort规则选项,由于要匹配的模式是只能实现如下的规则:
    alert tcp !$HOME_NET any -> $HOME_NET 3000 (msg:"MDaemon form2raw.cgi overflow attack!";content:"/form2raw.cgi";nocase;content:"From=";nocase;offset:17;depth:15;content:!"&";offset:30;depth:120;)

    这样的规则只能检测如下比较“正常”的攻击净载情况:
    "GET /form2raw.cgi?From=AAA...AAA&To=me@hello.org&Subject=hi&Body=hello HTTP/1.0"

    不考虑各种对抗IDS的URI变形方式,就是仅仅在“/form2raw.cgi”前带了比较长目录的情况就会导致漏报,但我们也不能过度扩大对“From=”串的搜索范围,因为那样可能会带来更多的误报。

    content选项新增的distance和within修饰选项,可以使匹配多个有一定顺序和固定间隔的模式成为可能,这对于匹配网络流量中那些结构相对固定的协议头结构(比如SMB,Sun-RPC,DNS等)非常有用,可以很方便地检查结构中的某些字段。

    对于上面的form2raw.cgi检测例子,借助于content的新修饰选项,我们可以把规则改进为如下的形式:

    alert tcp !$HOME_NET any -> $HOME_NET 3000 (msg:"MDaemon form2raw.cgi overflow attack!";content:"/form2raw.cgi";nocase;content:"From=";nocase;distance:1;content:!"&";within:120;)

    这样,不管“From=”串在数据包净载中的偏移如何,我们可以都以保证检测到接于其后超长的参数串了,极大地提高了检测的准确性。

    新增的isdataat主要用于判断相对某个匹配后面还有多少的数据,主要用于类似FTP的协议命令后的参数是否超长,由于isdataat判断开始的偏移是相对的,这比以前判断整个净载长度的办法要精确的多,因为一个净载里可能包含了多个命令,而且在命令之前可能还有数据。

    新增的byte_jump选项是非常强大的,使用它可以使我们动态地根据网络数据包中值来选择匹配开始的偏移成为可能,实际上这样已经部分地实现了协议解码的能力,我们可以根据协头中包含的字段偏移信息来直接定位我们关心的字段在数据包中的位置,可以实现非常精确地匹配。有关此选项会在下面结合例子详细介绍。

    新增的byte_test选项主要用于检查可能的协议数据结构中某些字段的值大小,最常见的就是某个串的长度。有关此选项会在下面结合例子详细介绍。

    新版的Snort加强了正则表达式,在很多规则里普遍使用了正则表达式。

    下面介绍一个结合使用了多个选项的rpc.statd格式串攻击的规则来演示新规则选项的强大特性。

    一个rpc.statd攻击数据包可能是如下这个样子,攻击者使用一个带有超长的格式串参数的rpc.statd包来利用格式串攻击来获取Linux系统的root用户权限:

    Frame 3 (1118 bytes on wire, 1118 bytes captured)
    Ethernet II, Src: 00:06:5b:9f:95:37, Dst: 00:01:02:86:a6:f3
    Internet Protocol, Src Addr: 192.168.5.223 (192.168.5.223), Dst Addr: 202.99.11.220 (202.99.11.220)
    User Datagram Protocol, Src Port: 816 (816), Dst Port: 32770 (32770)
    Remote Procedure Call, Type:Call XID:0x42688ef6
        XID: 0x42688ef6 (1114148598)
        Message Type: Call (0)
        RPC Version: 2
        Program: STAT (100024)
        Program Version: 1
        Procedure: STAT (1)
        The reply to this request is in frame 4
        Credentials
            Flavor: AUTH_UNIX (1)
            Length: 32
            Stamp: 0x3db04376
            Machine Name: localhost
                length: 9
                contents: localhost
                fill bytes: opaque data
            UID: 0
            GID: 0
            Auxiliary GIDs
        Verifier
            Flavor: AUTH_NULL (0)
            Length: 0
    Network Status Monitor Protocol
        Program Version: 1
        V1 Procedure: STAT (1)
        Name: ????????????????8x%8x%8x%8x%8x%8x%8x%8x%8x%236x%n%137x%n%10x%n%192x%n悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙?
            length: 999
            contents: ????????????????8x%8x%8x%8x%8x%8x%8x%8x%8x%236x%n%137x%n%10x%n%192x%n悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙?
            fill bytes: opaque data

    0000  00 01 02 86 a6 f3 00 06 5b 9f 95 37 08 00 45 00   ........[..7..E.
    0010  04 50 00 00 40 00 01 11 d8 d6 c0 a8 05 df ca 63   .P..@..........c
    0020  0b dc 03 30 80 02 04 3c 58 79 42 68 8e f6 00 00   ...0...<XyBh....
    0030  00 00 00 00 00 02 00 01 86 b8 00 00 00 01 00 00   ................
    0040  00 01 00 00 00 01 00 00 00 20 3d b0 43 76 00 00   ......... =.Cv..
    0050  00 09 6c 6f 63 61 6c 68 6f 73 74 00 00 00 00 00   ..localhost.....
    0060  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
    0070  00 00 00 00 03 e7 18 f7 ff bf 18 f7 ff bf 19 f7   ................
    0080  ff bf 19 f7 ff bf 1a f7 ff bf 1a f7 ff bf 1b f7   ................
    0090  ff bf 1b f7 ff bf 25 38 78 25 38 78 25 38 78 25   ......%8x%8x%8x%
    00a0  38 78 25 38 78 25 38 78 25 38 78 25 38 78 25 38   8x%8x%8x%8x%8x%8
    00b0  78 25 32 33 36 78 25 6e 25 31 33 37 78 25 6e 25   x%236x%n%137x%n%
    00c0  31 30 78 25 6e 25 31 39 32 78 25 6e 90 90 90 90   10x%n%192x%n....
    00d0  90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90   ................
                              ...
                              ...
    03c0  90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90   ................
    03d0  90 90 90 90 90 90 90 90 31 c0 eb 7c 59 89 41 10   ........1..|Y.A.
    03e0  89 41 08 fe c0 89 41 04 89 c3 fe c0 89 01 b0 66   .A....A........f
    03f0  cd 80 b3 02 89 59 0c c6 41 0e 99 c6 41 08 10 89   .....Y..A...A...
    0400  49 04 80 41 04 0c 88 01 b0 66 cd 80 b3 04 b0 66   I..A.....f.....f
    0410  cd 80 b3 05 30 c0 88 41 04 b0 66 cd 80 89 ce 88   ....0..A..f.....
    0420  c3 31 c9 b0 3f cd 80 fe c1 b0 3f cd 80 fe c1 b0   .1..?.....?.....
    0430  3f cd 80 c7 06 2f 62 69 6e c7 46 04 2f 73 68 41   ?..../bin.F./shA
    0440  30 c0 88 46 07 89 76 0c 8d 56 10 8d 4e 0c 89 f3   0..F..v..V..N...
    0450  b0 0b cd 80 b0 01 cd 80 e8 7f ff ff ff 00         ..............

    Snort的演示规则对于此rpc.statd溢出攻击如下:
    alert udp any any -> any 32770:34000 (content: "|00 01 86 b8|"; content: "|00 00 00 01|"; distance: 4; within: 4; byte_jump: 4, 12, relative, align; byte_test: 4, >, 900, 20, relative; msg: "statd format string buffer overflow";)

    在分析规则之前贴一下来自《TCP/IP Illustrated》的Sun-RPC协议的头结构:

    +----------------------+
    | transaction ID (XID) |  4字节
    +----------------------+
    |        call(0)       |  4字节
    +----------------------+
    |    RPC version(2)    |  4字节
    +----------------------+
    |    program number    |  4字节
    +----------------------+
    |    version number    |  4字节
    +----------------------+
    |   procedure number   |  4字节
    +----------------------+
    |                      |
    |      credentials     |
    |                      |
    +----------------------+
    |                      |
    |       verifier       |
    |                      |
    +----------------------+
    |                      |
    |     procedure        |
    |     parameters       |
    |        ...           |
    |                      |
    +----------------------+

    Snort的演示规则由两个content选项、一个byte_jump选项、一个byte_test选项组成。

    第一个content选项:content: "|00 01 86 b8|",用于匹配SunRPC头结构中的program number:x00x01x86xb8 代表网络字节序的100024,100024是statd的程序号。这个串在上例攻击包中的偏移是0x36 。

    第二个content选项:content: "|00 00 00 01|"; distance: 4; within: 4; ,表示从上一次匹配成功的串尾开始,在上例中攻击包的0x3a开始,跳过4个字节,从那儿开始匹配4个字节,也就是说从偏移为0x3e的地方开始匹配4个字节是不是x00x00x00x01。从上面的结构看跳过的是version number,因为我们不关心那个,匹配的目标就是procedure number,如果是0x00000001,则表示是STAT过程。

    第三个是byte_jump选项:byte_jump: 4, 12, relative, align; ,表示从上一次匹配成功的串尾开始,在上例中攻击包的0x3e+0x04=0x42开始,跳过12个字节,也就是0x42+12=0x4e的偏移开始取4个字节,转换成整数并圆整到4的倍数,然后从0x4e+0x04=0x52开始跳过转换出来的整数个字节。从上例的攻击包来看偏移0x4e开始的四个字节转换为网络字节序的值是0x00000009,圆整到4的整数为12,也就是说引擎下一次匹配开始的偏移会跳到0x4e+4+12=0x5e地方开始。这个byte_jump操作的目的是跳过长度不确定的STAT过程的主机名字段。

    第四个是byte_test选项:byte_test: 4, >, 900, 20, relative; ,表示当前的指针开始,也就是上面byte_jump跳到的0x5e偏移开始,跳过20字节,也就是从0x5e+20=0x72偏移开始,取4个字节转换成整数与900比较,如果大于则满足本规则的最后一个条件。从上例的攻击包数据来看,从偏移0x72开始取的四个字节转变出来的值是0x000003e7=999,大于900,所以是一个攻击。跳过的那20个字节从ethereal解码来看分别是UID、GID、Auxiliary GIDS、Flavor、Length字段,它们都是4字节长的,总共20字节。

    以下是规则对ethereal解码的数据包的匹配要点:

    Remote Procedure Call, Type:Call XID:0x42688ef6
        XID: 0x42688ef6 (1114148598)
        Message Type: Call (0)
        RPC Version: 2
        Program: STAT (100024)    ; content: "|00 01 86 b8|" , 0x0186b8==100024
        Program Version: 1        ; 跳过这4个字节,由第二个content选项的 distance:4 修饰选项表示这个意思
        Procedure: STAT (1)       ; content: "|00 00 00 01|"; distance: 4; within: 4;
        The reply to this request is in frame 4
        Credentials
            Flavor: AUTH_UNIX (1)
            Length: 32
            Stamp: 0x3db04376
            Machine Name: localhost
                length: 9         ; byte_jump: 4, 12, relative, align; 从这取四个字节转换成整数跳过
                contents: localhost
                fill bytes: opaque data
            UID: 0
            GID: 0
            Auxiliary GIDs
        Verifier
            Flavor: AUTH_NULL (0)
            Length: 0
    Network Status Monitor Protocol
        Program Version: 1
        V1 Procedure: STAT (1)
        Name: ????????????????8x%8x%8x%8x%8x%8x%8x%8x%8x%236x%n%137x%n%10x%n%192x%n悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙?
            length: 999         ; byte_test: 4, >, 900, 20, relative; 跳过之前的20字节,在这取四个字节转变成整数,与900比较,如果大于,则认定为攻击。
            contents: ????????????????8x%8x%8x%8x%8x%8x%8x%8x%8x%236x%n%137x%n%10x%n%192x%n悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙悙?
            fill bytes: opaque data

    总结:

    新版Snort规则选项引入的相对偏移概念很大程度上提高了攻击检测规则的灵活性和准确性,特别是byte_jump选项的引入部分弥补了Snort不进行应用层协议解码的弱点。

  • 相关阅读:
    bzoj5253 [2018多省省队联测]制胡窜
    bzoj5249 [2018多省省队联测]IIIDX
    bzoj5248 [2018多省省队联测]一双木棋
    HEOI2018 游记
    bzoj2720 [Violet 5]列队春游
    bzoj4871 [Heoi2017]摧毁“树状图”
    bzoj3991 [SDOI2015]寻宝游戏
    bzoj3598 [Scoi2014]方伯伯的商场之旅
    Flash平台的分析与RIA的趋势
    JavaScript的变量预解析特性
  • 原文地址:https://www.cnblogs.com/Lthis/p/4950132.html
Copyright © 2011-2022 走看看