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 // sfportscan.c author Daniel Roelker <droelker@sourcefire.com>
21 // port_scan.cc author Russ Combs <rucombs@cisco.com>
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "detection/detection_engine.h"
28 #include "log/messages.h"
29 #include "managers/inspector_manager.h"
30 #include "profiler/profiler.h"
31 #include "utils/util.h"
32 #include "utils/util_cstring.h"
33
34 #include "ps_inspect.h"
35 #include "ps_module.h"
36
37 using namespace snort;
38
39 THREAD_LOCAL PsPegStats spstats;
40 THREAD_LOCAL ProfileStats psPerfStats;
41
make_port_scan_info(Packet * p,PS_PROTO * proto)42 static void make_port_scan_info(Packet* p, PS_PROTO* proto)
43 {
44 DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
45
46 SfIp* ip1 = &proto->low_ip;
47 SfIp* ip2 = &proto->high_ip;
48
49 char a1[INET6_ADDRSTRLEN];
50 char a2[INET6_ADDRSTRLEN];
51
52 ip1->ntop(a1, sizeof(a1));
53 ip2->ntop(a2, sizeof(a2));
54
55 char type;
56
57 if ( proto->alerts == PS_ALERT_PORTSWEEP or proto->alerts == PS_ALERT_PORTSWEEP_FILTERED )
58 type = 'd';
59 else
60 type = 'r';
61
62 buf.len = safe_snprintf((char*)buf.data, sizeof(buf.data),
63 "Priority Count: %d\n"
64 "Connection Count: %d\n"
65 "IP Count: %d\n"
66 "Scanne%c IP Range: %s:%s\n"
67 "Port/Proto Count: %d\n"
68 "Port/Proto Range: %d:%d\n",
69 proto->priority_count,
70 proto->connection_count,
71 proto->u_ip_count,
72 type, a1, a2,
73 proto->u_port_count,
74 proto->low_p, proto->high_p);
75 }
76
make_open_port_info(Packet * p,PS_PROTO * proto)77 static void make_open_port_info(Packet* p, PS_PROTO* proto)
78 {
79 DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
80
81 SfIp* ip1 = &proto->low_ip;
82 char a1[INET6_ADDRSTRLEN];
83 ip1->ntop(a1, sizeof(a1));
84
85 buf.len += safe_snprintf((char*)buf.data+buf.len, sizeof(buf.data)-buf.len,
86 "Scanned IP: %s\n"
87 "Port Count: %d\n"
88 "Open Ports:",
89 a1,
90 proto->open_ports_cnt);
91
92 for ( int i = 0; i < proto->open_ports_cnt; i++ )
93 {
94 buf.len += safe_snprintf(
95 (char*)buf.data + buf.len, sizeof(buf.data) - buf.len, " %hu", proto->open_ports[i]);
96 }
97 buf.len += safe_snprintf((char*)buf.data + buf.len, sizeof(buf.data) - buf.len, "\n");
98 }
99
100 #if 0
101 // FIXIT-L add open port for port sweeps
102 static void make_open_port_info(Packet* p, uint16_t port)
103 {
104 DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
105
106 SfIpString ip_str;
107
108 buf.len = safe_snprintf((char*)buf.data, sizeof(buf.data),
109 "Scanned IP: %s\n"
110 "Open Port: %hu\n",
111 p->ptrs.ip_api.get_src()->ntop(ip_str), port);
112 }
113 #endif
114
PortscanAlertTcp(Packet * p,PS_PROTO * proto)115 static void PortscanAlertTcp(Packet* p, PS_PROTO* proto)
116 {
117 assert(proto);
118
119 if ( proto->open_ports_cnt and proto->alerts != PS_ALERT_PORTSWEEP and
120 proto->alerts != PS_ALERT_PORTSWEEP_FILTERED )
121 {
122 make_open_port_info(p, proto);
123 }
124 switch (proto->alerts)
125 {
126 case PS_ALERT_ONE_TO_ONE:
127 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_TCP_PORTSCAN);
128 break;
129
130 case PS_ALERT_ONE_TO_ONE_DECOY:
131 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_TCP_DECOY_PORTSCAN);
132 break;
133
134 case PS_ALERT_PORTSWEEP:
135 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_TCP_PORTSWEEP);
136 break;
137
138 case PS_ALERT_DISTRIBUTED:
139 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_TCP_DISTRIBUTED_PORTSCAN);
140 break;
141
142 case PS_ALERT_ONE_TO_ONE_FILTERED:
143 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_TCP_FILTERED_PORTSCAN);
144 break;
145
146 case PS_ALERT_ONE_TO_ONE_DECOY_FILTERED:
147 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_TCP_FILTERED_DECOY_PORTSCAN);
148 break;
149
150 case PS_ALERT_PORTSWEEP_FILTERED:
151 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_TCP_PORTSWEEP_FILTERED);
152 break;
153
154 case PS_ALERT_DISTRIBUTED_FILTERED:
155 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_TCP_FILTERED_DISTRIBUTED_PORTSCAN);
156 break;
157
158 default:
159 return;
160 }
161 }
162
PortscanAlertUdp(Packet *,PS_PROTO * proto)163 static void PortscanAlertUdp(Packet*, PS_PROTO* proto)
164 {
165 assert(proto);
166
167 switch (proto->alerts)
168 {
169 case PS_ALERT_ONE_TO_ONE:
170 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_UDP_PORTSCAN);
171 break;
172
173 case PS_ALERT_ONE_TO_ONE_DECOY:
174 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_UDP_DECOY_PORTSCAN);
175 break;
176
177 case PS_ALERT_PORTSWEEP:
178 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_UDP_PORTSWEEP);
179 break;
180
181 case PS_ALERT_DISTRIBUTED:
182 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_UDP_DISTRIBUTED_PORTSCAN);
183 break;
184
185 case PS_ALERT_ONE_TO_ONE_FILTERED:
186 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_UDP_FILTERED_PORTSCAN);
187 break;
188
189 case PS_ALERT_ONE_TO_ONE_DECOY_FILTERED:
190 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_UDP_FILTERED_DECOY_PORTSCAN);
191 break;
192
193 case PS_ALERT_PORTSWEEP_FILTERED:
194 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_UDP_PORTSWEEP_FILTERED);
195 break;
196
197 case PS_ALERT_DISTRIBUTED_FILTERED:
198 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_UDP_FILTERED_DISTRIBUTED_PORTSCAN);
199 break;
200
201 default:
202 break;
203 }
204 }
205
PortscanAlertIp(Packet *,PS_PROTO * proto)206 static void PortscanAlertIp(Packet*, PS_PROTO* proto)
207 {
208 assert(proto);
209
210 switch (proto->alerts)
211 {
212 case PS_ALERT_ONE_TO_ONE:
213 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_IP_PORTSCAN);
214 break;
215
216 case PS_ALERT_ONE_TO_ONE_DECOY:
217 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_IP_DECOY_PORTSCAN);
218 break;
219
220 case PS_ALERT_PORTSWEEP:
221 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_IP_PORTSWEEP);
222 break;
223
224 case PS_ALERT_DISTRIBUTED:
225 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_IP_DISTRIBUTED_PORTSCAN);
226 break;
227
228 case PS_ALERT_ONE_TO_ONE_FILTERED:
229 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_IP_FILTERED_PORTSCAN);
230 break;
231
232 case PS_ALERT_ONE_TO_ONE_DECOY_FILTERED:
233 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_IP_FILTERED_DECOY_PORTSCAN);
234 break;
235
236 case PS_ALERT_PORTSWEEP_FILTERED:
237 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_IP_PORTSWEEP_FILTERED);
238 break;
239
240 case PS_ALERT_DISTRIBUTED_FILTERED:
241 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_IP_FILTERED_DISTRIBUTED_PORTSCAN);
242 break;
243
244 default:
245 break;
246 }
247 }
248
PortscanAlertIcmp(Packet *,PS_PROTO * proto)249 static void PortscanAlertIcmp(Packet*, PS_PROTO* proto)
250 {
251 assert(proto);
252
253 switch (proto->alerts)
254 {
255 case PS_ALERT_PORTSWEEP:
256 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_ICMP_PORTSWEEP);
257 break;
258
259 case PS_ALERT_PORTSWEEP_FILTERED:
260 DetectionEngine::queue_event(GID_PORT_SCAN, PSNG_ICMP_PORTSWEEP_FILTERED);
261 break;
262
263 default:
264 break;
265 }
266 }
267
PortscanAlert(PS_PKT * ps_pkt,PS_PROTO * proto,int proto_type)268 static void PortscanAlert(PS_PKT* ps_pkt, PS_PROTO* proto, int proto_type)
269 {
270 Packet* p = ps_pkt->pkt;
271 make_port_scan_info(p, proto);
272
273 switch (proto_type)
274 {
275 case PS_PROTO_TCP:
276 PortscanAlertTcp(p, proto);
277 break;
278
279 case PS_PROTO_UDP:
280 PortscanAlertUdp(p, proto);
281 break;
282
283 case PS_PROTO_ICMP:
284 PortscanAlertIcmp(p, proto);
285 break;
286
287 case PS_PROTO_IP:
288 PortscanAlertIp(p, proto);
289 break;
290 }
291 }
292
get_protos(int ds)293 static std::string get_protos(int ds)
294 {
295 std::string protos;
296
297 if ( !ds )
298 return "none";
299 if ( (ds & PS_PROTO_ALL) == PS_PROTO_ALL )
300 return "all";
301 if ( ds & PS_PROTO_TCP )
302 protos += "tcp ";
303 if ( ds & PS_PROTO_UDP )
304 protos += "udp ";
305 if ( ds & PS_PROTO_ICMP )
306 protos += "icmp ";
307 if ( ds & PS_PROTO_IP )
308 protos += "ip ";
309
310 protos.pop_back();
311
312 return protos;
313 }
314
get_types(int dst)315 static std::string get_types(int dst)
316 {
317 std::string types;
318
319 if ( !dst )
320 return "none";
321 if ( (dst & PS_TYPE_ALL) == PS_TYPE_ALL )
322 return "all";
323 if ( dst & PS_TYPE_PORTSCAN )
324 types += "portscan ";
325 if ( dst & PS_TYPE_PORTSWEEP )
326 types += "portsweep ";
327 if ( dst & PS_TYPE_DECOYSCAN )
328 types += "decoy_portscan ";
329 if ( dst & PS_TYPE_DISTPORTSCAN )
330 types += "distributed_portscan ";
331
332 types.pop_back();
333
334 return types;
335 }
336
to_string(const IPSET * list)337 static std::string to_string(const IPSET* list)
338 {
339 SF_LNODE* cursor;
340 std::string ipset;
341
342 for (auto p = (const IP_PORT*)sflist_first(&list->ip_list, &cursor); p;
343 p = (const IP_PORT*)sflist_next(&cursor))
344 {
345 SfIpString ip_str;
346
347 p->ip.get_addr()->ntop(ip_str);
348
349 if ( p->notflag )
350 ipset += "!";
351
352 ipset += std::string(ip_str);
353
354 if ( ((p->ip.get_family() == AF_INET6) and (p->ip.get_bits() != 128)) or
355 ((p->ip.get_family() == AF_INET ) and (p->ip.get_bits() != 32 )) )
356 ipset += "/" + std::to_string(p->ip.get_bits());
357
358 SF_LNODE* pr_cursor;
359 auto pr =(const PORTRANGE*)sflist_first(&p->portset.port_list, &pr_cursor);
360
361 if ( pr and pr->port_lo )
362 ipset += " : ";
363
364 for (; pr; pr = (const PORTRANGE*)sflist_next(&pr_cursor))
365 {
366 if ( pr->port_lo )
367 {
368 ipset += std::to_string(pr->port_lo);
369 if ( pr->port_hi != pr->port_lo )
370 ipset += "-" + std::to_string(pr->port_hi);
371 ipset += " ";
372 }
373 }
374 ipset += ", ";
375 }
376
377 if ( ipset.empty() )
378 return "none";
379
380 ipset.erase(ipset.end() - 2);
381
382 return ipset;
383 }
384
portscan_config_show(const PortscanConfig * config)385 static void portscan_config_show(const PortscanConfig* config)
386 {
387 ConfigLogger::log_value("memcap", static_cast<uint64_t>(config->memcap));
388 ConfigLogger::log_value("protos", get_protos(config->detect_scans).c_str());
389 ConfigLogger::log_value("scan_types", get_types(config->detect_scan_type).c_str());
390
391 if ( config->watch_ip )
392 ConfigLogger::log_list("watch_ip", to_string(config->watch_ip).c_str());
393
394 if ( config->ignore_scanners )
395 ConfigLogger::log_list("ignore_scanners", to_string(config->ignore_scanners).c_str());
396
397 if ( config->ignore_scanned )
398 ConfigLogger::log_list("ignore_scanned", to_string(config->ignore_scanned).c_str());
399
400 ConfigLogger::log_flag("alert_all", config->alert_all);
401 ConfigLogger::log_flag("include_midstream", config->include_midstream);
402
403 ConfigLogger::log_value("tcp_window", config->tcp_window);
404 ConfigLogger::log_value("udp_window", config->udp_window);
405 ConfigLogger::log_value("ip_window", config->ip_window);
406 ConfigLogger::log_value("icmp_window", config->icmp_window);
407 }
408
409 //-------------------------------------------------------------------------
410 // class stuff
411 //-------------------------------------------------------------------------
412
PortScan(PortScanModule * mod)413 PortScan::PortScan(PortScanModule* mod)
414 { config = mod->get_data(); }
415
~PortScan()416 PortScan::~PortScan()
417 {
418 if ( config )
419 delete config;
420 }
421
tinit()422 void PortScan::tinit()
423 { ps_init_hash(config->memcap); }
424
tterm()425 void PortScan::tterm()
426 { ps_cleanup(); }
427
show(const SnortConfig *) const428 void PortScan::show(const SnortConfig*) const
429 {
430 if ( config )
431 portscan_config_show(config);
432 }
433
eval(Packet * p)434 void PortScan::eval(Packet* p)
435 {
436 Profile profile(psPerfStats);
437 assert(p->ptrs.ip_api.is_ip());
438
439 if ( p->packet_flags & PKT_REBUILT_STREAM )
440 return;
441
442 ++spstats.packets;
443 PS_PKT ps_pkt(p);
444
445 ps_detect(&ps_pkt);
446
447 if (ps_pkt.scanner and ps_pkt.scanner->proto.alerts and
448 (ps_pkt.scanner->proto.alerts != PS_ALERT_GENERATED))
449 {
450 PortscanAlert(&ps_pkt, &ps_pkt.scanner->proto, ps_pkt.proto);
451 }
452
453 if (ps_pkt.scanned and ps_pkt.scanned->proto.alerts and
454 (ps_pkt.scanned->proto.alerts != PS_ALERT_GENERATED))
455 {
456 PortscanAlert(&ps_pkt, &ps_pkt.scanned->proto, ps_pkt.proto);
457 }
458 }
459
460 //-------------------------------------------------------------------------
461 // api stuff
462 //-------------------------------------------------------------------------
463
port_scan_tinit()464 static void port_scan_tinit()
465 { }
466
port_scan_tterm()467 static void port_scan_tterm()
468 { ps_cleanup(); }
469
mod_ctor()470 static Module* mod_ctor()
471 { return new PortScanModule; }
472
mod_dtor(Module * m)473 static void mod_dtor(Module* m)
474 { delete m; }
475
sp_ctor(Module * m)476 static Inspector* sp_ctor(Module* m)
477 { return new PortScan((PortScanModule*)m); }
478
sp_dtor(Inspector * p)479 static void sp_dtor(Inspector* p)
480 { delete p; }
481
sp_reset()482 static void sp_reset()
483 { ps_reset(); }
484
485 static const InspectApi sp_api =
486 {
487 {
488 PT_INSPECTOR,
489 sizeof(InspectApi),
490 INSAPI_VERSION,
491 0,
492 API_RESERVED,
493 API_OPTIONS,
494 PS_NAME,
495 PS_HELP,
496 mod_ctor,
497 mod_dtor
498 },
499 IT_PROBE,
500 PROTO_BIT__ANY_IP,
501 nullptr, // buffers
502 nullptr, // service
503 nullptr, // pinit
504 nullptr, // pterm
505 port_scan_tinit, // tinit
506 port_scan_tterm, // tterm
507 sp_ctor,
508 sp_dtor,
509 nullptr, // ssn
510 sp_reset // FIXIT-L only inspector using this, eliminate?
511 };
512
513 #ifdef BUILDING_SO
514 SO_PUBLIC const BaseApi* snort_plugins[] =
515 #else
516 const BaseApi* nin_port_scan[] =
517 #endif
518 {
519 &sp_api.base,
520 nullptr
521 };
522
523