forked from SigmaHQ/sigma
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sigmacover.py
160 lines (150 loc) · 5.67 KB
/
sigmacover.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Project: sigmacover.py
Date: 26/09/2021
Author: frack113
Version: 1.1
Description:
get cover of the rules vs backend
Requirements:
python 3.7 min
$ pip install ruyaml
Todo:
- clean code and bug
- better use of subprocess.run
- have idea
"""
import re
import subprocess
import pathlib
import ruyaml
import json
import copy
import platform
import argparse
def get_sigmac(name,conf):
infos = []
if conf == None:
options = ["python","../tools/sigmac","-t",name,"--debug","-rI","-o","dump.txt","../rules"]
else:
options = ["python","../tools/sigmac","-t",name,"-c",conf,"--debug","-rI","-o","dump.txt","../rules"]
if platform.system() == "Windows":
si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
ret = subprocess.run(options,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
startupinfo=si
)
my_regex = "Convertion Sigma input \S+\\\\(\w+\.yml) (\w+)"
else:
ret = subprocess.run(options,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
my_regex = "Convertion Sigma input \S+/(\w+\.yml) (\w+)"
if not ret.returncode == 0:
print (f"error {ret.returncode} in sigmac")
log = pathlib.Path("sigmac.log")
with log.open() as f:
lines = f.readlines()
for line in lines:
if "Convertion Sigma input" in line:
info = re.findall(my_regex,line)[0]
infos.append(info)
log.unlink()
dump = pathlib.Path("dump.txt")
if dump.exists():
dump.unlink()
return infos
def update_dict(my_dict,my_data,backend):
for file,state in my_data:
my_dict[file][backend] = state
#the backend dict command line options
backend_dict = {
"ala": None,
"ala-rule": None,
"arcsight": "../tools/config/elk-winlogbeat.yml",
"arcsight-esm": "../tools/config/elk-winlogbeat.yml",
"carbonblack": "../tools/config/elk-winlogbeat.yml",
"chronicle": "../tools/config/elk-winlogbeat.yml",
"crowdstrike": "../tools/config/elk-winlogbeat.yml",
"csharp" : None,
"devo": "../tools/config/elk-winlogbeat.yml",
"ee-outliers": "../tools/config/winlogbeat-modules-enabled.yml",
"elastalert": "../tools/config/winlogbeat-modules-enabled.yml",
"elastalert-dsl": "../tools/config/winlogbeat-modules-enabled.yml",
"es-dsl": "../tools/config/winlogbeat-modules-enabled.yml",
"es-eql": "../tools/config/winlogbeat-modules-enabled.yml",
"es-qs": "../tools/config/winlogbeat-modules-enabled.yml",
"es-qs-lr": "../tools/config/logrhythm_winevent.yml",
"es-rule": "../tools/config/winlogbeat-modules-enabled.yml",
"es-rule-eql": "../tools/config/winlogbeat-modules-enabled.yml",
"fireeye-helix": "../tools/config/elk-winlogbeat.yml",
"graylog" : None,
"grep" : None,
"humio": "../tools/config/elk-winlogbeat.yml",
"kibana": "../tools/config/winlogbeat-modules-enabled.yml",
"kibana-ndjson": "../tools/config/winlogbeat-modules-enabled.yml",
"lacework" : None,
"limacharlie" : None,
"logiq" : None,
"logpoint" : None,
"mdatp" : None,
"netwitness" : None,
"netwitness-epl" : None,
"opensearch-monitor": "../tools/config/winlogbeat.yml",
"powershell" : None,
"qradar" : None,
"qualys" : None,
"sentinel-rule" : None,
"splunk": "../tools/config/splunk-windows.yml",
"splunkdm": "../tools/config/splunk-windows.yml",
"splunkxml": "../tools/config/splunk-windows.yml",
"sql": "../tools/config/elk-winlogbeat.yml",
"sqlite": "../tools/config/elk-winlogbeat.yml",
"stix": "../tools/config/stix2.0.yml",
"sumologic" : None,
"sumologic-cse" : None,
"sumologic-cse-rule" : None,
"sysmon": "../tools/config/elk-windows.yml",
"uberagent" : None,
"xpack-watcher": "../tools/config/winlogbeat-modules-enabled.yml",
}
print("""
███ ███ ████ █▄┼▄█ ███ ┼┼ ███ ███ █▄█ ███ ███
█▄▄ ┼█┼ █┼▄▄ █┼█┼█ █▄█ ┼┼ █┼┼ █┼█ ███ █▄┼ █▄┼
▄▄█ ▄█▄ █▄▄█ █┼┼┼█ █┼█ ┼┼ ███ █▄█ ┼█┼ █▄▄ █┼█
v1.1 bugfix
please wait during the tests
""")
argparser = argparse.ArgumentParser(description="Check Sigma rules with all backend.")
argparser.add_argument("--target", "-t", choices=["yaml","json"], help="Output target format")
cmdargs = argparser.parse_args()
if cmdargs.target == None:
print("No outpout use -h to see help")
exit()
#init dict of all rules
default_key_test = {key : "NO TEST" for key in backend_dict.keys()}
the_dico ={}
rules = pathlib.Path("../rules").glob("**/*.yml")
for rule in rules:
the_dico[rule.name] = copy.deepcopy(default_key_test)
#Check all the backend
for name,opt in backend_dict.items():
print (f"check backend : {name}")
result = get_sigmac(name,opt)
update_dict(the_dico,result,name)
#Save
if cmdargs.target.lower() == "yaml":
cover = pathlib.Path("sigmacover.yml")
with cover.open("w") as file:
ruyaml.dump(the_dico, file, Dumper=ruyaml.RoundTripDumper)
else:
cover = pathlib.Path("sigmacover.json")
with cover.open("w") as file:
json_dumps_str = json.dumps(the_dico, indent=4)
file.write(json_dumps_str)