网络安全 频道

IPS/IDS特征识别和签名或规则编写

总结一下:检测SMTP主要的威胁主要是破解和溢出,SNORT签名存在固有的弱点,我们在做分析的时候要多考虑以下几个要素:

a)       破解本身要基于时间统计来做检测,不能单独的只检测一个expn root或其他

b)      溢出的检测要基于其原理来分析,不能只做某个溢出工具的检测

 

F)      SMB微软网络共享协议的特征和识别

1)      SMB登陆检测

my_schema = library_schema:new(1, ["time", "ip", "int", "ip", "int", "str"],

       scope());

my_recorder = recorder ("bin/list %c", "my_schema");

_:reg_callback(ssax_client, "SMB", 0x73, "CLIENT");

_:reg_callback(ssax_server, "SMB", 0x73, "SERVER");

func reg_callback {

       # Register callbacks for guest accounts. Called functions will be called

       # with no arguments.

       # Pass in: Function to call.

       CALL_GUEST_ACCOUNT = listadd(CALL_GUEST_ACCOUNT, $1);

}

func ssax_client {

       declare $Username inside tcp.connsym;

       if (!$2)

              $wco = 36;

       else

              $wco = $2;

      

       $SMBBlob = $1;

       $word_count = byte($SMBBlob, $wco);

       # post NTLM 0.12, without extended security bit set word count == 13

       if ($word_count == 13) {

              $ansi_pw_len = le_ushort($SMBBlob, $wco + 15);

              $unicode_pw_len = le_ushort($SMBBlob, $wco + 17);

              $tmp_offset = $wco + 30 + $ansi_pw_len + $unicode_pw_len;

              if (($tmp = substr($SMBBlob, $tmp_offset, (_:absindex($SMBBlob,

                     "\x00\x00", $tmp_offset) + 1) - $tmp_offset))

                     == "\x00" ) {

                     $Username = "NULL_UID";

              } else {

                     $Username = _:shrink($tmp, "\x00");

              }

       }

       # pre NTLM 0.12 word count should be 10.

       else if ($word_count == 10) {

              # ANSI password should be the first item in the ByteCount

              # buffer.

              $pw_len = le_ushort($SMBBlob, $wco + 15);

              if ($pw_len == 0) {

                     #NULL PASSWORD?

              }

              $tmp = substr($SMBBlob, $wco + 23 + $pw_len);

              if (prefix($tmp, "\x00")) {

                     $Username = "NULL_UID";

              } else {

                     $Username = _:shrink($tmp, "\x00");

              }

       }

       ##else if ($word_count == 12) { ##NTLMSSP Challenge Response }

}

func ssax_server {

       $SMBBlob = $1;

       # A NULL long() int the NT Status field indicates success.

       $errors = le_long($SMBBlob, 9);

       if ($errors == -1073741802) {

              #NTLMSSP Chalenge Response

              #NT STATUS MSG MORE PROCCESSING REQUIRED

              return;

       }

       declare $Username inside tcp.connsym;

       if ($Username == "NULL_UID" || $Username == "GUEST") {

              # foreach guest account callback inside those things

              foreach $c inside (CALL_GUEST_ACCOUNT) {

                     ($c)();

              }

       }

       if (SMB_LOGIN_NOTIFY_AUTHENTICATION) {

              if ($errors == 0) {

                     #SUCCESSFUL LOGIN

                     $authblob["STATUS"] = 1;

              } else {

                     #FAILED LOGIN

                     $authblob["STATUS"] = 0;

              }

              $authblob["IP_ADDR_SRC"] = tcp.connsrc;

              $authblob["IP_ADDR_DST"] = tcp.conndst;

              $authblob["PASSWORD"] = -1;

              $authblob["USERNAME"] = $Username;

              $authblob["SERVICE_NAME"] = "SMB";

              authentication_authentication:authdata($authblob);

       }

}

这里申明一点微软的SMB协议格式是未公开的,现在根本没有好的解码办法,这里写的用户名的检测是根据SMB包里的UNICODE编码转化成ASCII的字符的,本身SMB的用户名是可读的,但是密码是没办法的,密码是被HASH的

密码登陆成功与否的状态也是可读的,就是用SNORT来写规则也是可以作到的

总结一下:目前SMB协议的解码都是难题,这里的SMB登陆检测

也是用没办法的办法做的,其他一些比如SSH,HTTPS等的协议也是有一些没办法的办法来做一些事情的,也是可以考虑导进一些默认证书的办法,可以做一定层次的DECODE的

G)     基于统计的签名的特征和开发

1)      WEBCC检测

这里说一下NFR的引擎的内置函数timeout:

filter checkem timeout (sec: INTERVAL, repeat)

这个内置函数在SENSOR上是作为一个定时器的作用,没有它,我们没办法做基于时间特征的统计.我们这里就不详细解释webcc的写法了,下面还会提到.

NFR的引擎还有内置函数except,exception,也就是运行NCODE或处理协议栈异常的时候调用的,在下面的SYNFLOOD的检测代码里用到的.

总结一下:我们一般使用到与时间有关系的统计签名的时候请大家考虑一下timeout函数,遇到代码异常可以考虑except

H)     基于协议异常的特征的开发和编写

1)      SYNFLOOD

filter synflood except (tcpsynacktimeout) {

       if (tcp.connsyn) {

              if (!SynTimeoutCnt[tcp.connsrc]) {

                     SynTimeoutCnt[tcp.connsrc] = 1;

              } else {

                     SynTimeoutCnt[tcp.connsrc] = SynTimeoutCnt[tcp.connsrc] + 1;

              }

      

              # grab packets if we’re gonna alert

              if (!Context[tcp.connsrc] && SynTimeoutCnt[tcp.connsrc] > THRESHOLD) {

                     Context[tcp.connsrc] = attack:context(synflood_alert);

                     if (AGGRESSIVE_PREVENTION)

                            announce_synflood();

              }

       }

       debug:trace("synflood: ",tcp.connsrc,  Context[tcp.connsrc], SynTimeoutCnt[tcp.connsrc]);

}

上面说的意思是统计半开放连接的个数是否超过上限

filter synflood_is_working except (tcpsyntimeout) {

       debug:trace("tcp syn timeout", tcp.connsrc, Context[tcp.connsrc], FloodTimer[Context[tcp.connsrc]]);

       if (Context[tcp.connsrc] && !FloodTimer[Context[tcp.connsrc]]) {

              announce_synflood();

              FloodTimer[Context[tcp.connsrc]] = system.time;

              StartTime[system.time] = listadd(StartTime[system.time], tcp.connsrc);

       }

}

跟踪每个半开放连接的超时时间

在SNORTRULES 2.3里检测SYN有一条

1
相关文章