Changeset 1658

Show
Ignore:
Timestamp:
11/12/06 16:40:29 (2 years ago)
Author:
mbr
Message:

first working version of new Snort signature rules interface, support for many new Snort keywords and additional signatures (about 50) have been added

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • psad/branches/sigdevel/psad

    r1656 r1658  
    10441044            ### sid matching, Netfilter logging prefixes and chains, etc.) 
    10451045            'fwsnort_sid' => 0, 
    1046             'nf_chain'=> '', 
    1047             'nf_log_prefix' => '', 
     1046            'chain'       => '', 
     1047            'log_prefix' => '', 
    10481048            'dshield_str' => '', 
    10491049            'syslog_host' => '', 
     
    11531153        $scan{$pkt{'src'}}{$pkt{'dst'}}{'absnum'}++; 
    11541154        $scan{$pkt{'src'}}{$pkt{'dst'}}{'chain'} 
    1155             {$pkt{'nf_chain'}}{$pkt{'intf'}}{$pkt{'proto'}}++; 
     1155            {$pkt{'chain'}}{$pkt{'intf'}}{$pkt{'proto'}}++; 
    11561156        $curr_scan{$pkt{'src'}}{$pkt{'dst'}}{$pkt{'proto'}}{'pkts'}++; 
    11571157        $curr_scan{$pkt{'src'}}{$pkt{'dst'}} 
     
    11661166            {$pkt{'syslog_host'}} = '' if $pkt{'syslog_host'}; 
    11671167 
    1168         if ($pkt{'nf_log_prefix'}) { 
     1168        if ($pkt{'log_prefix'}) { 
    11691169            ### see if the logging prefix matches the blocking 
    11701170            ### regex, and if not the IP will not be blocked 
     
    11741174                ### we require a match 
    11751175                if (not defined $auto_block_regex_match{$pkt{'src'}} 
    1176                     and $pkt{'nf_log_prefix'} =~ /$config{'AUTO_BLOCK_REGEX'}/) { 
     1176                    and $pkt{'log_prefix'} =~ /$config{'AUTO_BLOCK_REGEX'}/) { 
    11771177                    $auto_block_regex_match{$pkt{'src'}} = ''; 
    11781178                } 
    11791179            } 
    11801180        } else { 
    1181             $pkt{'nf_log_prefix'} = '*noprfx*'; 
     1181            $pkt{'log_prefix'} = '*noprfx*'; 
    11821182        } 
    11831183 
    11841184        ### keep track of Netfilter chain and logging prefix 
    11851185        $curr_scan{$pkt{'src'}}{$pkt{'dst'}}{$pkt{'proto'}}{'chain'} 
    1186                 {$pkt{'nf_chain'}}{$pkt{'nf_log_prefix'}}++; 
     1186                {$pkt{'chain'}}{$pkt{'log_prefix'}}++; 
    11871187 
    11881188        unless ($pkt{'proto'} eq 'icmp') { 
     
    12461246            ### found a snort sid in the packet log message 
    12471247            my $dl = &add_snort_sid($pkt{'src'}, $pkt{'dst'}, 
    1248                 $pkt{'nf_chain'}, $pkt{'proto'}, $pkt{'fwsnort_sid'}); 
     1248                $pkt{'chain'}, $pkt{'proto'}, $pkt{'fwsnort_sid'}); 
    12491249            $curr_sids_dl{$pkt{'src'}} = $dl if $dl; 
    12501250        } else { 
     
    13031303    ### "kernel:" string is preceded by .*). 
    13041304    if ($pkt_str =~ /.*kernel:\s+(.*?)\s*IN=/) { 
    1305         $pkt_hr->{'nf_log_prefix'} = $1; 
    1306         if ($pkt_hr->{'nf_log_prefix'} =~ /\S/) { 
     1305        $pkt_hr->{'log_prefix'} = $1; 
     1306        if ($pkt_hr->{'log_prefix'} =~ /\S/) { 
    13071307            if ($config{'IGNORE_LOG_PREFIXES'} ne 'NONE') { 
    1308                 return $PKT_IGNORE if $pkt_hr->{'nf_log_prefix'} 
     1308                return $PKT_IGNORE if $pkt_hr->{'log_prefix'} 
    13091309                        =~ m|$config{'IGNORE_LOG_PREFIXES'}|; 
    13101310            } 
    1311             $ipt_prefixes{$pkt_hr->{'nf_log_prefix'}}++; 
     1311            $ipt_prefixes{$pkt_hr->{'log_prefix'}}++; 
    13121312        } 
    13131313    } 
     
    15711571    my $pkt_hr = shift; 
    15721572 
     1573    my $dl = 0; 
     1574 
    15731575    ### always run the IP protocol sigs 
    15741576    for my $proto ($pkt_hr->{'proto'}, 'ip') { 
     
    16361638                                        ### and sp/dp, so match any Snort 
    16371639                                        ### keywords 
    1638                                         &match_snort_keywords($pkt_hr, 
     1640                                        my $dl_tmp = &match_snort_keywords($pkt_hr, 
    16391641                                                $dp_hr->{$dp_s}->{$dp_e}); 
     1642 
     1643                                        ### return maximal danger level from all 
     1644                                        ### signature matches 
     1645                                        $dl = $dl_tmp if $dl_tmp > $dl; 
    16401646                                    } 
    16411647                                } 
     
    16461652                    ### now we have the set of applicable icmp 
    16471653                    ### signatures that match the sip/dip 
    1648                     &match_snort_keywords($pkt_hr, 
     1654                    my $dl_tmp = &match_snort_keywords($pkt_hr, 
    16491655                            $sig_search{$proto}{$src}{$dst}); 
    16501656 
    1651                 } 
    1652             } 
    1653         } 
    1654     } 
    1655     return 0; 
     1657                    ### return maximal danger level from all signature matches 
     1658                    $dl = $dl_tmp if $dl_tmp > $dl; 
     1659                } 
     1660            } 
     1661        } 
     1662    } 
     1663    return $dl; 
    16561664} 
    16571665 
     
    16591667    my ($pkt_hr, $sigs_ids_hr) = @_; 
    16601668 
    1661 print ".......match_snort_keywords()\n"; 
     1669    print STDERR "[+] match_snort_keywords()\n" if $debug; 
     1670 
     1671    my $dl = 0; 
    16621672 
    16631673    ### see if all Snort keywords match the packet 
     
    16711681        ### values (at least for ipv4, see 
    16721682        ### linux/net/ipv4/netfilter/ipt_LOG.c) 
    1673         next SIG unless &match_snort_ip_keywords($pkt_hr, $sig_hr); 
     1683        my $dl_tmp = &match_snort_ip_keywords($pkt_hr, $sig_hr); 
     1684        next SIG unless $dl_tmp; 
     1685 
     1686        $dl = $dl_tmp if $dl_tmp > $dl; 
    16741687 
    16751688        if ($sig_hr->{'proto'} eq 'tcp') { 
    16761689 
    1677             &match_snort_tcp_keywords($pkt_hr, $sig_hr); 
    1678  
     1690            $dl_tmp = &match_snort_tcp_keywords($pkt_hr, $sig_hr); 
     1691            if ($dl_tmp) { 
     1692                $dl = $dl_tmp if $dl_tmp > $dl; 
     1693 
     1694                $scan{$pkt_hr->{'src'}}{$pkt_hr->{'dst'}}{'tcp'}{'curr_sig'} 
     1695                    {$pkt_hr->{'sid'}}{$pkt_hr->{'chain'}}{'dp'} 
     1696                    {$pkt_hr->{'dp'}}++; 
     1697 
     1698                $scan{$pkt_hr->{'src'}}{$pkt_hr->{'dst'}}{'tcp'}{'curr_sig'} 
     1699                    {$pkt_hr->{'sid'}}{$pkt_hr->{'chain'}}{'flags'} 
     1700                    {$pkt_hr->{'dp'}} = $pkt_hr->{'flags'}; 
     1701 
     1702            } 
    16791703        } elsif ($sig_hr->{'proto'} eq 'udp') { 
    16801704 
    1681             &match_snort_udp_keywords($pkt_hr, $sig_hr); 
    1682  
     1705            $dl_tmp = &match_snort_udp_keywords($pkt_hr, $sig_hr); 
     1706            if ($dl_tmp) { 
     1707                $dl = $dl_tmp if $dl_tmp > $dl; 
     1708 
     1709                $scan{$pkt_hr->{'src'}}{$pkt_hr->{'dst'}}{'udp'}{'curr_sig'} 
     1710                    {$pkt_hr->{'sid'}}{$pkt_hr->{'chain'}}{'dp'} 
     1711                    {$pkt_hr->{'dp'}}++; 
     1712            } 
    16831713        } elsif ($sig_hr->{'proto'} eq 'icmp') { 
    16841714 
    1685             &match_snort_icmp_keywords($pkt_hr, $sig_hr); 
    1686         } 
    1687     } 
    1688  
    1689     return; 
     1715            ### validate icmp type and code fields against the official values 
     1716            ### in RFC 792.  See %inval_type_code for corresponding signature 
     1717            ### message text and danger levels. 
     1718            my $type_code_rv = &check_icmp_type($pkt_hr->{'itype'}, 
     1719                    $pkt_hr->{'icode'}); 
     1720            if ($type_code_rv == 1) {  ### bad type 
     1721 
     1722                $dl = 2 if $dl < 2; 
     1723 
     1724                $scan{$pkt_hr->{'src'}}{$pkt_hr->{'dst'}}{'icmp'} 
     1725                    {'invalid_type'}{$pkt_hr->{'itype'}} 
     1726                    {$pkt_hr->{'chain'}}{'pkts'}++; 
     1727 
     1728            } elsif ($type_code_rv == 2) { 
     1729 
     1730                $dl = 2 if $dl < 2; 
     1731 
     1732                $scan{$pkt_hr->{'src'}}{$pkt_hr->{'dst'}}{'icmp'} 
     1733                    {'invalid_code'}{$pkt_hr->{'itype'}}{$pkt_hr->{'icode'}} 
     1734                    {$pkt_hr->{'chain'}}{'pkts'}++; 
     1735            } 
     1736            $dl = $dl_tmp if $dl_tmp > $dl; 
     1737 
     1738            $dl_tmp = &match_snort_icmp_keywords($pkt_hr, $sig_hr); 
     1739            if ($dl_tmp) { 
     1740                $dl = $dl_tmp if $dl_tmp > $dl; 
     1741 
     1742                $scan{$pkt_hr->{'src'}}{$pkt_hr->{'dst'}}{'icmp'}{'curr_sig'} 
     1743                    {$sid}{$pkt_hr->{'chain'}}{'pkts'}++; 
     1744            } 
     1745        } 
     1746 
     1747    } 
     1748    return $dl; 
    16901749} 
    16911750 
     
    16941753 
    16951754    if (defined $sig_hr->{'flags'}) { 
    1696         return unless $pkt_hr->{'flags'} eq $sig_hr->{'flags'}; 
    1697     } 
    1698  
    1699     return unless &check_sig_int_range( 
     1755        return 0 unless $pkt_hr->{'flags'} eq $sig_hr->{'flags'}; 
     1756    } 
     1757 
     1758    return 0 unless &check_sig_int_range( 
    17001759            ($pkt_hr->{'ip_len'}-$IP_HEADER_LEN-$TCP_HEADER_LEN), 
    17011760            'dsize', $sig_hr 
    17021761    ); 
    17031762 
    1704     return unless &check_sig_int_range( 
     1763    return 0 unless &check_sig_int_range( 
    17051764            ($pkt_hr->{'ip_len'}-$IP_HEADER_LEN-$TCP_HEADER_LEN), 
    17061765            'psad_dsize', $sig_hr 
    17071766    ); 
    17081767 
    1709     return unless &check_sig_int_range($pkt_hr->{'win'}, 'window', $sig_hr); 
    1710     return unless &check_sig_int_range($pkt_hr->{'tcp_seq'}, 'seq', $sig_hr); 
    1711     return unless &check_sig_int_range($pkt_hr->{'tcp_ack'}, 'ack', $sig_hr); 
     1768    return 0 unless &check_sig_int_range($pkt_hr->{'win'}, 'window', $sig_hr); 
     1769    return 0 unless &check_sig_int_range($pkt_hr->{'tcp_seq'}, 'seq', $sig_hr); 
     1770    return 0 unless &check_sig_int_range($pkt_hr->{'tcp_ack'}, 'ack', $sig_hr); 
    17121771 
    17131772    ### matched the signature 
    1714 print "..... matched tcp keywords: $sig_hr->{'sid'} $sig_hr->{'psad_id'}\n"; 
    1715     return; 
     1773    if ($debug) { 
     1774        print STDERR "[+] packet matched matched tcp keywords for sid: ", 
     1775            "$sig_hr->{'sid'} (psad_id: $sig_hr->{'psad_id'})\n"; 
     1776    } 
     1777    return $sig_hr->{'dl'}; 
    17161778} 
    17171779 
     
    17191781    my ($pkt_hr, $sig_hr) = @_; 
    17201782 
    1721     return unless &check_sig_int_range( 
     1783    return 0 unless &check_sig_int_range( 
    17221784            ($pkt_hr->{'udp_len'}-$UDP_HEADER_LEN), 
    17231785            'dsize', $sig_hr 
    17241786    ); 
    17251787 
    1726     return unless &check_sig_int_range( 
     1788    return 0 unless &check_sig_int_range( 
    17271789            ($pkt_hr->{'udp_len'}-$UDP_HEADER_LEN), 
    17281790            'psad_dsize', $sig_hr 
     
    17301792 
    17311793    ### matched the signature 
    1732 print "..... matched udp keywords: $sig_hr->{'sid'} $sig_hr->{'psad_id'}\n"; 
    1733     return; 
     1794    if ($debug) { 
     1795        print STDERR "[+] packet matched udp keywords for sid: ", 
     1796            "$sig_hr->{'sid'} (psad_id: $sig_hr->{'psad_id'})\n"; 
     1797    } 
     1798    return $sig_hr->{'dl'}; 
    17341799} 
    17351800 
     
    17371802    my ($pkt_hr, $sig_hr) = @_; 
    17381803 
    1739     return unless &check_sig_int_range( 
     1804    return 0 unless &check_sig_int_range( 
    17401805            ($pkt_hr->{'ip_len'}-$IP_HEADER_LEN-$ICMP_HEADER_LEN), 
    17411806            'dsize', $sig_hr 
    17421807    ); 
    17431808 
    1744     return unless &check_sig_int_range( 
     1809    return 0 unless &check_sig_int_range( 
    17451810            ($pkt_hr->{'ip_len'}-$IP_HEADER_LEN-$ICMP_HEADER_LEN), 
    17461811            'psad_dsize', $sig_hr 
    17471812    ); 
    17481813 
    1749     return unless &check_sig_int_range($pkt_hr->{'itype'}, 'itype', $sig_hr); 
    1750     return unless &check_sig_int_range($pkt_hr->{'icode'}, 'icode', $sig_hr); 
    1751     return unless &check_sig_int_range($pkt_hr->{'icmp_seq'}, 'icmp_seq', $sig_hr); 
    1752     return unless &check_sig_int_range($pkt_hr->{'icmp_id'}, 'icmp_id', $sig_hr); 
     1814    return 0 unless &check_sig_int_range($pkt_hr->{'itype'}, 'itype', $sig_hr); 
     1815    return 0 unless &check_sig_int_range($pkt_hr->{'icode'}, 'icode', $sig_hr); 
     1816    return 0 unless &check_sig_int_range($pkt_hr->{'icmp_seq'}, 'icmp_seq', $sig_hr); 
     1817    return 0 unless &check_sig_int_range($pkt_hr->{'icmp_id'}, 'icmp_id', $sig_hr); 
    17531818 
    17541819    ### matched the signature 
    1755 print "..... matched icmp keywords: $sig_hr->{'sid'} $sig_hr->{'psad_id'}\n"; 
    1756     return; 
     1820    if ($debug) { 
     1821        print STDERR "[+] packet matched icmp keywords for sid: ", 
     1822            "$sig_hr->{'sid'} (psad_id: $sig_hr->{'psad_id'})\n"; 
     1823    } 
     1824    return $sig_hr->{'dl'}; 
    17571825} 
    17581826 
     
    17731841    if ($sig_hr->{'proto'} eq 'ip') { 
    17741842        ### signature match 
    1775         print "$sig_hr->{'sid'} sig proto: $sig_hr->{'proto'} packet proto: $pkt_hr->{'proto'}\n"; 
    1776     } 
    1777  
     1843        if ($debug) { 
     1844            print STDERR "[+] packet matched ip keywords for sid: ", 
     1845                "$sig_hr->{'sid'} (psad_id: $sig_hr->{'psad_id'})\n"; 
     1846        } 
     1847        return $sig_hr->{'dl'} 
     1848    } 
    17781849    return 1; 
    17791850} 
     
    18121883    } 
    18131884    return 0; 
    1814 } 
    1815  
    1816  
    1817 sub old_match_sigs() { 
    1818     my ($src, $dst, $chain, $sp, $dp, $proto, 
    1819         $flags, $len, $ttl, $type, $code, $id, $seq) = @_; 
    1820  
    1821     my $dl = 0; 
    1822     if ($proto eq 'tcp') { 
    1823         for my $sid (keys %{$sigs{'tcp'}}) { 
    1824             next unless defined $sigs{'tcp'}{$sid}{'flags'}; 
    1825             if (&check_port($sp, $dp, $sigs{'tcp'}{$sid}) 
    1826                     and $flags eq $sigs{'tcp'}{$sid}{'flags'} 
    1827                     and &check_src($chain, $src, $sigs{'tcp'}{$sid}{'src'}) 
    1828                     and &check_dst($chain, $dst, $sigs{'tcp'}{$sid}{'dst'})) { 
    1829                 ### future 
    1830 #               && &check_misc_fields($sid, $proto, $len, $ttl)) { 
    1831                 ### tripped a tcp signature 
    1832                 print STDERR "[+] match_sigs(): matched tcp $dp,$sp,$flags, ", 
    1833                     "sid: $sid\n" if $debug; 
    1834                 if ($dl < $sigs{$sid}{'dl'}) { 
    1835                     $dl = $sigs{$sid}{'dl'}; 
    1836                 } 
    1837                 $scan{$src}{$dst}{$proto}{'curr_sig'} 
    1838                     {$sid}{$chain}{'dp'}{$dp}++; 
    1839                 $scan{$src}{$dst}{$proto}{'curr_sig'} 
    1840                     {$sid}{$chain}{'flags'}{$dp} = $flags; 
    1841             } 
    1842         } 
    1843     } elsif ($proto eq 'udp') { 
    1844         for my $sid (keys %{$sigs{'udp'}}) { 
    1845             if (&check_src($chain, $src, $sigs{'udp'}{$sid}{'src'}) 
    1846                     and &check_dst($chain, $dst, $sigs{'udp'}{$sid}{'dst'}) 
    1847                     and &check_port($sp, $dp, $sigs{'udp'}{$sid})) { 
    1848 #               && &check_misc_fields($sid, $proto, $len, $ttl)) { 
    1849                 ### tripped a udp signature 
    1850                 print STDERR "[+] match_sigs(): matched udp $dp,$sp, ", 
    1851                     "sid: $sid\n" if $debug; 
    1852                 if ($dl < $sigs{$sid}{'dl'}) { 
    1853                     $dl = $sigs{$sid}{'dl'}; 
    1854                 } 
    1855                 $scan{$src}{$dst}{$proto}{'curr_sig'} 
    1856                     {$sid}{$chain}{'dp'}{$dp}++; 
    1857             } 
    1858         } 
    1859     } elsif ($proto eq 'icmp') { 
    1860         ### check icmp type and code fields against the official values 
    1861         ### in RFC 792.  See %inval_type_code for corresponding signature 
    1862         ### message text and danger levels. 
    1863         my $type_code_rv = &check_icmp_type($type, $code); 
    1864         if ($type_code_rv == 1) {  ### bad type 
    1865             if ($dl < 2) { 
    1866                 $dl = 2;  ### FIXME: hard-coded as dl 2 for now. 
    1867             } 
    1868             $scan{$src}{$dst}{'icmp'}{'invalid_type'} 
    1869                 {$type}{$chain}{'pkts'}++; 
    1870         } elsif ($type_code_rv == 2) { 
    1871             if ($dl < 2) { 
    1872                 $dl = 2;  ### FIXME: hard-coded as dl 2 for now. 
    1873             } 
    1874             $scan{$src}{$dst}{'icmp'}{'invalid_code'} 
    1875                 {$type}{$code}{$chain}{'pkts'}++; 
    1876         } 
    1877         for my $sid (keys %{$sigs{'icmp'}}) { 
    1878             if (&check_src($chain, $src, $sigs{'icmp'}{$sid}{'src'}) 
    1879                     and &check_dst($chain, $dst, $sigs{'icmp'}{$sid}{'dst'}) 
    1880                     and &check_icmp_sig($sid, $ttl, $type, $code, 
    1881                         $id, $seq)) { 
    1882                 print STDERR "[+] match_sigs(): matched icmp sid: $sid\n" 
    1883                     if $debug; 
    1884                 if ($dl < $sigs{$sid}{'dl'}) { 
    1885                     $dl = $sigs{$sid}{'dl'}; 
    1886                 } 
    1887                 $scan{$src}{$dst}{'icmp'}{'curr_sig'} 
    1888                     {$sid}{$chain}{'pkts'}++; 
    1889             } 
    1890         } 
    1891     } 
    1892     return $dl; 
    18931885} 
    18941886 
     
    32673259 
    32683260        ### psad danger level 
     3261        $sig{'dl'} = 2;  ### default danger level 
    32693262        if ($rule_options =~ /psad_dl:\s*(\d+)/) { 
    32703263            $sig{'dl'} = $1; 
    3271         } else { 
    3272             die "[*] import_signatures(): could not find ", 
    3273                 qq|"psad_dl" on line: $line_num|; 
    32743264        } 
    32753265 
     
    43224312                if (defined $curr_scan_hr->{$src}->{$dst}->{'tcp'}->{'chain'}) { 
    43234313                    &print_chains_and_prefixes( 
    4324                         $curr_scan_hr->{$src}->{$dst}->{'tcp'}->{'chain'}, 
    4325                         $fh 
     4314                        $curr_scan_hr->{$src}->{$dst}->{'tcp'}->{'chain'}, $fh 
    43264315                    ); 
    43274316                }