1
2
3
4
5
6 import datetime
7 import logging
8 import os.path
9 import re
10 import subprocess
11
12 from lib.cuckoo.common.abstracts import Processing
13 from lib.cuckoo.common.exceptions import CuckooProcessingError
14
15 log = logging.getLogger(__name__)
16
18 """Snort processing module."""
19
20
21 alert_re = re.compile(
22 r"(?P<timestamp>\d{2}/\d{2}/\d{2}-\d{2}:\d{2}:\d{2}\.\d+)\s+"
23 r"\[\*\*\]\s+\[\d+:(?P<sid>\d+):(?P<revision>\d+)\] "
24 r"(?P<message>.+) \[\*\*\]\s+(\[Classification: (?P<classtype>.+)\] )?"
25 r"\[Priority: (?P<priority>\d+)\] \{(?P<protocol>[:a-zA-Z0-9_-]+)\} "
26 r"(?P<src>.+) \-\> (?P<dest>.+)"
27 )
28
30 self.key = "snort"
31
32 results = {
33 "alerts": [],
34 }
35
36 self.snort = self.options.get("snort", "/usr/local/bin/snort")
37 self.config_path = self.options.get("conf", "/etc/snort/snort.conf")
38
39 if not os.path.isfile(self.pcap_path):
40 log.warning("Unable to run Snort as no pcap is available")
41 return results
42
43 if not os.path.isfile(self.snort):
44 raise CuckooProcessingError("Unable to locate Snort binary")
45
46 if not os.path.isfile(self.config_path):
47 raise CuckooProcessingError(
48 "Unable to locate Snort configuration")
49
50 args = [
51 self.snort,
52 "-c", self.config_path,
53 "-A", "console",
54 "-r", self.pcap_path,
55 "-q", "-y",
56 ]
57
58 try:
59 output = subprocess.check_output(args)
60 except subprocess.CalledProcessError as e:
61 raise CuckooProcessingError(
62 "Snort returned an error processing this pcap: %s" % e)
63
64 for line in output.split("\n"):
65 if not line:
66 continue
67
68 x = self.alert_re.match(line)
69 if not x:
70 log.warning("Error matching Snort line: %r", line)
71 continue
72
73 timestamp = datetime.datetime.strptime(
74 x.group("timestamp"), "%m/%d/%y-%H:%M:%S.%f")
75
76 if ":" in x.group("src"):
77 src_ip, src_port = x.group("src").rsplit(":", 1)
78 else:
79 src_ip = x.group("src")
80 src_port = None
81
82 if ":" in x.group("dest"):
83 dst_ip, dst_port = x.group("dest").rsplit(":", 1)
84 else:
85 dst_ip = x.group("dest")
86 dst_port = None
87
88 results["alerts"].append({
89 "timestamp": timestamp,
90 "sid": int(x.group("sid")),
91 "priority": int(x.group("priority")),
92 "revision": int(x.group("revision")),
93 "message": x.group("message"),
94 "src_ip": src_ip,
95 "src_port": int(src_port) if src_port else None,
96 "dst_ip": dst_ip,
97 "dst_port": int(dst_port) if dst_port else None,
98 "protocol": x.group("protocol"),
99 "classtype": x.group("classtype"),
100 })
101
102 return results
103