Sneeze

Материал из Xgu.ru

Перейти к: навигация, поиск

Sneeze -- генератор ложных срабатывания для Snort, написанный на языке Perl. Он читает файлы с описанием сигнатур атак Snort, и имитирует соответствующие атаки. Помогает тестировать качество работы системы обнаружения вторжений, а также скрывать истинные атаки среди ложных.


Содержание

[править] Пример использования

Скачать sneeze.pl:

%# cd /tmp/
%# wget http://xgu.ru/downloads/sneeze.pl

Установить модуль Perl Net::RawIP необходимый для работы sneeze.pl.

В Debian GNU/Linux это делается так:

%# apt-get install libnet-rawip-perl

Если запустить sneeze.pl без параметров, будет показано сообщение с информацией об использовании:

%# perl /tmp/sneeze.pl 
Must have EUID == 0 to use Net::RawIP at /tmp/sneeze.pl line 20
Usage /tmp/sneeze.pl -d <dest host> -f <rule file> [options]
        -c count        Loop X times. -1 == forever. Default is 1.
        -s ip           Spoof this IP as source. Default is your IP.
        -p port         Force use of this source port.
        -i interface    Outbound interface. Default is eth0.
        -x debug        Turn on debugging information.
        -h help         Duh? This is it.

Берём описание сигнатур атак Snort с машины, где установлен Snort (192.168.15.201). Возьмём для примера правила, относящиеся к атакам на DNS:

%# scp 192.168.15.200:/etc/snort/rules/dns.rules

Выполнить имитацию DNS-атак против машины 192.168.15.201:

%# perl /tmp/sneeze.pl -d 192.168.15.201 -f dns.rules
Password:
ATTACK: 
 sky.unix.nt:4929 -> 192.168.15.201:48150

ATTACK: 
 sky.unix.nt:3349 -> 192.168.15.201:21230

ATTACK: 
 sky.unix.nt:16070 -> 192.168.15.201:36591

ATTACK: DNS named authors attempt
ATTACK TYPE: attempted-recon
tcp sky.unix.nt:12151 -> 192.168.15.201:53
Reference => 10728
Reference => http://www.whitehats.com/info/IDS480
....

На машине 192.168.15.201 будут зафиксированы атаки (фрагмент страницы ACID BASE):

#62-(1-63) [nessus] arachNIDS[local] [snort] DNS named authors attempt 2007-06-23 11:47:06 10.0.35.1:51373 192.168.15.201:53 UDP
#63-(1-64) [nessus] arachNIDS[local] [snort] DNS named version attempt 2007-06-23 11:47:06 10.0.35.1:51373 192.168.15.201:53 UDP
#64-(1-65) [nessus] arachNIDS[local] [snort] DNS named authors attempt 2007-06-23 11:47:06 10.0.35.1:2229 192.168.15.201:53 UDP
#65-(1-66) [nessus] arachNIDS[local] [snort] DNS named version attempt 2007-06-23 11:47:06 10.0.35.1:2229 192.168.15.201:53 UDP
#66-(1-67) [nessus] arachNIDS[local] [snort] DNS named authors attempt 2007-06-23 11:47:06 10.0.35.1:63402 192.168.15.201:53 UDP
#67-(1-68) [nessus] arachNIDS[local] [snort] DNS named version attempt 2007-06-23 11:47:06 10.0.35.1:63402 192.168.15.201:53 UDP

[править] Дополнительная информация

[править] Материалы по Snort на xgu.ru

  • Snort — система обнаружения вторжений
  • BASE — консоль анализа аномалий, обнаруженных Snort
  • Oinkmaster — обновление правил Snort
  • Sneeze — генерирование ложных срабатываний (false pozitives) Snort и других IDS

[править] Приложение

Текст скрипта sneeze.pl:

  1. !/usr/bin/perl
  2. sneeze.pl v 1.0
  3. 8/3/2001
  4. Don Bailey (baileydl@mitre.org) and Brian Caswell (bmc@mitre.org)

require 'getopts.pl';

  1. require destination and rule file or help

Getopts('d:f:c:s:p:i:h:x'); if ($opt_h || (!$opt_d && !$opt_f)) { die "Usage $0 -d <dest host> -f <rule file> [options]\ \t-c count\tLoop X times. -1 == forever. Default is 1.\ \t-s ip\t\tSpoof this IP as source. Default is your IP.\ \t-p port\t\tForce use of this source port.\ \t-i interface\tOutbound interface. Default is eth0.\ \t-x debug\tTurn on debugging information.\ \t-h help\t\tDuh? This is it.\n"; }

use Net::RawIP;

  1. setup our sneeze objects for tcp, icmp, and udp

$sneeze_tcp = new Net::RawIP ({tcp => {}}); $sneeze_icmp = new Net::RawIP ({icmp => {}}); $sneeze_udp = new Net::RawIP ({udp => {}}); $sneeze_ip = new Net::RawIP ({generic => {}});

my $DEBUG = 0; if ($opt_x) { $DEBUG = 1; }

my $refurls; $refurls{bugtraq} = "http://www.securityfocus.com/bid/"; $refurls{cve} = "http://cve.mitre.org/cgi-bin/cvename.cgi?name="; $refurls{arachnids} = "http://www.whitehats.com/info/IDS"; $refurls{mcafee} = "http://vil.nai.com/vil/dispVirus.asp?virus_k="; $refurls{url} = "http://";

  1. parse some options if they exist or set default values

chomp($forcesrc = `hostname`);

$setsrc = $opt_s; if ($opt_p) { $srcport = $opt_p; } if($opt_i) { $sneeze_tcp->ethnew($opt_i); $sneeze_icmp->ethnew($opt_i); $sneeze_udp->ethnew($opt_i); $sneeze_ip->ethnew($opt_i); } $loop = ($opt_c) ? $opt_c : 1;

  1. add rules

my @rulez = add_rules($opt_f);

sub add_rules {

  my ($file) = @_;
  my @rules;
  open(RULES,$file) || die "Cannot open $file!\n";
  my @lines = <RULES>;
  close (RULES);
  foreach my $line (@lines) {
     chomp ($line);
     if ($line =~ /^include (.*)$/) {
         if ($opt_x) { print "Adding include of $1\n";}
         my @line_rules = add_rules($1);
         push (@rules,@line_rules);
     }
     else {push (@rules,$line);}
  }
  return (@rules);

}

@rulez = set_vars(@rulez);

sub set_vars {

  my (@rules) = @_;
  my @returns;
  my $vars;
  foreach my $line (@rulez)
  {
     if ($line =~ /^var ([\w]+)(.*)/)
     {
        if ($DEBUG) { print "Got variable $1 set to $2\n";}
        $vars{$1} = $2;
     }
     foreach my $key (keys (%vars))
     {
        $line =~ s/\$$key/$vars{$key}/g;
     }
     push (@returns, $line);
  }
  return (@returns);

}



  1. for every rule in rule file, parse and send a packet like that to dest

foreach $rule (@rulez) {

my $dsize;

       if ($rule =~ /^\s*#/ || $rule eq "\n") {
               next;
       }
       # only use "alert" and "log" rules
       # if ($rule !~ /^(alert|log)/) { next; }
       # ALERT|LOG PROTO src srcport direction dst dstport
       $rule =~ /(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(->|<>|<-)\s+(\S+)\s+(\S+)(.*)$/;
 $attack = $1;
       $proto = $2;
       $rule_src = $3;
       if (!$setsrc) {

if ($rule_src =~ /^(\d+\.\d+\.\d+\.\d+)/ ) { $src = $1; } else { $src = $forcesrc; }

       }
       $srcport = $4;
       $direction = $5;
       #$dst = $6;
       $dstport = $7;
       $rest = $8;
       $content = undef;
       if ($rest =~ /msg\s*:\s*"([^"]+)/i) { $msg = $1; }
       if ($rest =~ /flags\s*:\s*([^;]+)/i ) { $flags = $1; }
       if ($rest =~ /dsize\s*:\s*([^;]+)/i ) { $dsize= $1; }
       if ($rest =~ /classtype\s*:\s*([^;]+)/i ) {$type= $1; }
       if ($rest =~ /depth\s*:\s*([^;]+)/g ) {$depth = $1; }
       if ($rest =~ /sameip;/i) { $src = $opt_d; }
       $rest =~ s/nocase;//g;


       my $payload;
       my $contents = $rest;
       if ($contents =~ /content\s*:\s*"[^"]+.*content\s*:\s*"[^"]+/)
       {
          while ($contents =~ /content/)
          {
          if ($contents =~ s/content:"([^"]+)\"\;\s+offset:(\d+)\;(.*)/$3/i)
          {
             my $tmp = $1;

my $offset = $2;

             my $pad = 'A' x $offset;

push (@contents,parse_content($pad . $tmp)); }

          elsif ($contents =~ s/content\s*:\s*"([^"]+)(.*)/$2/i)
          {
             push (@contents,parse_content($1));

}

          }
 }

foreach (@contents) { $payload = $payload . $_; }

       $ref = $rest;
       my @refs;
       while ($ref =~ s/(.*)reference:([^\;]+)(.*)$/$1 $3/)
       {
          my $tmp = $2;
          if ($tmp =~ /(\w+),(.*)/i) { $tmp = $refurls{$1} . $2; }
          push (@refs,$tmp);
       }

if($dsize) {

               my $dsize_len = $dsize;
               $dsize_len =~ s/dsize: //;
               $dsize_len =~ /([\D]{0,1})(\d+)$/;
               $dsize_len = $2;
               my $gtolt = $1;
               my $length = length ($payload);
               my $need = $dsize_len - $length;
               if ($gtolt eq ">") {
                       $need++;
               } elsif ($gtolt eq "<") {
                       $need--;
               }
               my $pad = 'A' x $need;
               $payload = $payload . $pad;
       }

push @attacks, { src => $src, dst => $opt_d, dstport => $dstport, srcport => $srcport, payload => $payload, msg => $msg, proto => $proto, refs => \@refs, type => $type, sig => $rule }; }


  1. loop for loop amount of times or forever if loop was -1

$count = 0; while (($count < $loop) || ($loop == -1)) { foreach my $attack (@attacks) {

  if ($attack->{srcport} !~ /\d+/) {
     $attack->{srcport} = int(rand(65535));
  }
  if ($attack->{dstport} !~ /\d+/) {
     $attack->{dstport} = int(rand(65535));
  }
  print "ATTACK: $attack->{msg}\n";
  if ($attack->{type}) { print "ATTACK TYPE: $attack->{type}\n"; }
  print "$attack->{proto} $attack->{src}:$attack->{srcport} -> $attack->{dst}:$attack->{dstport}\n";
  $refs = $attack->{refs};
  if ($refs) { foreach (@$refs) { print "Reference => $_\n"; } }
  if ($DEBUG) { print "SIGNATURE $attack->{sig}\n"; }
  print "\n";
  if ($attack->{proto} =~ /tcp/i) {
    $sneeze_tcp->set({ip =>{saddr => $attack->{src}, daddr => $attack->{dst}},

tcp => {source => $attack->{srcport} ,dest => $attack->{dstport},

       ack => 1, data => $attack->{payload} }});
     $sneeze_tcp->send;
  } elsif ($attack->{proto} =~ /icmp/i ) {
     $sneeze_icmp->set({ip => {saddr =>$attack->{src},daddr =>$attack->{dst}},
         icmp => {data => $attack->{payload} }});
     $sneeze_icmp->send;
  } elsif ($attack->{proto} =~ /udp/i ) {

$sneeze_udp->set({ip =>{saddr => $attack->{src},daddr =>$attack->{dst}}, udp => {source => $attack->{srcport},dest => $attack->{dstport}, data =>$attack->{payload} }}); $sneeze_udp->send;

  } else {

$sneeze_ip->set({ip => {saddr => $attack->{src},daddr =>$attack->{dst}}, generic => {data => $attack->{payload} }});

  } # end if elsif for packet gen stuff

} # end foreach

$count++; } # end while


sub parse_content {

  my ($content) = @_;
  my $end; my $hex2a;
  $content =~ s/([^|]*)(.*)/$2/;
  my $pre = $1;
  if ($content =~ /\|/) {
     $content =~ s/([^|]+)\|(.*)/$1/;
     my $hex = $1; my $post = $2;
     while ($hex =~ s/(\w{2})(.*)/$2/) {
        $hex2a .= chr(hex $1);
     }
    if ($post) { $end = parse_content($post); }
  }
  return ($pre . $hex2a . $end);

} <sh/>

Источник — «http://xgu.ru/wiki/Sneeze»