-
Notifications
You must be signed in to change notification settings - Fork 90
/
start-multiple-alerts-scan.gmp.py
280 lines (227 loc) · 8.02 KB
/
start-multiple-alerts-scan.gmp.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# SPDX-FileCopyrightText: 2018 inovex GmbH
# SPDX-FileCopyrightText: 2019-2021 Greenbone AG
#
# SPDX-License-Identifier: GPL-3.0-or-later
import sys
from argparse import Namespace
from typing import List
from gvm.protocols.gmp import Gmp
def check_args(args):
len_args = len(args.script) - 1
message = """
This script makes an alert scan
It needs two parameters after the script name.
1. <sender_email> -- E-Mail of the sender
2. <receiver_email> -- E-Mail of the receiver
Example:
$ gvm-script --gmp-username name --gmp-password pass \
ssh --hostname <gsm> scripts/start-multiple-alert-scan.gmp.py \
<sender_email> <receiver_email>
"""
if len_args != 2:
print(message)
sys.exit()
# returns a list containing all port_list names
def get_port_list_names(gmp) -> List[str]:
res = gmp.get_port_lists()
port_names_list = [""]
for name in res.findall("port_list/name"):
port_names_list.append(str(name.text))
return port_names_list
def get_scan_config(gmp, debug=False):
# get all configs of the openvas instance
res = gmp.get_scan_configs()
# configurable template
template = "fast"
# match the config abbreviation to accepted config names
config_list = [
"Full and fast",
"Full and fast ultimate",
"Full and very deep",
"Full and very deep ultimate",
"System Discovery",
]
template_abbreviation_mapper = {
"fast": config_list[0],
"fast-ulti": config_list[1],
"deep": config_list[2],
"deep-ulti": config_list[3],
"discovery": config_list[4],
}
config_id = "-"
for conf in res.xpath("config"):
cid = conf.xpath("@id")[0]
name = conf.xpath("name/text()")[0]
# get the config id of the desired template
if template_abbreviation_mapper.get(template, "-") == name:
config_id = cid
if debug:
print(f"{name}: {config_id}")
break
# check for existence of the desired config
if config_id == "-":
print(
f"error: could not recognize template '{template}'\n"
f"valid template names are: {config_list}\n"
)
exit()
return config_id
def get_target(gmp, debug=False):
# find a targetName
targets = gmp.get_targets()
counter = 0
exists = True
# iterate over existing targets and find a vacant targetName
while exists:
exists = False
target_name = f"targetName{str(counter)}"
for target in targets.xpath("target"):
name = target.xpath("name/text()")[0]
if name == target_name:
exists = True
break
counter += 1
if debug:
print(f"target name: {target_name}")
# iterate over existing port lists and find a vacant name
new_port_list_name = "portlistName"
counter = 0
while True:
portlist_name = f"{new_port_list_name}{str(counter)}"
if portlist_name not in get_port_list_names(gmp):
break
counter += 1
# configurable port string
port_string = "T:80-80"
# create port list
portlist = gmp.create_port_list(portlist_name, port_string)
portlist_id = portlist.xpath("@id")[0]
if debug:
print(f"Portlist-name:\t{str(portlist_name)}")
print(f"Portlist-id:\t{str(portlist_id)}")
# configurable hosts
hosts = ["localhost"]
# integrate port list id into create_target
res = gmp.create_target(
name=target_name, hosts=hosts, port_list_id=portlist_id
)
return res.xpath("@id")[0]
def get_alerts(gmp, sender_email, recipient_email, debug=False) -> List[str]:
# configurable alert name
alert_name = recipient_email
# create alert if necessary
alert_object = gmp.get_alerts(filter=f"name={alert_name}")
alert_id = None
alert = alert_object.xpath("alert")
if len(alert) == 0:
gmp.create_alert(
alert_name,
event=gmp.types.AlertEvent.TASK_RUN_STATUS_CHANGED,
event_data={"status": "Done"},
condition=gmp.types.AlertCondition.ALWAYS,
method=gmp.types.AlertMethod.EMAIL,
method_data={
"""Task '$n': $e
After the event $e,
the following condition was met: $c
This email escalation is configured to attach report format '$r'.
Full details and other report formats are available on the scan engine.
$t
Note:
This email was sent to you as a configured security scan escalation.
Please contact your local system administrator if you think you
should not have received it.
""": "message",
"2": "notice",
sender_email: "from_address",
"[OpenVAS-Manager] Task": "subject",
"c402cc3e-b531-11e1-9163-406186ea4fc5": "notice_attach_format",
recipient_email: "to_address",
},
)
alert_object = gmp.get_alerts(filter=f"name={recipient_email}")
alert = alert_object.xpath("alert")
alert_id = alert[0].get("id", "no id found")
else:
alert_id = alert[0].get("id", "no id found")
if debug:
print(f"alert_id: {str(alert_id)}")
# second configurable alert name
alert_name2 = f"{recipient_email}-2"
# create second alert if necessary
alert_object2 = gmp.get_alerts(filter=f"name={alert_name2}")
alert_id2 = None
alert2 = alert_object2.xpath("alert")
if len(alert2) == 0:
gmp.create_alert(
alert_name2,
event=gmp.types.AlertEvent.TASK_RUN_STATUS_CHANGED,
event_data={"status": "Done"},
condition=gmp.types.AlertCondition.ALWAYS,
method=gmp.types.AlertMethod.EMAIL,
method_data={
"""Task '$n': $e
After the event $e,
the following condition was met: $c
This email escalation is configured to attach report format '$r'.
Full details and other report formats are available on the scan engine.
$t
Note:
This email was sent to you as a configured security scan escalation.
Please contact your local system administrator if you think you
should not have received it.
""": "message",
"2": "notice",
sender_email: "from_address",
"[OpenVAS-Manager] Task": "subject",
recipient_email: "to_address",
},
)
alert_object2 = gmp.get_alerts(filter=f"name={recipient_email}")
alert2 = alert_object2.xpath("alert")
alert_id2 = alert2[0].get("id", "no id found")
else:
alert_id2 = alert2[0].get("id", "no id found")
if debug:
print(f"alert_id2: {str(alert_id2)}")
return [alert_id, alert_id2]
def get_scanner(gmp):
res = gmp.get_scanners()
scanner_ids = res.xpath("scanner/@id")
return scanner_ids[1] # default scanner
def create_and_start_task(
gmp, config_id, target_id, scanner_id, alerts, debug=False
):
# Create the task
tasks = gmp.get_tasks(filter="name~ScanDoneMultipleAlert")
task_name = f"ScanDoneMultipleAlert{len(tasks.xpath('tasks/@id'))}"
task_comment = "test comment"
res = gmp.create_task(
name=task_name,
config_id=config_id,
target_id=target_id,
scanner_id=scanner_id,
alert_ids=alerts,
comment=task_comment,
)
# Start the task
task_id = res.xpath("@id")[0]
gmp.start_task(task_id)
print(f"Task started: {task_name}")
if debug:
# Stop the task (for performance reasons)
gmp.stop_task(task_id)
print("Task stopped")
def main(gmp: Gmp, args: Namespace) -> None:
# pylint: disable=undefined-variable
check_args(args)
sender_email = args.script[1]
recipient_email = args.script[2]
config_id = get_scan_config(gmp)
target_id = get_target(gmp)
alerts = get_alerts(gmp, sender_email, recipient_email)
scanner_id = get_scanner(gmp)
create_and_start_task(gmp, config_id, target_id, scanner_id, alerts)
print("\nScript finished\n")
if __name__ == "__gmp__":
main(gmp, args)