⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 portscan.c

📁 著名的入侵检测系统snort的最新版本的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/**************************************************************************** * * Copyright (C) 2004-2007 Sourcefire, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License Version 2 as * published by the Free Software Foundation.  You may not use, modify or * distribute this program under any other version of the GNU General * Public License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ****************************************************************************/ /***  @file       portscan.c****  @author     Daniel Roelker <droelker@sourcefire.com>****  @brief      Detect portscans****  NOTES**    - Marc Norton and Jeremy Hewlett were involved in the requirements and**      design of this portscan detection engine.**    - Thanks to Judy Novak for her suggestion to log open ports**      on hosts that are portscanned.  This idea makes portscan a lot more**      useful for analysts.****  The philosophy of portscan detection that we use is based on a generic**  network attack methodology: reconnaissance, network service enumeration,**  and service exploitation.****  The reconnaissance phase determines what types of network protocols and**  services that a host supports.  This is the traditional phase where a**  portscan occurs.  An important requirement of this phase is that an**  attacker does not already know what protocols and services are supported**  by the destination host.  If an attacker does know what services are**  open on the destination host then there is no need for this phase.**  Because of this requirement, we assume that if an attacker engages in this**  phase that they do not have prior knowledege to what services are open.**  So, the attacker will need to query the ports or protocols they are**  interested in.  Most or at least some of these queries will be negative**  and take the form of either an invalid response (TCP RSTs, ICMP**  unreachables) or no response (in which case the host is firewalled or**  filtered).  We detect portscans from these negative queries.**  **  The primary goal of this portscan detection engine is to catch nmap and**  variant scanners.  The engine tracks connection attempts on TCP, UDP,**  ICMP, and IP Protocols.  If there is a valid response, the connection**  is marked as valid.  If there is no response or a invalid response**  (TCP RST), then we track these attempts separately, so we know the**  number of invalid responses and the number of connection attempts that**  generated no response.  These two values differentiate between a**  normal scan and a filtered scan.****  We detect four different scan types, and each scan type has its own**  negative query characteristics.  This is how we determine what type**  of scan we are seeing.  The different scans are:****    - Portscan**    - Decoy Portscan**    - Distributed Portscan**    - Portsweep****  Portscan:  A portscan is a basic one host to one host scan where**  multiple ports are scanned on the destination host.  We detect these**  scans by looking for a low number of hosts that contacted the**  destination host and a high number of unique ports and a high number**  of invalid responses or connections.****  Distributed Portscan:  A distributed portscan occurs when many hosts**  connect to a single destination host and multiple ports are scanned**  on the destination host.  We detect these scans by looking for a high**  number of hosts that contacted the destination host and a high number**  of unique ports with a high number of invalid responses or connections.****  Decoy Portscan:  A decoy portscan is a variation on a distributed**  portscan, the difference being that a decoy portscan connects to a**  single port multiple times.  This shows up in the unqiue port count that**  is tracked.  There's still many hosts connecting to the destination host.****  Portsweep:  A portsweep is a basic one host to many host scan where**  one to a few ports are scanned on each host.  We detect these scans by**  looking at src hosts for a high number of contacted hosts and a low**  number of unique ports with a high number of invalid responses or**  connections.****  Each of these scans can also be detected as a filtered portscan, or a**  portscan where there wasn't invalid responses and the responses have**  been firewalled in some way.** */#include <stdlib.h>#include <string.h>#include <sys/types.h>#ifndef WIN32    #include <sys/socket.h>    #include <netinet/in.h>    #include <arpa/inet.h>#endif /* !WIN32 */#include "decode.h"#include "portscan.h"#include "packet_time.h"#include "sfxhash.h"#include "ipobj.h"#include "flow.h"#include "stream_api.h"#ifdef SUP_IP6#define CLEARED &cleared#else#define CLEARED cleared#endiftypedef struct s_PS_INIT{    int detect_scans;    int detect_scan_type;    int sense_level;    int proto_cnt;    IPSET *ignore_scanners;    IPSET *ignore_scanned;    IPSET *watch_ip;} PS_INIT;typedef struct s_PS_HASH_KEY{    ip_t scanner;    ip_t scanned;} PS_HASH_KEY;typedef struct s_PS_ALERT_CONF{    short connection_count;    short priority_count;    short u_ip_count;    short u_port_count;} PS_ALERT_CONF;static int      g_ps_tracker_size;static PS_INIT  g_ps_init;static SFXHASH *g_hash;extern int g_include_midstream;/***  Scanning configurations.  This is where we configure what the thresholds**  are for the different types of scans, protocols, and sense levels.  If**  you want to tweak the sense levels, change the values here.*//***  TCP alert configurations*/static PS_ALERT_CONF g_tcp_low_ps =       {0,5,25,5};static PS_ALERT_CONF g_tcp_low_decoy_ps = {0,15,50,30};static PS_ALERT_CONF g_tcp_low_sweep =    {0,5,5,15};static PS_ALERT_CONF g_tcp_low_dist_ps =  {0,15,50,15};static PS_ALERT_CONF g_tcp_med_ps =       {200,10,60,15};static PS_ALERT_CONF g_tcp_med_decoy_ps = {200,30,120,60};static PS_ALERT_CONF g_tcp_med_sweep =    {30,7,7,10};static PS_ALERT_CONF g_tcp_med_dist_ps =  {200,30,120,30};static PS_ALERT_CONF g_tcp_hi_ps =        {200,5,100,10};static PS_ALERT_CONF g_tcp_hi_decoy_ps =  {200,7,200,60};static PS_ALERT_CONF g_tcp_hi_sweep =     {30,3,3,10};static PS_ALERT_CONF g_tcp_hi_dist_ps =   {200,5,200,10};/***  UDP alert configurations*/static PS_ALERT_CONF g_udp_low_ps =       {0,5,25,5};static PS_ALERT_CONF g_udp_low_decoy_ps = {0,15,50,30};static PS_ALERT_CONF g_udp_low_sweep =    {0,5,5,15};static PS_ALERT_CONF g_udp_low_dist_ps =  {0,15,50,15};static PS_ALERT_CONF g_udp_med_ps =       {200,10,60,15};static PS_ALERT_CONF g_udp_med_decoy_ps = {200,30,120,60};static PS_ALERT_CONF g_udp_med_sweep =    {30,5,5,20};static PS_ALERT_CONF g_udp_med_dist_ps =  {200,30,120,30};static PS_ALERT_CONF g_udp_hi_ps =        {200,3,100,10};static PS_ALERT_CONF g_udp_hi_decoy_ps =  {200,7,200,60};static PS_ALERT_CONF g_udp_hi_sweep =     {30,3,3,10};static PS_ALERT_CONF g_udp_hi_dist_ps =   {200,3,200,10};/***  IP Protocol alert configurations*/static PS_ALERT_CONF g_ip_low_ps =        {0,10,10,50};static PS_ALERT_CONF g_ip_low_decoy_ps =  {0,40,50,25};static PS_ALERT_CONF g_ip_low_sweep =     {0,10,10,10};static PS_ALERT_CONF g_ip_low_dist_ps =   {0,15,25,50};static PS_ALERT_CONF g_ip_med_ps =        {200,10,10,50};static PS_ALERT_CONF g_ip_med_decoy_ps =  {200,40,50,25};static PS_ALERT_CONF g_ip_med_sweep =     {30,10,10,10};static PS_ALERT_CONF g_ip_med_dist_ps =   {200,15,25,50};static PS_ALERT_CONF g_ip_hi_ps =         {200,3,3,10};static PS_ALERT_CONF g_ip_hi_decoy_ps =   {200,7,15,5};static PS_ALERT_CONF g_ip_hi_sweep =      {30,3,3,7};static PS_ALERT_CONF g_ip_hi_dist_ps =    {200,3,11,10};/***  ICMP alert configurations*/static PS_ALERT_CONF g_icmp_low_sweep =   {0,5,5,5};static PS_ALERT_CONF g_icmp_med_sweep =   {20,5,5,5};static PS_ALERT_CONF g_icmp_hi_sweep =    {10,3,3,5};/***  NAME**    ps_tracker_free::*//****  This function is passed into the hash algorithm, so that**  we only reuse nodes that aren't priority nodes.  We have to make**  sure that we only track so many priority nodes, otherwise we could**  have all priority nodes and not be able to allocate more.*/static int ps_tracker_free(void *key, void *data){    PS_TRACKER *tracker;    int         iCtr;    time_t      pkt_time;    if(!key || !data)        return 0;    tracker = (PS_TRACKER *)data;    if(!tracker->priority_node)        return 0;    /*    **  Cycle through the protos to see if it's past the time.    **  We only get here if we ARE a priority node.    */    pkt_time = packet_timeofday();    for(iCtr = 0; iCtr < g_ps_init.proto_cnt; iCtr++)    {        if(tracker->proto[iCtr].window >= pkt_time)            return 1;    }    return 0;}/***  NAME**    ps_init::*//***  Initialize the portscan infrastructure.  We check to make sure that**  we have enough memory to support at least 100 nodes.** **  @return int**  **  @retval -2 memcap is too low*/int ps_init(int detect_scans, int detect_scan_type, int sense_level,        IPSET *scanner, IPSET *scanned, IPSET *watch, int memcap){    int proto_cnt = 0;    int datasize;    proto_cnt += ((detect_scans & PS_PROTO_TCP)  ? 1 : 0);    proto_cnt += ((detect_scans & PS_PROTO_UDP)  ? 1 : 0);    proto_cnt += ((detect_scans & PS_PROTO_ICMP) ? 1 : 0);    proto_cnt += ((detect_scans & PS_PROTO_IP)   ? 1 : 0);    if(!proto_cnt)        return -1;   if(!(detect_scan_type & PS_TYPE_ALL))        return -1;   if(sense_level < 1 || sense_level > 3)       return -1;   /*   **  Set the datasize that the hash will be keeping track of.  This   **  changes dynamically based on the number of protocols that we are   **  tracking.   */   datasize = sizeof(PS_TRACKER) + (sizeof(PS_PROTO)*(proto_cnt - 1));   if(memcap <= 0 || memcap < (datasize * 100))       return -2;   g_hash = sfxhash_new(50000, sizeof(PS_HASH_KEY), datasize,            memcap, 1, ps_tracker_free, NULL, 1);   if(!g_hash)       return -1;   g_ps_init.detect_scans     = detect_scans;   g_ps_init.detect_scan_type = detect_scan_type;   g_ps_init.sense_level      = sense_level;   g_ps_init.ignore_scanners  = scanner;   g_ps_init.ignore_scanned   = scanned;   g_ps_init.watch_ip         = watch;   g_ps_tracker_size = datasize;   return 0;}/***  NAME**    ps_cleanup::*//****  Cleanup the portscan infrastructure.*/void ps_cleanup(){    if (g_hash)    {        sfxhash_delete(g_hash);        g_hash = NULL;    }    g_ps_tracker_size = 0;}/***  NAME**    ps_ignore_ip::*//****  Check scanner and scanned ips to see if we can filter them out.*/#ifdef SUP_IP6static int ps_ignore_ip(ip_p scanner, unsigned short scanner_port,                        ip_p scanned, unsigned short scanned_port)#elsestatic int ps_ignore_ip(unsigned long scanner, unsigned short scanner_port,                        unsigned long scanned, unsigned short scanned_port)#endif{    if(g_ps_init.ignore_scanners)    {#ifdef SUP_IP6        if(sfip_family(scanner) == AF_INET6 &&            ipset_contains(g_ps_init.ignore_scanners, scanner, &scanner_port, IPV6_FAMILY))                return 1;        else             if(ipset_contains(g_ps_init.ignore_scanners, scanner, &scanner_port, IPV4_FAMILY))                return 1;#else        if(ipset_contains(g_ps_init.ignore_scanners, &scanner, &scanner_port, IPV4_FAMILY))            return 1;#endif    }    if(g_ps_init.ignore_scanned)    {#ifdef SUP_IP6        if(sfip_family(scanned) &&           ipset_contains(g_ps_init.ignore_scanned, scanned, &scanned_port, IPV6_FAMILY))            return 1;        else            if(ipset_contains(g_ps_init.ignore_scanned, scanned, &scanned_port, IPV4_FAMILY))                return 1;#else        if(ipset_contains(g_ps_init.ignore_scanned, &scanned, &scanned_port, IPV4_FAMILY))            return 1;#endif    }    return 0;}/***  NAME**    ps_filter_ignore::*//****  Check the incoming packet to decide whether portscan detection cares**  about this packet.  We try to ignore as many packets as possible.*/static int ps_filter_ignore(PS_PKT *ps_pkt){    Packet  *p;    FLOW    *flow;    int      reverse_pkt = 0;#ifdef SUP_IP6    ip_p scanner, scanned;#else    unsigned long scanner;    unsigned long scanned;#endif    p = (Packet *)ps_pkt->pkt;    if(!IPH_IS_VALID(p))        return 1;    if(p->tcph)    {        if(!(g_ps_init.detect_scans & PS_PROTO_TCP))            return 1;           /*        **  This is where we check all of snort's flags for different        **  TCP session scenarios.  The checks cover:        **        **    - dropping packets in established sessions, but not the        **      TWH packet.        **    - dropping the SYN/ACK packet from the server on a valid        **      connection (we'll catch the TWH later if it happens).        */        /*        **  Ignore packets that are already part of an established TCP        **  stream.         */        if(((p->packet_flags & (PKT_STREAM_EST | PKT_STREAM_TWH))                 == PKT_STREAM_EST) && !(p->tcph->th_flags & TH_RST))        {            return 1;        }        /*        **  Ignore the server's initial response, unless it's to RST        **  the connection.        */        /*        if(!(p->tcph->th_flags & TH_RST) &&           !(p->packet_flags & (PKT_STREAM_EST)) &&            (p->packet_flags & PKT_FROM_SERVER))        {            return 1;        }        */    }    else if(p->udph)    {        if(!(g_ps_init.detect_scans & PS_PROTO_UDP))            return 1;    }    else if(p->icmph)    {        if(p->icmph->type != ICMP_DEST_UNREACH &&           !(g_ps_init.detect_scans & PS_PROTO_ICMP))        {            return 1;        }    }    else    {        if(!(g_ps_init.detect_scans & PS_PROTO_IP))            return 1;    }    /*    **  Check if the packet is reversed    */    if((p->packet_flags & PKT_FROM_SERVER))    {        reverse_pkt = 1;    }    else if(p->icmph && p->icmph->type == ICMP_DEST_UNREACH)    {        reverse_pkt = 1;    }    else if (p->udph && p->ssnptr &&             stream_api && stream_api->version >= STREAM_API_VERSION5)    {        if (stream_api->get_packet_direction(p) & PKT_FROM_SERVER)            reverse_pkt = 1;    }    else if((p->udph || IPH_IS_VALID(p)) && p->flow)    {        flow = (FLOW *)p->flow;        if(flow->stats.direction == FROM_RESPONDER)            reverse_pkt = 1;    }#ifdef SUP_IP6    scanner = GET_SRC_IP(p);    scanned = GET_DST_IP(p);#else    scanner = ntohl(p->iph->ip_src.s_addr);    scanned = ntohl(p->iph->ip_dst.s_addr);#endif        if(reverse_pkt)    {        if(ps_ignore_ip(scanned, p->dp, scanner, p->sp))            return 1;    }    else    {        if(ps_ignore_ip(scanner, p->sp, scanned, p->dp))            return 1;    }        ps_pkt->reverse_pkt = reverse_pkt;    if(g_ps_init.watch_ip)    {#ifdef SUP_IP6         if(sfip_family(scanner) == AF_INET6)         {            if(ipset_contains(g_ps_init.watch_ip, scanner, &(p->sp), IPV6_FAMILY))                return 0;            if(ipset_contains(g_ps_init.watch_ip, scanned, &(p->dp), IPV6_FAMILY))                return 0;        }        else        {            if(ipset_contains(g_ps_init.watch_ip, scanner, &(p->sp), IPV4_FAMILY))                return 0;            if(ipset_contains(g_ps_init.watch_ip, scanned, &(p->dp), IPV4_FAMILY))                return 0;        }#else        if(ipset_contains(g_ps_init.watch_ip, &scanner, &(p->sp), IPV4_FAMILY))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -