1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 // Copyright (C) 2004-2013 Sourcefire, Inc.
4 //
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License Version 2 as published
7 // by the Free Software Foundation.  You may not use, modify or distribute
8 // this program under any other version of the GNU General Public License.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 //--------------------------------------------------------------------------
19 
20 //  portscan.c author Daniel Roelker <droelker@sourcefire.com>
21 //  ps_detect.cc author Russ Combs <rucombs@cisco.com>
22 
23 /*
24 **  - Marc Norton and Jeremy Hewlett were involved in the requirements and
25 **    design of this portscan detection engine.
26 **  - Thanks to Judy Novak for her suggestion to log open ports on hosts
27 **    that are portscanned.  This idea makes portscan a lot more useful for
28 **    analysts.
29 */
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33 
34 #include "ps_detect.h"
35 
36 #include "hash/hash_defs.h"
37 #include "hash/xhash.h"
38 #include "log/messages.h"
39 #include "protocols/icmp4.h"
40 #include "protocols/packet.h"
41 #include "protocols/tcp.h"
42 #include "stream/stream.h"
43 #include "time/packet_time.h"
44 #include "utils/cpp_macros.h"
45 #include "utils/stats.h"
46 
47 #include "ps_inspect.h"
48 #include "ps_pegs.h"
49 
50 using namespace snort;
51 
52 PADDING_GUARD_BEGIN
53 struct PS_HASH_KEY
54 {
55     int protocol;
56     SfIp scanner;
57     SfIp scanned;
58     int16_t group;
59     uint16_t asid;
60 };
61 PADDING_GUARD_END
62 
63 class PortScanCache : public XHash
64 {
65 public:
PortScanCache(unsigned rows,unsigned key_len,unsigned datasize,unsigned memcap)66     PortScanCache(unsigned rows, unsigned key_len, unsigned datasize, unsigned memcap)
67         : XHash(rows, key_len, datasize, memcap)
68     { }
69 
is_node_recovery_ok(HashNode * hnode)70     bool is_node_recovery_ok(HashNode* hnode) override
71     {
72         PS_TRACKER* tracker = (PS_TRACKER*)hnode->data;
73 
74         if ( !tracker->priority_node )
75             return true;
76 
77         /*
78          **  Cycle through the protos to see if it's past the time.
79          **  We only get here if we ARE a priority node.
80          */
81         if ( tracker->proto.window >= packet_time() )
82             return false;
83 
84         return true;
85     }
86 };
87 
88 static THREAD_LOCAL PortScanCache* portscan_hash = nullptr;
89 extern THREAD_LOCAL PsPegStats spstats;
90 
PS_PKT(Packet * p)91 PS_PKT::PS_PKT(Packet* p)
92 {
93     pkt = p;
94     scanner = scanned = nullptr;
95     proto = reverse_pkt = 0;
96 }
97 
PortscanConfig()98 PortscanConfig::PortscanConfig()
99 {
100     memset(this, 0, sizeof(*this));
101 }
102 
~PortscanConfig()103 PortscanConfig::~PortscanConfig()
104 {
105     if ( ignore_scanners )
106         ipset_free(ignore_scanners);
107 
108     if ( ignore_scanned )
109         ipset_free(ignore_scanned);
110 
111     if ( watch_ip )
112         ipset_free(watch_ip);
113 }
114 
ps_cleanup()115 void ps_cleanup()
116 {
117     if ( portscan_hash )
118     {
119         delete portscan_hash;
120         portscan_hash = nullptr;
121     }
122 }
123 
ps_node_size()124 unsigned ps_node_size()
125 { return sizeof(PS_HASH_KEY) + sizeof(PS_TRACKER); }
126 
ps_init_hash(unsigned long memcap)127 bool ps_init_hash(unsigned long memcap)
128 {
129     if ( portscan_hash )
130     {
131         bool need_pruning = (memcap < portscan_hash->get_mem_used());
132         portscan_hash->set_memcap(memcap);
133         return need_pruning;
134     }
135 
136     int rows = memcap / ps_node_size();
137     portscan_hash = new PortScanCache(rows, sizeof(PS_HASH_KEY), sizeof(PS_TRACKER),
138         memcap);
139 
140     return false;
141 }
142 
ps_prune_hash(unsigned work_limit)143 bool ps_prune_hash(unsigned work_limit)
144 {
145     if ( !portscan_hash )
146         return true;
147 
148     unsigned num_pruned = 0;
149     int result = portscan_hash->tune_memory_resources(work_limit, num_pruned);
150     spstats.reload_prunes += num_pruned;
151     return result != HASH_PENDING;
152 }
153 
ps_reset()154 void ps_reset()
155 {
156     if ( portscan_hash )
157         portscan_hash->clear_hash();
158 }
159 
160 //  Check scanner and scanned ips to see if we can filter them out.
ps_ignore_ip(const SfIp * scanner,uint16_t scanner_port,const SfIp * scanned,uint16_t scanned_port)161 bool PortScan::ps_ignore_ip(const SfIp* scanner, uint16_t scanner_port,
162     const SfIp* scanned, uint16_t scanned_port)
163 {
164     if (config->ignore_scanners)
165     {
166         if (ipset_contains(config->ignore_scanners, scanner, &scanner_port))
167             return true;
168     }
169 
170     if (config->ignore_scanned)
171     {
172         if (ipset_contains(config->ignore_scanned, scanned, &scanned_port))
173             return true;
174     }
175 
176     return false;
177 }
178 
179 /*
180 **  Check the incoming packet to decide whether portscan detection cares
181 **  about this packet.  We try to ignore as many packets as possible.
182 */
ps_filter_ignore(PS_PKT * ps_pkt)183 bool PortScan::ps_filter_ignore(PS_PKT* ps_pkt)
184 {
185     Packet* p;
186     int reverse_pkt = 0;
187     const SfIp* scanner, * scanned;
188 
189     p = (Packet*)ps_pkt->pkt;
190 
191     if(!p->ptrs.ip_api.is_ip())
192         return true;
193 
194     if (p->ptrs.tcph)
195     {
196         if ( !(config->detect_scans & PS_PROTO_TCP) )
197             return true;
198 
199         /*
200         **  This is where we check all of snort's flags for different
201         **  TCP session scenarios.  The checks cover:
202         **
203         **    - dropping packets in established sessions, but not the
204         **      TWH packet.
205         **    - dropping the SYN/ACK packet from the server on a valid
206         **      connection (we'll catch the TWH later if it happens).
207         */
208         /*
209         **  Ignore packets that are already part of an established TCP
210         **  stream.
211         */
212         if (((p->packet_flags & (PKT_STREAM_EST | PKT_STREAM_TWH))
213             == PKT_STREAM_EST) && !(p->ptrs.tcph->th_flags & TH_RST))
214         {
215             return true;
216         }
217 
218         /*
219         **  Ignore the server's initial response, unless it's to RST
220         **  the connection.
221         */
222         /*
223         if(!(p->ptrs.tcph->th_flags & TH_RST) &&
224            !(p->packet_flags & (PKT_STREAM_EST)) &&
225             (p->is_from_server()))
226         {
227             return true;
228         }
229         */
230     }
231     else if (p->ptrs.udph)
232     {
233         if ( !(config->detect_scans & PS_PROTO_UDP) )
234             return true;
235     }
236     else if (p->ptrs.icmph)
237     {
238         if ( p->ptrs.icmph->type != ICMP_DEST_UNREACH and !(config->detect_scans & PS_PROTO_ICMP) )
239             return true;
240     }
241     else
242     {
243         if ( !(config->detect_scans & PS_PROTO_IP) )
244             return true;
245     }
246 
247     //  Check if the packet is reversed
248     if ((p->is_from_server()))
249     {
250         reverse_pkt = 1;
251     }
252     else if (p->ptrs.icmph && p->ptrs.icmph->type == ICMP_DEST_UNREACH)
253     {
254         reverse_pkt = 1;
255     }
256     else if (p->ptrs.udph and p->flow )
257     {
258         if (Stream::get_packet_direction(p) & PKT_FROM_SERVER)
259             reverse_pkt = 1;
260     }
261 
262     scanner = p->ptrs.ip_api.get_src();
263     scanned = p->ptrs.ip_api.get_dst();
264 
265     if (reverse_pkt)
266     {
267         if (ps_ignore_ip(scanned, p->ptrs.dp, scanner, p->ptrs.sp))
268             return true;
269     }
270     else
271     {
272         if (ps_ignore_ip(scanner, p->ptrs.sp, scanned, p->ptrs.dp))
273             return true;
274     }
275 
276     ps_pkt->reverse_pkt = reverse_pkt;
277 
278     if (config->watch_ip)
279     {
280         if (ipset_contains(config->watch_ip, scanner, &(p->ptrs.sp)))
281             return false;
282 
283         if (ipset_contains(config->watch_ip, scanned, &(p->ptrs.dp)))
284             return false;
285 
286         return true;
287     }
288     return false;
289 }
290 
291 /*
292 **  Get a tracker node by either finding one or starting a new one.  We may
293 **  return null, in which case we wait `til the next packet.
294 */
ps_tracker_get(PS_HASH_KEY * key)295 static PS_TRACKER* ps_tracker_get(PS_HASH_KEY* key)
296 {
297     PS_TRACKER* ht = (PS_TRACKER*)portscan_hash->get_user_data((void*)key);
298 
299     if ( ht )
300         return ht;
301 
302     auto prev_count = portscan_hash->get_num_nodes();
303     if ( portscan_hash->insert((void*)key, nullptr) != HASH_OK )
304         return nullptr;
305 
306     ++spstats.trackers;
307     if ( prev_count == portscan_hash->get_num_nodes() )
308         ++spstats.alloc_prunes;
309 
310     ht = (PS_TRACKER*)portscan_hash->get_mru_user_data();
311 
312     if ( ht )
313         memset(ht, 0x00, sizeof(PS_TRACKER));
314 
315     return ht;
316 }
317 
ps_tracker_lookup(PS_PKT * ps_pkt,PS_TRACKER ** scanner,PS_TRACKER ** scanned)318 bool PortScan::ps_tracker_lookup(
319     PS_PKT* ps_pkt, PS_TRACKER** scanner, PS_TRACKER** scanned)
320 {
321     PS_HASH_KEY key;
322     Packet* p = (Packet*)ps_pkt->pkt;
323 
324     if (ps_get_proto(ps_pkt, &key.protocol) == -1)
325         return false;
326 
327     ps_pkt->proto = key.protocol;
328     key.asid = p->pkth->address_space_id;
329 
330     /*
331     **  Let's lookup the host that is being scanned, taking into account
332     **  the pkt may be reversed.
333     */
334     if (config->detect_scan_type &
335         (PS_TYPE_PORTSCAN | PS_TYPE_DECOYSCAN | PS_TYPE_DISTPORTSCAN))
336     {
337         key.scanner.clear();
338 
339         if (ps_pkt->reverse_pkt)
340         {
341             key.scanned = *p->ptrs.ip_api.get_src();
342             key.group = p->get_ingress_group();
343         }
344         else
345         {
346             key.scanned = *p->ptrs.ip_api.get_dst();
347             key.group = p->get_egress_group();
348         }
349 
350         *scanned = ps_tracker_get(&key);
351     }
352 
353     //  Let's lookup the host that is scanning.
354     if (config->detect_scan_type &
355         (PS_TYPE_PORTSWEEP | PS_TYPE_PORTSCAN | PS_TYPE_DECOYSCAN | PS_TYPE_DISTPORTSCAN))
356     {
357         key.scanned.clear();
358 
359         if (ps_pkt->reverse_pkt)
360         {
361             key.scanner = *p->ptrs.ip_api.get_dst();
362             key.group = p->get_egress_group();
363         }
364         else
365         {
366             key.scanner = *p->ptrs.ip_api.get_src();
367             key.group = p->get_ingress_group();
368         }
369 
370         *scanner = ps_tracker_get(&key);
371     }
372 
373     return *scanner or *scanned;
374 }
375 
376 /*
377 **  This logic finds the index to the proto array based on the
378 **  portscan configuration.  We need special logic because the
379 **  index of the protocol changes based on the configuration.
380 */
ps_get_proto(PS_PKT * ps_pkt,int * proto)381 int PortScan::ps_get_proto(PS_PKT* ps_pkt, int* proto)
382 {
383     Packet* p;
384 
385     if (!ps_pkt || !ps_pkt->pkt || !proto)
386         return -1;
387 
388     p = (Packet*)ps_pkt->pkt;
389     *proto = 0;
390 
391     if ( config->detect_scans & PS_PROTO_TCP )
392     {
393         if ((p->ptrs.tcph)
394             || ((p->ptrs.icmph) && (p->ptrs.icmph->type == ICMP_DEST_UNREACH)
395             && ((p->ptrs.icmph->code == ICMP_PORT_UNREACH)
396             || (p->ptrs.icmph->code == ICMP_PKT_FILTERED))
397             && (p->proto_bits & PROTO_BIT__TCP_EMBED_ICMP)))
398         {
399             *proto = PS_PROTO_TCP;
400             return 0;
401         }
402     }
403 
404     if ( config->detect_scans & PS_PROTO_UDP )
405     {
406         if ((p->ptrs.udph)
407             || ((p->ptrs.icmph) && (p->ptrs.icmph->type == ICMP_DEST_UNREACH)
408             && ((p->ptrs.icmph->code == ICMP_PORT_UNREACH)
409             || (p->ptrs.icmph->code == ICMP_PKT_FILTERED))
410             && (p->proto_bits & PROTO_BIT__UDP_EMBED_ICMP)))
411         {
412             *proto = PS_PROTO_UDP;
413             return 0;
414         }
415     }
416 
417     if ( config->detect_scans & PS_PROTO_IP )
418     {
419         if ((p->ptrs.ip_api.is_ip() && (!p->ptrs.icmph))
420             || ((p->ptrs.icmph) && (p->ptrs.icmph->type == ICMP_DEST_UNREACH)
421             && ((p->ptrs.icmph->code == ICMP_PROT_UNREACH)
422             || (p->ptrs.icmph->code == ICMP_PKT_FILTERED))))
423         {
424             *proto = PS_PROTO_IP;
425             return 0;
426         }
427     }
428 
429     if ( config->detect_scans & PS_PROTO_ICMP )
430     {
431         if (p->ptrs.icmph)
432         {
433             *proto = PS_PROTO_ICMP;
434             return 0;
435         }
436     }
437 
438     return -1;
439 }
440 
ps_proto_update_window(unsigned interval,PS_PROTO * proto,time_t pkt_time)441 void PortScan::ps_proto_update_window(unsigned interval, PS_PROTO* proto, time_t pkt_time)
442 {
443     if (pkt_time > proto->window)
444     {
445         memset(proto, 0x00, sizeof(PS_PROTO));
446 
447         proto->window = pkt_time + interval;
448     }
449 }
450 
451 /*
452 **  This function updates the PS_PROTO structure.
453 **
454 **  @param PS_PROTO pointer to structure to update
455 **  @param int      number to increment portscan counter
456 **  @param u_long   IP address of other host
457 **  @param unsigned short  port/ip_proto to track
458 **  @param time_t   time the packet was received. update windows.
459 */
ps_proto_update(PS_PROTO * proto,int ps_cnt,int pri_cnt,unsigned window,const SfIp * ip,unsigned short port,time_t pkt_time)460 int PortScan::ps_proto_update(PS_PROTO* proto, int ps_cnt, int pri_cnt,
461     unsigned window, const SfIp* ip, unsigned short port, time_t pkt_time)
462 {
463     if (!proto)
464         return 0;
465 
466     /*
467     **  If the ps_cnt is negative, that means we are just taking off
468     **  for valid connection, and we don't want to do anything else,
469     **  like update ip/port, etc.
470     */
471     if (ps_cnt < 0)
472     {
473         proto->connection_count += ps_cnt;
474         if (proto->connection_count < 0)
475             proto->connection_count = 0;
476 
477         return 0;
478     }
479 
480     /*
481     **  If we are updating a priority cnt, it means we already did the
482     **  unique port and IP on the connection packet.
483     **
484     **  Priority points are only added for invalid response packets.
485     */
486     if (pri_cnt)
487     {
488         proto->priority_count += pri_cnt;
489         if (proto->priority_count < 0)
490             proto->priority_count = 0;
491 
492         return 0;
493     }
494 
495     /*
496     **  Do time check first before we update the counters, so if
497     **  we need to reset them we do it before we update them.
498     */
499     ps_proto_update_window(window, proto, pkt_time);
500 
501     //  Update ps counter
502     proto->connection_count += ps_cnt;
503     if (proto->connection_count < 0)
504         proto->connection_count = 0;
505 
506     if (!proto->u_ips.equals(*ip, false))
507     {
508         proto->u_ip_count++;
509         proto->u_ips = *ip;
510     }
511 
512     /* we need to do the IP comparisons in host order */
513 
514     if (proto->low_ip.is_set())
515     {
516         if (proto->low_ip.greater_than(*ip))
517             proto->low_ip = *ip;
518     }
519     else
520     {
521         proto->low_ip = *ip;
522     }
523 
524     if (proto->high_ip.is_set())
525     {
526         if (proto->high_ip.less_than(*ip))
527             proto->high_ip = *ip;
528     }
529     else
530     {
531         proto->high_ip = *ip;
532     }
533 
534     if (proto->u_ports != port)
535     {
536         proto->u_port_count++;
537         proto->u_ports = port;
538     }
539 
540     if (proto->low_p)
541     {
542         if (proto->low_p > port)
543             proto->low_p = port;
544     }
545     else
546     {
547         proto->low_p = port;
548     }
549 
550     if (proto->high_p)
551     {
552         if (proto->high_p < port)
553             proto->high_p = port;
554     }
555     else
556     {
557         proto->high_p = port;
558     }
559 
560     return 0;
561 }
562 
ps_update_open_ports(PS_PROTO * proto,unsigned short port)563 static int ps_update_open_ports(PS_PROTO* proto, unsigned short port)
564 {
565     int iCtr;
566 
567     for (iCtr = 0; iCtr < proto->open_ports_cnt; iCtr++)
568     {
569         if (port == proto->open_ports[iCtr])
570             return 0;
571     }
572 
573     if (iCtr < (PS_OPEN_PORTS - 1))
574     {
575         proto->open_ports[iCtr] = port;
576         proto->open_ports_cnt++;
577     }
578 
579     return 0;
580 }
581 
582 /*
583 **  Determine how to update the portscan counter depending on the type
584 **  of TCP packet we have.
585 **
586 **  We are concerned with three types of TCP packets:
587 **
588 **    - initiating TCP packets (we don't care about flags)
589 **    - TCP 3-way handshake packets (we decrement the counter)
590 **    - TCP reset packets on unestablished streams.
591 */
ps_tracker_update_tcp(PS_PKT * ps_pkt,PS_TRACKER * scanner,PS_TRACKER * scanned)592 void PortScan::ps_tracker_update_tcp(PS_PKT* ps_pkt, PS_TRACKER* scanner,
593     PS_TRACKER* scanned)
594 {
595     Packet* p = (Packet*)ps_pkt->pkt;
596     unsigned win = config->tcp_window;
597 
598     SfIp cleared;
599     cleared.clear();
600 
601     /*
602     **  Handle the initiating packet.
603     **
604     **  If this what stream4 considers to be a valid initiator, then
605     **  we will use the available stream4 information.  Otherwise, we
606     **  can just revert to flow and look for initiators and responders.
607     **
608     **  For Stream, depending on the configuration, there might not
609     **  be a session created only based on the SYN packet.  Stream
610     **  by default has code that helps deal with SYN flood attacks,
611     **  and may simply ignore the SYN.  In this case, we fall through
612     **  to the checks for specific TCP header files (SYN, SYN-ACK, RST).
613     **
614     **  The "midstream" logic below says that, if we include sessions
615     **  picked up midstream, then we don't care about the MIDSTREAM flag.
616     **  Otherwise, only consider streams not picked up midstream.
617     */
618     // FIXIT-E using SSNFLAG_COUNTED_INITIALIZE is a hack to get parity with 2.X
619     // this should be completely redone and port_scan should require stream_tcp
620     if ( p->flow and (p->flow->ssn_state.session_flags & SSNFLAG_COUNTED_INITIALIZE) )
621     {
622         uint32_t session_flags = p->flow->get_session_flags();
623 
624         if ((session_flags & SSNFLAG_SEEN_CLIENT) &&
625             !(session_flags & SSNFLAG_SEEN_SERVER) &&
626             (config->include_midstream || !(session_flags & SSNFLAG_MIDSTREAM)))
627         {
628             if (scanned)
629             {
630                 ps_proto_update(&scanned->proto, 1, 0, win,
631                     p->ptrs.ip_api.get_src(), p->ptrs.dp, packet_time());
632             }
633 
634             if (scanner)
635             {
636                 ps_proto_update(&scanner->proto, 1, 0, win,
637                     p->ptrs.ip_api.get_dst(), p->ptrs.dp, packet_time());
638             }
639         }
640         //  Handle the final packet of the three-way handshake.
641         else if (p->packet_flags & PKT_STREAM_TWH)
642         {
643             if (scanned)
644             {
645                 ps_proto_update(&scanned->proto, -1, 0, win, &cleared, 0, 0);
646             }
647 
648             if (scanner)
649             {
650                 ps_proto_update(&scanner->proto, -1, 0, win, &cleared, 0, 0);
651             }
652         }
653         //  RST packet on unestablished streams
654         else if ((p->is_from_server()) &&
655             (p->ptrs.tcph && (p->ptrs.tcph->th_flags & TH_RST)) &&
656             (!(p->packet_flags & PKT_STREAM_EST) ||
657             (session_flags & SSNFLAG_MIDSTREAM)))
658         {
659             if (scanned)
660             {
661                 ps_proto_update(&scanned->proto, 0, 1, win, &cleared, 0, 0);
662                 scanned->priority_node = 1;
663             }
664 
665             if (scanner)
666             {
667                 ps_proto_update(&scanner->proto, 0, 1, win, &cleared, 0, 0);
668                 scanner->priority_node = 1;
669             }
670         }
671         /*
672         **  We only get here on the server's response to the initial
673         **  client connection.
674         **
675         **  That's why we use the sp, because that's the port that is
676         **  open.
677         */
678         else if ((p->is_from_server()) &&
679             !(p->packet_flags & PKT_STREAM_EST))
680         {
681             if (scanned)
682                 ps_update_open_ports(&scanned->proto, p->ptrs.sp);
683         }
684     }
685     /*
686     ** Stream didn't create a session on the SYN packet,
687     ** so check specifically for SYN here.
688     */
689     else if ( p->ptrs.tcph and p->ptrs.tcph->is_syn_only() )
690     {
691         /* No session established, packet only has SYN.  SYN only
692         ** packet always from client, so use dp.
693         */
694         if (scanned)
695         {
696             ps_proto_update(&scanned->proto, 1, 0, win,
697                 p->ptrs.ip_api.get_src(), p->ptrs.dp, packet_time());
698         }
699 
700         if (scanner)
701         {
702             ps_proto_update(&scanner->proto, 1, 0, win,
703                 p->ptrs.ip_api.get_dst(), p->ptrs.dp, packet_time());
704         }
705     }
706     /*
707     ** Stream didn't create a session on the SYN packet,
708     ** so check specifically for SYN & ACK here.  Clear based
709     ** on the 'completion' of three-way handshake.
710     */
711     else if ( p->ptrs.tcph and p->ptrs.tcph->is_syn_ack() )
712     {
713         if (scanned)
714         {
715             ps_proto_update(&scanned->proto, -1, 0, win, &cleared, 0, 0);
716         }
717 
718         if (scanner)
719         {
720             ps_proto_update(&scanner->proto, -1, 0, win, &cleared, 0, 0);
721         }
722     }
723     /*
724     ** No session created, clear based on the RST on non
725     ** established session.
726     */
727     else if (p->ptrs.tcph && (p->ptrs.tcph->th_flags & TH_RST))
728     {
729         if (scanned)
730         {
731             ps_proto_update(&scanned->proto, 0, 1, win, &cleared, 0, 0);
732             scanned->priority_node = 1;
733         }
734 
735         if (scanner)
736         {
737             ps_proto_update(&scanner->proto, 0, 1, win, &cleared, 0, 0);
738             scanner->priority_node = 1;
739         }
740     }
741     //  If we are an icmp unreachable, deal with it here.
742     else if (p->ptrs.icmph)
743     {
744         if (scanned)
745         {
746             ps_proto_update(&scanned->proto, 0, 1, win, &cleared, 0, 0);
747             scanned->priority_node = 1;
748         }
749 
750         if (scanner)
751         {
752             ps_proto_update(&scanner->proto, 0, 1, win, &cleared, 0, 0);
753             scanner->priority_node = 1;
754         }
755     }
756 }
757 
ps_tracker_update_ip(PS_PKT * ps_pkt,PS_TRACKER * scanner,PS_TRACKER * scanned)758 void PortScan::ps_tracker_update_ip(PS_PKT* ps_pkt, PS_TRACKER* scanner,
759     PS_TRACKER* scanned)
760 {
761     Packet* p = (Packet*)ps_pkt->pkt;
762 
763     if ( !p->ptrs.ip_api.is_ip() )
764         return;
765 
766     unsigned win = config->ip_window;
767     SfIp cleared;
768     cleared.clear();
769 
770     if (p->ptrs.icmph and (p->ptrs.icmph->type == ICMP_DEST_UNREACH))
771     {
772         if (p->ptrs.icmph->code == ICMP_PROT_UNREACH)
773         {
774             if (scanned)
775             {
776                 ps_proto_update(&scanned->proto, 0, 1, win, &cleared, 0, 0);
777                 scanned->priority_node = 1;
778             }
779             if(scanner)
780             {
781                 ps_proto_update(&scanner->proto, 0, 1, win, &cleared, 0, 0);
782                 scanner->priority_node = 1;
783             }
784         }
785         else
786             return;
787     }
788     else
789     {
790         if (scanned)
791         {
792             ps_proto_update(&scanned->proto, 1, 0, win, p->ptrs.ip_api.get_src(),
793                 (unsigned short)p->get_ip_proto_next(), packet_time());
794         }
795         if (scanner)
796         {
797             ps_proto_update(&scanner->proto, 1, 0, win, p->ptrs.ip_api.get_dst(),
798                 (unsigned short)p->get_ip_proto_next(), packet_time());
799         }
800     }
801 }
802 
ps_tracker_update_udp(PS_PKT * ps_pkt,PS_TRACKER * scanner,PS_TRACKER * scanned)803 void PortScan::ps_tracker_update_udp(
804     PS_PKT* ps_pkt, PS_TRACKER* scanner, PS_TRACKER* scanned)
805 {
806     Packet* p = (Packet*)ps_pkt->pkt;
807     unsigned win = config->udp_window;
808 
809     SfIp cleared;
810     cleared.clear();
811 
812     if (p->ptrs.icmph)
813     {
814         if (scanned)
815         {
816             ps_proto_update(&scanned->proto, 0, 1, win, &cleared, 0, 0);
817             scanned->priority_node = 1;
818         }
819 
820         if (scanner)
821         {
822             ps_proto_update(&scanner->proto, 0, 1, win, &cleared, 0, 0);
823             scanner->priority_node = 1;
824         }
825     }
826     else if (p->ptrs.udph)
827     {
828         if ( p->flow )
829         {
830             uint32_t direction = Stream::get_packet_direction(p);
831 
832             if (direction == PKT_FROM_CLIENT)
833             {
834                 if (scanned)
835                 {
836                     ps_proto_update(&scanned->proto, 1, 0, win,
837                         p->ptrs.ip_api.get_src(), p->ptrs.dp, packet_time());
838                 }
839 
840                 if (scanner)
841                 {
842                     ps_proto_update(&scanner->proto, 1, 0, win,
843                         p->ptrs.ip_api.get_dst(), p->ptrs.dp, packet_time());
844                 }
845             }
846             else if (direction == PKT_FROM_SERVER)
847             {
848                 if (scanned)
849                     ps_proto_update(&scanned->proto, -1, 0, win, &cleared, 0, 0);
850 
851                 if (scanner)
852                     ps_proto_update(&scanner->proto, -1, 0, win, &cleared, 0, 0);
853             }
854         }
855     }
856 }
857 
ps_tracker_update_icmp(PS_PKT * ps_pkt,PS_TRACKER * scanner,PS_TRACKER *)858 void PortScan::ps_tracker_update_icmp(
859     PS_PKT* ps_pkt, PS_TRACKER* scanner, PS_TRACKER*)
860 {
861     Packet* p = (Packet*)ps_pkt->pkt;
862     unsigned win = config->icmp_window;
863 
864     if (p->ptrs.icmph)
865     {
866         switch (p->ptrs.icmph->type)
867         {
868         case ICMP_ECHO:
869         case ICMP_TIMESTAMP:
870         case ICMP_ADDRESS:
871         case ICMP_INFO_REQUEST:
872             if (scanner)
873             {
874                 ps_proto_update(&scanner->proto, 1, 0, win,
875                     p->ptrs.ip_api.get_dst(), 0, packet_time());
876             }
877             break;
878 
879         case ICMP_DEST_UNREACH:
880             if (scanner)
881             {
882                 SfIp cleared;
883                 cleared.clear();
884 
885                 ps_proto_update(&scanner->proto, 0, 1, win, &cleared, 0, 0);
886                 scanner->priority_node = 1;
887             }
888             break;
889 
890         default:
891             break;
892         }
893     }
894 }
895 
896 /*
897 **  At this point, we should only be looking at transport protocols
898 **  that we want to.  For instance, if we aren't doing UDP portscans
899 **  then we won't see UDP packets here because they were ignored.
900 **
901 **  This is where we evaluate the packet to add/subtract portscan
902 **  tracker values and prioritize a tracker.  We also update the
903 **  time windows.
904 */
ps_tracker_update(PS_PKT * ps_pkt,PS_TRACKER * scanner,PS_TRACKER * scanned)905 bool PortScan::ps_tracker_update(PS_PKT* ps_pkt, PS_TRACKER* scanner, PS_TRACKER* scanned)
906 {
907     if ( scanner and scanner->proto.alerts )
908         scanner->proto.alerts = PS_ALERT_GENERATED;
909 
910     if ( scanned and scanned->proto.alerts )
911         scanned->proto.alerts = PS_ALERT_GENERATED;
912 
913     switch ( ps_pkt->proto )
914     {
915     case PS_PROTO_TCP:
916         ps_tracker_update_tcp(ps_pkt, scanner, scanned);
917         break;
918 
919     case PS_PROTO_UDP:
920         ps_tracker_update_udp(ps_pkt, scanner, scanned);
921         break;
922 
923     case PS_PROTO_ICMP:
924         ps_tracker_update_icmp(ps_pkt, scanner, scanned);
925         break;
926 
927     case PS_PROTO_IP:
928         ps_tracker_update_ip(ps_pkt, scanner, scanned);
929         break;
930 
931     default:
932         return false;
933     }
934     return true;
935 }
936 
ps_alert_one_to_one(const PS_ALERT_CONF & conf,PS_PROTO * scanner,PS_PROTO * scanned)937 static bool ps_alert_one_to_one(
938     const PS_ALERT_CONF& conf, PS_PROTO* scanner, PS_PROTO* scanned)
939 {
940     //  Let's evaluate the scanned host.
941     if (scanned && !scanned->alerts)
942     {
943         if (scanned->priority_count >= conf.priority_count)
944         {
945             if (scanned->u_ip_count < conf.u_ip_count &&
946                 scanned->u_port_count >= conf.u_port_count)
947             {
948                 if (scanner)
949                 {
950                     if (scanner->priority_count >= conf.priority_count)
951                     {
952                         //  Now let's check to make sure this is one to one
953                         scanned->alerts = PS_ALERT_ONE_TO_ONE;
954                         return true;
955                     }
956                 }
957                 else
958                 {
959                     //  If there is no scanner, then we do the best we can.
960                     scanned->alerts = PS_ALERT_ONE_TO_ONE;
961                     return true;
962                 }
963             }
964         }
965         if (scanned->connection_count >= conf.connection_count)
966         {
967             if (conf.connection_count == 0)
968                 return false;
969 
970             if (scanned->u_ip_count < conf.u_ip_count &&
971                 scanned->u_port_count >= conf.u_port_count)
972             {
973                 scanned->alerts = PS_ALERT_ONE_TO_ONE_FILTERED;
974                 return true;
975             }
976         }
977     }
978 
979     return false;
980 }
981 
ps_alert_one_to_one_decoy(const PS_ALERT_CONF & conf,PS_PROTO * scanner,PS_PROTO * scanned)982 static bool ps_alert_one_to_one_decoy(
983     const PS_ALERT_CONF& conf, PS_PROTO* scanner, PS_PROTO* scanned)
984 {
985     if (scanned && !scanned->alerts)
986     {
987         if (scanned->priority_count >= conf.priority_count)
988         {
989             if (scanned->u_ip_count >= conf.u_ip_count &&
990                 scanned->u_port_count >= conf.u_port_count)
991             {
992                 if (scanner && scanner->u_port_count >= conf.u_port_count)
993                 {
994                     scanned->alerts = PS_ALERT_ONE_TO_ONE_DECOY;
995                     return true;
996                 }
997             }
998         }
999         if (scanned->connection_count >= conf.connection_count)
1000         {
1001             if (conf.connection_count == 0)
1002                 return false;
1003 
1004             if (scanned->u_ip_count >= conf.u_ip_count &&
1005                 scanned->u_port_count >= conf.u_port_count)
1006             {
1007                 if (scanner && scanner->u_port_count >= conf.u_port_count)
1008                 {
1009                     scanned->alerts = PS_ALERT_ONE_TO_ONE_DECOY_FILTERED;
1010                     return true;
1011                 }
1012             }
1013         }
1014     }
1015 
1016     return false;
1017 }
1018 
ps_alert_many_to_one(const PS_ALERT_CONF & conf,PS_PROTO * scanner,PS_PROTO * scanned)1019 static bool ps_alert_many_to_one(
1020     const PS_ALERT_CONF& conf, PS_PROTO* scanner, PS_PROTO* scanned)
1021 {
1022     if (scanned && !scanned->alerts)
1023     {
1024         if (scanned->priority_count >= conf.priority_count)
1025         {
1026             if (scanned->u_ip_count >= conf.u_ip_count &&
1027                 scanned->u_port_count >= conf.u_port_count)
1028             {
1029                 if (scanner && scanner->u_port_count <= conf.u_port_count)
1030                 {
1031                     scanned->alerts = PS_ALERT_DISTRIBUTED;
1032                     return true;
1033                 }
1034             }
1035         }
1036         if (scanned->connection_count >= conf.connection_count)
1037         {
1038             if (conf.connection_count == 0)
1039                 return false;
1040 
1041             if (scanned->u_ip_count >= conf.u_ip_count &&
1042                 scanned->u_port_count >= conf.u_port_count)
1043             {
1044                 if (scanner && scanner->u_port_count <= conf.u_port_count)
1045                 {
1046                     scanned->alerts = PS_ALERT_DISTRIBUTED_FILTERED;
1047                     return true;
1048                 }
1049             }
1050         }
1051     }
1052 
1053     return false;
1054 }
1055 
ps_alert_one_to_many(const PS_ALERT_CONF & conf,PS_PROTO * scanner,PS_PROTO *)1056 static bool ps_alert_one_to_many(
1057     const PS_ALERT_CONF& conf, PS_PROTO* scanner, PS_PROTO*)
1058 {
1059     if (scanner && !scanner->alerts)
1060     {
1061         if (scanner->priority_count >= conf.priority_count)
1062         {
1063             if (scanner->u_ip_count >= conf.u_ip_count &&
1064                 scanner->u_port_count <= conf.u_port_count)
1065             {
1066                 scanner->alerts = PS_ALERT_PORTSWEEP;
1067                 return true;
1068             }
1069         }
1070         if (scanner->connection_count >= conf.connection_count)
1071         {
1072             if (conf.connection_count == 0)
1073                 return false;
1074 
1075             if (scanner->u_ip_count >= conf.u_ip_count &&
1076                 scanner->u_port_count <= conf.u_port_count)
1077             {
1078                 scanner->alerts = PS_ALERT_PORTSWEEP_FILTERED;
1079                 return true;
1080             }
1081         }
1082     }
1083 
1084     return false;
1085 }
1086 
ps_alert_tcp(PS_PROTO * scanner,PS_PROTO * scanned)1087 void PortScan::ps_alert_tcp(PS_PROTO* scanner, PS_PROTO* scanned)
1088 {
1089     if ((config->detect_scan_type & PS_TYPE_PORTSCAN) &&
1090         ps_alert_one_to_one(config->tcp_ports, scanner, scanned))
1091     {
1092         return;
1093     }
1094 
1095     if ((config->detect_scan_type & PS_TYPE_DECOYSCAN) &&
1096         ps_alert_one_to_one_decoy(config->tcp_decoy, scanner, scanned))
1097     {
1098         return;
1099     }
1100 
1101     if ((config->detect_scan_type & PS_TYPE_PORTSWEEP) &&
1102         ps_alert_one_to_many(config->tcp_sweep, scanner, scanned))
1103     {
1104         return;
1105     }
1106 
1107     if ((config->detect_scan_type & PS_TYPE_DISTPORTSCAN) &&
1108         ps_alert_many_to_one(config->tcp_dist, scanner, scanned))
1109     {
1110         return;
1111     }
1112 }
1113 
ps_alert_ip(PS_PROTO * scanner,PS_PROTO * scanned)1114 void PortScan::ps_alert_ip(PS_PROTO* scanner, PS_PROTO* scanned)
1115 {
1116     if ((config->detect_scan_type & PS_TYPE_PORTSCAN) &&
1117         ps_alert_one_to_one(config->ip_proto, scanner, scanned))
1118     {
1119         return;
1120     }
1121 
1122     if ((config->detect_scan_type & PS_TYPE_DECOYSCAN) &&
1123         ps_alert_one_to_one_decoy(config->ip_decoy, scanner, scanned))
1124     {
1125         return;
1126     }
1127 
1128     if ((config->detect_scan_type & PS_TYPE_PORTSWEEP) &&
1129         ps_alert_one_to_many(config->ip_sweep, scanner, scanned))
1130     {
1131         return;
1132     }
1133 
1134     if ((config->detect_scan_type & PS_TYPE_DISTPORTSCAN) &&
1135         ps_alert_many_to_one(config->ip_dist, scanner, scanned))
1136     {
1137         return;
1138     }
1139 }
1140 
ps_alert_udp(PS_PROTO * scanner,PS_PROTO * scanned)1141 void PortScan::ps_alert_udp(PS_PROTO* scanner, PS_PROTO* scanned)
1142 {
1143     if ((config->detect_scan_type & PS_TYPE_PORTSCAN) &&
1144         ps_alert_one_to_one(config->udp_ports, scanner,  scanned))
1145     {
1146         return;
1147     }
1148 
1149     if ((config->detect_scan_type & PS_TYPE_DECOYSCAN) &&
1150         ps_alert_one_to_one_decoy(config->udp_decoy, scanner, scanned))
1151     {
1152         return;
1153     }
1154 
1155     if ((config->detect_scan_type & PS_TYPE_PORTSWEEP) &&
1156         ps_alert_one_to_many(config->udp_sweep, scanner, scanned))
1157     {
1158         return;
1159     }
1160 
1161     if ((config->detect_scan_type & PS_TYPE_DISTPORTSCAN) &&
1162         ps_alert_many_to_one(config->udp_dist, scanner, scanned))
1163     {
1164         return;
1165     }
1166 }
1167 
ps_alert_icmp(PS_PROTO * scanner,PS_PROTO * scanned)1168 void PortScan::ps_alert_icmp(PS_PROTO* scanner, PS_PROTO* scanned)
1169 {
1170     if ((config->detect_scan_type & PS_TYPE_PORTSWEEP) &&
1171         ps_alert_one_to_many(config->icmp_sweep, scanner, scanned))
1172     {
1173         return;
1174     }
1175 }
1176 
1177 /*
1178 **  This function evaluates the scanner and scanned trackers and if
1179 **  applicable, generate an alert or alerts for either of the trackers.
1180 **
1181 **  The following alerts can be generated:
1182 **    - One to One Portscan
1183 **    - One to One Decoy Portscan
1184 **    - One to Many Portsweep
1185 **    - Distributed Portscan (Many to One)
1186 **    - Filtered Portscan?
1187 */
ps_tracker_alert(PS_PKT * ps_pkt,PS_TRACKER * scanner,PS_TRACKER * scanned)1188 bool PortScan::ps_tracker_alert(
1189     PS_PKT* ps_pkt, PS_TRACKER* scanner, PS_TRACKER* scanned)
1190 {
1191     PS_PROTO* scanner_proto = nullptr;
1192     PS_PROTO* scanned_proto = nullptr;
1193 
1194     if ( scanner )
1195     {
1196         if ( config->alert_all )
1197             scanner->proto.alerts = 0;
1198         scanner_proto = &scanner->proto;
1199     }
1200 
1201     if ( scanned )
1202     {
1203         if ( config->alert_all )
1204             scanned->proto.alerts = 0;
1205         scanned_proto = &scanned->proto;
1206     }
1207 
1208     switch (ps_pkt->proto)
1209     {
1210     case PS_PROTO_TCP:
1211         ps_alert_tcp(scanner_proto, scanned_proto);
1212         break;
1213 
1214     case PS_PROTO_UDP:
1215         ps_alert_udp(scanner_proto, scanned_proto);
1216         break;
1217 
1218     case PS_PROTO_ICMP:
1219         ps_alert_icmp(scanner_proto, scanned_proto);
1220         break;
1221 
1222     case PS_PROTO_IP:
1223         ps_alert_ip(scanner_proto, scanned_proto);
1224         break;
1225 
1226     default:
1227         return false;
1228     }
1229 
1230     return true;
1231 }
1232 
1233 /*
1234 **  The design of portscan is as follows:
1235 **
1236 **    - Filter Packet.  Is the packet part of the ignore or watch list?  Is
1237 **      the packet part of an established TCP session (we ignore it)?
1238 **
1239 **    - Tracker Lookup.  We lookup trackers for src and dst if either is in
1240 **      the watch list, or not in the ignore list if there is no watch list.
1241 **      If there is not tracker, we create a new one and keep track, both of
1242 **      the scanned host and the scanning host.
1243 **
1244 **    - Tracker Update.  We update the tracker using the incoming packet.  If
1245 **      the update causes a portscan alert, then we move into the log alert
1246 **      phase.
1247 **
1248 **    - Tracker Evaluate.  Generate an alert from the updated tracker.  We
1249 **      decide whether we are logging a portscan or sweep (based on the
1250 **      scanning or scanned host, we decide which is more relevant).
1251 */
ps_detect(PS_PKT * ps_pkt)1252 int PortScan::ps_detect(PS_PKT* ps_pkt)
1253 {
1254     PS_TRACKER* scanner = nullptr;
1255     PS_TRACKER* scanned = nullptr;
1256     int check_tcp_rst_other_dir = 1;
1257 
1258     assert(ps_pkt and ps_pkt->pkt);
1259 
1260     if (ps_filter_ignore(ps_pkt))
1261         return 0;
1262 
1263     Packet* p = (Packet*)ps_pkt->pkt;
1264 
1265     do
1266     {
1267         if ( !ps_tracker_lookup(ps_pkt, &scanner, &scanned) )
1268             return 0;
1269 
1270         if ( !ps_tracker_update(ps_pkt, scanner, scanned) )
1271             return 0;
1272 
1273         if ( !ps_tracker_alert(ps_pkt, scanner, scanned) )
1274             return 0;
1275 
1276         /* This is added to address the case of no
1277          * session and a RST packet going back from the Server. */
1278         if ( p->ptrs.tcph and (p->ptrs.tcph->th_flags & TH_RST) and !p->flow )
1279         {
1280             if (ps_pkt->reverse_pkt == 1)
1281                 check_tcp_rst_other_dir = 0;
1282             else
1283                 ps_pkt->reverse_pkt = 1;
1284         }
1285         else
1286         {
1287             check_tcp_rst_other_dir = 0;
1288         }
1289     }
1290     while (check_tcp_rst_other_dir);
1291 
1292     ps_pkt->scanner = scanner;
1293     ps_pkt->scanned = scanned;
1294 
1295     return 1;
1296 }
1297 
1298