rosetta-ce 1.6.8__py3-none-any.whl → 1.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rosetta-ce might be problematic. Click here for more details.
- rosetta/constants/systems.py +33 -29
- rosetta/rfaker.py +495 -533
- {rosetta_ce-1.6.8.dist-info → rosetta_ce-1.7.0.dist-info}/METADATA +1 -1
- {rosetta_ce-1.6.8.dist-info → rosetta_ce-1.7.0.dist-info}/RECORD +7 -7
- {rosetta_ce-1.6.8.dist-info → rosetta_ce-1.7.0.dist-info}/WHEEL +1 -1
- {rosetta_ce-1.6.8.dist-info → rosetta_ce-1.7.0.dist-info}/LICENSE +0 -0
- {rosetta_ce-1.6.8.dist-info → rosetta_ce-1.7.0.dist-info}/top_level.txt +0 -0
rosetta/rfaker.py
CHANGED
|
@@ -2,9 +2,10 @@ import random
|
|
|
2
2
|
import requests
|
|
3
3
|
import warnings
|
|
4
4
|
import ipaddress
|
|
5
|
-
import json
|
|
6
5
|
import csv
|
|
7
6
|
import hashlib
|
|
7
|
+
import itertools
|
|
8
|
+
import time
|
|
8
9
|
from enum import Enum
|
|
9
10
|
from functools import reduce
|
|
10
11
|
from faker import Faker
|
|
@@ -180,7 +181,7 @@ class Observables:
|
|
|
180
181
|
warnings.warn(f"No source of a bad ip , generating a random IP.")
|
|
181
182
|
for i in range(count):
|
|
182
183
|
gen_observables.append(faker.ipv4())
|
|
183
|
-
|
|
184
|
+
elif observable_type == ObservableType.IP and known == ObservableKnown.GOOD:
|
|
184
185
|
for source in GOOD_IP_SOURCES:
|
|
185
186
|
try:
|
|
186
187
|
gen_observables = cls._get_observables_from_source(source)[:count]
|
|
@@ -192,7 +193,7 @@ class Observables:
|
|
|
192
193
|
warnings.warn(f"No source of a good ip , generating a random IP.")
|
|
193
194
|
for i in range(count):
|
|
194
195
|
gen_observables.append(faker.ipv4())
|
|
195
|
-
|
|
196
|
+
elif observable_type == ObservableType.URL and known == ObservableKnown.BAD:
|
|
196
197
|
for source in BAD_URL_SOURCES:
|
|
197
198
|
try:
|
|
198
199
|
gen_observables = cls._get_observables_from_source(source)[:count]
|
|
@@ -204,7 +205,7 @@ class Observables:
|
|
|
204
205
|
warnings.warn(f"No source of a bad url , generating a random url.")
|
|
205
206
|
for i in range(count):
|
|
206
207
|
gen_observables.append(faker.url())
|
|
207
|
-
|
|
208
|
+
elif observable_type == ObservableType.URL and known == ObservableKnown.GOOD:
|
|
208
209
|
for source in GOOD_URL_SOURCES:
|
|
209
210
|
try:
|
|
210
211
|
gen_observables = cls._get_observables_from_source(source)[:count]
|
|
@@ -216,7 +217,7 @@ class Observables:
|
|
|
216
217
|
warnings.warn(f"No source of a good url , generating a random url.")
|
|
217
218
|
for i in range(count):
|
|
218
219
|
gen_observables.append(faker.url())
|
|
219
|
-
|
|
220
|
+
elif observable_type == ObservableType.SHA256 and known == ObservableKnown.BAD:
|
|
220
221
|
for source in BAD_SHA256_SOURCES:
|
|
221
222
|
try:
|
|
222
223
|
gen_observables = cls._get_observables_from_source(source)[:count]
|
|
@@ -229,7 +230,7 @@ class Observables:
|
|
|
229
230
|
for i in range(count):
|
|
230
231
|
random_string = faker.text(max_nb_chars=50)
|
|
231
232
|
gen_observables.append(hashlib.sha256(random_string.encode()).hexdigest())
|
|
232
|
-
|
|
233
|
+
elif observable_type == ObservableType.SHA256 and known == ObservableKnown.GOOD:
|
|
233
234
|
for source in GOOD_SHA256_SOURCES:
|
|
234
235
|
try:
|
|
235
236
|
gen_observables = cls._get_observables_from_source(source)[:count]
|
|
@@ -242,7 +243,7 @@ class Observables:
|
|
|
242
243
|
for i in range(count):
|
|
243
244
|
random_string = faker.text(max_nb_chars=50)
|
|
244
245
|
gen_observables.append(hashlib.sha256(random_string.encode()).hexdigest())
|
|
245
|
-
|
|
246
|
+
elif observable_type == ObservableType.CVE:
|
|
246
247
|
for source in CVE_SOURCES:
|
|
247
248
|
try:
|
|
248
249
|
gen_observables = cls._get_observables_from_source(source)[:count]
|
|
@@ -255,7 +256,7 @@ class Observables:
|
|
|
255
256
|
for i in range(count):
|
|
256
257
|
fake_cve = "CVE-" + faker.numerify(text="####-####")
|
|
257
258
|
gen_observables.append(fake_cve)
|
|
258
|
-
|
|
259
|
+
elif observable_type == ObservableType.TERMS:
|
|
259
260
|
for source in TERMS_SOURCES:
|
|
260
261
|
try:
|
|
261
262
|
gen_observables = cls._get_observables_from_source(source)[:count]
|
|
@@ -272,612 +273,573 @@ class Observables:
|
|
|
272
273
|
|
|
273
274
|
class Events:
|
|
274
275
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
"""
|
|
278
|
-
Returns:
|
|
279
|
-
Faker instance.
|
|
280
|
-
"""
|
|
281
|
-
return Faker()
|
|
276
|
+
faker = Faker()
|
|
277
|
+
field_timings = {}
|
|
282
278
|
|
|
283
279
|
@staticmethod
|
|
284
|
-
def
|
|
285
|
-
"""
|
|
286
|
-
Returns:
|
|
287
|
-
Faker instance.
|
|
288
|
-
"""
|
|
289
|
-
return Observables()
|
|
290
|
-
|
|
291
|
-
@classmethod
|
|
292
|
-
def set_field(cls, field, observables: Optional[Observables] = None):
|
|
280
|
+
def _set_field(field):
|
|
293
281
|
"""
|
|
294
282
|
Returns:
|
|
295
283
|
Field value.
|
|
296
284
|
"""
|
|
297
|
-
field_value = None
|
|
298
|
-
faker = cls._create_faker()
|
|
299
|
-
if field == "pid":
|
|
300
|
-
field_value = faker.random_int(min=1000, max=65535)
|
|
301
|
-
if field == "src_host":
|
|
302
|
-
field_value = random.choice(observables.src_host) if observables and observables.src_host \
|
|
303
|
-
else faker.hostname()
|
|
304
|
-
if field == "dst_host":
|
|
305
|
-
field_value = random.choice(observables.dst_host) if observables and observables.dst_host \
|
|
306
|
-
else faker.hostname()
|
|
307
|
-
if field == "user":
|
|
308
|
-
field_value = random.choice(observables.user) if observables and observables.user \
|
|
309
|
-
else faker.user_name()
|
|
310
|
-
if field == "unix_process":
|
|
311
|
-
field_value = random.choice(observables.unix_process) if observables and observables.unix_process \
|
|
312
|
-
else "sudo"
|
|
313
|
-
if field == "unix_child_process":
|
|
314
|
-
field_value = random.choice(observables.unix_child_process) if observables and \
|
|
315
|
-
observables.unix_child_process else "sudo"
|
|
316
|
-
if field == "unix_cmd":
|
|
317
|
-
field_value = random.choice(observables.unix_cmd) if observables and observables.unix_cmd \
|
|
318
|
-
else random.choice(UNIX_CMD)
|
|
319
|
-
if field == "technique":
|
|
320
|
-
field_value = random.choice(observables.technique) if observables and observables.technique \
|
|
321
|
-
else random.choice(ATTACK_TECHNIQUES)
|
|
322
|
-
if field == "severity":
|
|
323
|
-
field_value = random.choice(observables.severity) if observables and observables.severity \
|
|
324
|
-
else random.choice(SEVERITIES)
|
|
325
|
-
if field == "local_ip":
|
|
326
|
-
field_value = random.choice(observables.local_ip) if observables and observables.local_ip \
|
|
327
|
-
else faker.ipv4()
|
|
328
|
-
if field == "local_port":
|
|
329
|
-
field_value = faker.random_int(min=1024, max=65535)
|
|
330
|
-
if field == "remote_ip":
|
|
331
|
-
field_value = random.choice(observables.remote_ip) if observables and observables.remote_ip \
|
|
332
|
-
else Observables.generator(observable_type=ObservableType.IP, known=ObservableKnown.BAD, count=1)[0]
|
|
333
|
-
if field == "local_ip_v6":
|
|
334
|
-
field_value = random.choice(observables.local_ip_v6) if observables and observables.local_ip_v6 \
|
|
335
|
-
else faker.ipv6()
|
|
336
|
-
if field == "remote_ip_v6":
|
|
337
|
-
field_value = random.choice(observables.remote_ip_v6) if observables and observables.remote_ip_v6 \
|
|
338
|
-
else faker.ipv6()
|
|
339
|
-
if field == "remote_port":
|
|
340
|
-
field_value = random.choice(observables.remote_port) if observables and observables.remote_port \
|
|
341
|
-
else faker.random_int(min=1024, max=65535)
|
|
342
|
-
if field == "dst_url":
|
|
343
|
-
field_value = random.choice(observables.url) if observables and observables.url \
|
|
344
|
-
else Observables.generator(observable_type=ObservableType.URL, known=ObservableKnown.BAD, count=1)
|
|
345
|
-
if field == "inbound_bytes":
|
|
346
|
-
field_value = random.choice(observables.inbound_bytes) if observables and observables.inbound_bytes \
|
|
347
|
-
else faker.random_int(min=10, max=1073741824)
|
|
348
|
-
if field == "outbound_bytes":
|
|
349
|
-
field_value = random.choice(observables.outbound_bytes) if observables and observables.outbound_bytes \
|
|
350
|
-
else faker.random_int(min=10, max=1073741824)
|
|
351
|
-
if field == "app":
|
|
352
|
-
field_value = random.choice(observables.app) if observables and observables.app \
|
|
353
|
-
else faker.sentence(nb_words=2)
|
|
354
|
-
if field == "os":
|
|
355
|
-
field_value = random.choice(observables.os) if observables and observables.os \
|
|
356
|
-
else random.choice(OS_LIST)
|
|
357
|
-
if field == "protocol":
|
|
358
|
-
field_value = random.choice(observables.protocol) if observables and observables.protocol \
|
|
359
|
-
else random.choice(PROTOCOLS)
|
|
360
|
-
if field == "rule_id":
|
|
361
|
-
field_value = random.choice(observables.event_id) if observables and observables.event_id \
|
|
362
|
-
else faker.random_int(min=1, max=200)
|
|
363
|
-
if field == "action":
|
|
364
|
-
field_value = random.choice(observables.action) if observables and observables.action \
|
|
365
|
-
else random.choice(ACTIONS)
|
|
366
|
-
if field == "src_domain":
|
|
367
|
-
field_value = random.choice(observables.src_domain) if observables and observables.src_domain \
|
|
368
|
-
else faker.domain_name()
|
|
369
|
-
if field == "dst_domain":
|
|
370
|
-
field_value = random.choice(observables.dst_domain) if observables and observables.dst_domain \
|
|
371
|
-
else faker.domain_name()
|
|
372
|
-
if field == "sender_email":
|
|
373
|
-
field_value = random.choice(observables.sender_email) if observables and observables.sender_email \
|
|
374
|
-
else faker.email()
|
|
375
|
-
if field == "recipient_email":
|
|
376
|
-
field_value = random.choice(observables.recipient_email) if observables and observables.recipient_email \
|
|
377
|
-
else faker.email()
|
|
378
|
-
if field == "email_subject":
|
|
379
|
-
field_value = random.choice(observables.email_subject) if observables and observables.email_subject \
|
|
380
|
-
else faker.sentence(nb_words=6)
|
|
381
|
-
if field == "email_body":
|
|
382
|
-
field_value = random.choice(observables.email_body) if observables and observables.email_body else \
|
|
383
|
-
faker.sentence(nb_words=50)
|
|
384
|
-
if field == "attachment_hash":
|
|
385
|
-
field_value = random.choice(observables.file_hash) if observables and observables.file_hash \
|
|
386
|
-
else Observables.generator(observable_type=ObservableType.SHA256, known=ObservableKnown.BAD,
|
|
387
|
-
count=1)
|
|
388
|
-
if field == "spam_score":
|
|
389
|
-
field_value = faker.random_int(min=1, max=5)
|
|
390
|
-
if field == "method":
|
|
391
|
-
field_value = random.choice(observables.technique).get('mechanism') if observables and \
|
|
392
|
-
observables.technique else random.choice(TECHNIQUES).get('mechanism')
|
|
393
|
-
if field == "url":
|
|
394
|
-
field_value = random.choice(observables.technique).get('indicator') if observables and \
|
|
395
|
-
observables.technique else random.choice(TECHNIQUES).get('indicator')
|
|
396
|
-
if field == "user_agent":
|
|
397
|
-
field_value = faker.user_agent()
|
|
398
|
-
if field == "referer":
|
|
399
|
-
field_value = random.choice(observables.url) if observables and observables.url \
|
|
400
|
-
else Observables.generator(observable_type=ObservableType.URL, known=ObservableKnown.BAD, count=1)
|
|
401
|
-
if field == "response_code":
|
|
402
|
-
field_value = random.choice(observables.error_code) if observables and observables.error_code \
|
|
403
|
-
else random.choice(ERROR_CODE)
|
|
404
|
-
if field == "response_size":
|
|
405
|
-
field_value = faker.random_int(min=100, max=10000)
|
|
406
|
-
if field == "attack_type":
|
|
407
|
-
field_value = random.choice(observables.technique).get('technique') if observables and \
|
|
408
|
-
observables.technique else random.choice(TECHNIQUES).get('technique')
|
|
409
|
-
if field == "cookies":
|
|
410
|
-
field_value = f"{faker.word()}={faker.uuid4()}"
|
|
411
|
-
if field == "guid":
|
|
412
|
-
field_value = faker.uuid4()
|
|
413
|
-
if field == "transmitted_services":
|
|
414
|
-
field_value = faker.sentence(nb_words=5)
|
|
415
|
-
if field == "process_id":
|
|
416
|
-
field_value = faker.random_int()
|
|
417
|
-
if field == "new_process_id":
|
|
418
|
-
field_value = faker.random_int()
|
|
419
|
-
if field == "thread_id":
|
|
420
|
-
field_value = faker.random_int()
|
|
421
|
-
if field == "target_pid":
|
|
422
|
-
field_value = faker.random_int()
|
|
423
|
-
if field == "subject_login_id":
|
|
424
|
-
field_value = faker.random_int()
|
|
425
|
-
if field == "win_user_id":
|
|
426
|
-
field_value = "S-1-" + str(faker.random_int())
|
|
427
|
-
if field == "destination_login_id":
|
|
428
|
-
field_value = faker.random_int()
|
|
429
|
-
if field == "privilege_list":
|
|
430
|
-
field_value = faker.sentence(nb_words=5)
|
|
431
|
-
if field == "event_record_id":
|
|
432
|
-
field_value = random.choice(observables.event_id) if observables and observables.event_id \
|
|
433
|
-
else faker.random.randint(1, 999)
|
|
434
|
-
if field == "win_process":
|
|
435
|
-
field_value = random.choice(observables.win_process) if observables and observables.win_process \
|
|
436
|
-
else random.choice(WIN_PROCESSES)
|
|
437
|
-
if field == "win_cmd":
|
|
438
|
-
field_value = random.choice(observables.win_cmd) if observables and observables.win_cmd \
|
|
439
|
-
else random.choice(WINDOWS_CMD)
|
|
440
|
-
if field == "win_child_process":
|
|
441
|
-
field_value = random.choice(observables.win_child_process) if \
|
|
442
|
-
observables and observables.win_child_process else random.choice(WIN_PROCESSES)
|
|
443
|
-
if field == "source_network_address":
|
|
444
|
-
field_value = random.choice(observables.local_ip) if observables and observables.local_ip \
|
|
445
|
-
else faker.ipv4_private()
|
|
446
|
-
if field == "file_name":
|
|
447
|
-
field_value = random.choice(observables.file_name) if observables and observables.file_name \
|
|
448
|
-
else faker.file_name()
|
|
449
|
-
if field == "cve":
|
|
450
|
-
field_value = random.choice(observables.cve) if observables and observables.cve \
|
|
451
|
-
else Observables.generator(observable_type=ObservableType.CVE, count=1)
|
|
452
|
-
if field == "file_hash":
|
|
453
|
-
field_value = random.choice(observables.file_hash) if observables and observables.file_hash \
|
|
454
|
-
else Observables.generator(observable_type=ObservableType.SHA256, known=ObservableKnown.BAD,
|
|
455
|
-
count=1)
|
|
456
|
-
if field == "incident_types":
|
|
457
|
-
field_value = random.choice(observables.incident_types) if observables and observables.incident_types \
|
|
458
|
-
else INCIDENTS_TYPES
|
|
459
|
-
if field == "analysts":
|
|
460
|
-
field_value = random.choice(observables.analysts) if observables and observables.analysts \
|
|
461
|
-
else [faker.unique.first_name() for _ in range(10)]
|
|
462
|
-
if field == "duration":
|
|
463
|
-
field_value = random.randint(1, 5)
|
|
464
|
-
if field == "log_id":
|
|
465
|
-
field_value = faker.uuid4()
|
|
466
|
-
if field == "alert_name":
|
|
467
|
-
field_value = random.choice(observables.alert_name) if observables and observables.alert_name \
|
|
468
|
-
else faker.sentence(nb_words=4)
|
|
469
|
-
if field == "query_type":
|
|
470
|
-
field_value = random.choice(observables.query_type) if \
|
|
471
|
-
observables and observables.query_type else random.choice(QUERY_TYPE)
|
|
472
|
-
if field == "database_name":
|
|
473
|
-
field_value = random.choice(observables.database_name) if \
|
|
474
|
-
observables and observables.database_name else random.choice(DATABASE_NAME)
|
|
475
|
-
if field == "query":
|
|
476
|
-
field_value = random.choice(observables.query) if \
|
|
477
|
-
observables and observables.query else random.choice(QUERY)
|
|
478
|
-
return field_value
|
|
479
285
|
|
|
286
|
+
faker = Events.faker
|
|
287
|
+
|
|
288
|
+
# Define default generators for each field
|
|
289
|
+
default_generators = {
|
|
290
|
+
"pid": lambda: faker.random_int(min=1000, max=65535),
|
|
291
|
+
"src_host": faker.hostname,
|
|
292
|
+
"dst_host": faker.hostname,
|
|
293
|
+
"user": faker.user_name,
|
|
294
|
+
"unix_process": lambda: "sudo",
|
|
295
|
+
"unix_child_process": lambda: "sudo",
|
|
296
|
+
"unix_cmd": lambda: random.choice(UNIX_CMD),
|
|
297
|
+
"technique": lambda: random.choice(ATTACK_TECHNIQUES),
|
|
298
|
+
"entry_type": lambda: faker.sentence(nb_words=2),
|
|
299
|
+
"sensor": lambda: faker.sentence(nb_words=1),
|
|
300
|
+
"event_id": lambda: faker.random_int(min=10, max=1073741824),
|
|
301
|
+
"error_code": lambda: faker.random_int(min=1000, max=5000),
|
|
302
|
+
"terms": lambda: faker.sentence(nb_words=10),
|
|
303
|
+
"alert_types": lambda: faker.sentence(nb_words=1),
|
|
304
|
+
"action_status": lambda: random.choice(ACTIONS),
|
|
305
|
+
"severity": lambda: random.choice(SEVERITIES),
|
|
306
|
+
"local_ip": faker.ipv4,
|
|
307
|
+
"local_port": lambda: faker.random_int(min=1024, max=65535),
|
|
308
|
+
"remote_ip": lambda: Observables.generator(
|
|
309
|
+
observable_type=ObservableType.IP,
|
|
310
|
+
known=ObservableKnown.BAD,
|
|
311
|
+
count=1
|
|
312
|
+
)[0],
|
|
313
|
+
"local_ip_v6": faker.ipv6,
|
|
314
|
+
"remote_ip_v6": faker.ipv6,
|
|
315
|
+
"remote_port": lambda: faker.random_int(min=1024, max=65535),
|
|
316
|
+
"dst_url": lambda: Observables.generator(
|
|
317
|
+
observable_type=ObservableType.URL,
|
|
318
|
+
known=ObservableKnown.BAD,
|
|
319
|
+
count=1
|
|
320
|
+
)[0],
|
|
321
|
+
"inbound_bytes": lambda: faker.random_int(min=10, max=1073741824),
|
|
322
|
+
"outbound_bytes": lambda: faker.random_int(min=10, max=1073741824),
|
|
323
|
+
"app": lambda: faker.sentence(nb_words=2),
|
|
324
|
+
"os": lambda: random.choice(OS_LIST),
|
|
325
|
+
"protocol": lambda: random.choice(PROTOCOLS),
|
|
326
|
+
"rule_id": lambda: faker.random_int(min=1, max=200),
|
|
327
|
+
"action": lambda: random.choice(ACTIONS),
|
|
328
|
+
"src_domain": faker.domain_name,
|
|
329
|
+
"dst_domain": faker.domain_name,
|
|
330
|
+
"sender_email": faker.email,
|
|
331
|
+
"recipient_email": faker.email,
|
|
332
|
+
"email_subject": lambda: faker.sentence(nb_words=6),
|
|
333
|
+
"email_body": lambda: faker.sentence(nb_words=50),
|
|
334
|
+
"attachment_hash": lambda: Observables.generator(
|
|
335
|
+
observable_type=ObservableType.SHA256,
|
|
336
|
+
known=ObservableKnown.BAD,
|
|
337
|
+
count=1
|
|
338
|
+
)[0],
|
|
339
|
+
"spam_score": lambda: faker.random_int(min=1, max=5),
|
|
340
|
+
"method": lambda: random.choice(TECHNIQUES).get('mechanism'),
|
|
341
|
+
"url": lambda: random.choice(TECHNIQUES).get('indicator'),
|
|
342
|
+
"user_agent": faker.user_agent,
|
|
343
|
+
"referer": lambda: Observables.generator(
|
|
344
|
+
observable_type=ObservableType.URL,
|
|
345
|
+
known=ObservableKnown.BAD,
|
|
346
|
+
count=1
|
|
347
|
+
)[0],
|
|
348
|
+
"response_code": lambda: random.choice(ERROR_CODE),
|
|
349
|
+
"response_size": lambda: faker.random_int(min=100, max=10000),
|
|
350
|
+
"attack_type": lambda: random.choice(TECHNIQUES).get('technique'),
|
|
351
|
+
"cookies": lambda: f"{faker.word()}={faker.uuid4()}",
|
|
352
|
+
"guid": faker.uuid4,
|
|
353
|
+
"transmitted_services": lambda: faker.sentence(nb_words=5),
|
|
354
|
+
"process_id": faker.random_int,
|
|
355
|
+
"new_process_id": faker.random_int,
|
|
356
|
+
"thread_id": faker.random_int,
|
|
357
|
+
"target_pid": faker.random_int,
|
|
358
|
+
"subject_login_id": faker.random_int,
|
|
359
|
+
"win_user_id": lambda: "S-1-" + str(faker.random_int()),
|
|
360
|
+
"destination_login_id": faker.random_int,
|
|
361
|
+
"privilege_list": lambda: faker.sentence(nb_words=5),
|
|
362
|
+
"event_record_id": lambda: faker.random_int(min=1, max=999),
|
|
363
|
+
"win_process": lambda: random.choice(WIN_PROCESSES),
|
|
364
|
+
"win_cmd": lambda: random.choice(WINDOWS_CMD),
|
|
365
|
+
"win_child_process": lambda: random.choice(WIN_PROCESSES),
|
|
366
|
+
"source_network_address": faker.ipv4_private,
|
|
367
|
+
"file_name": faker.file_name,
|
|
368
|
+
"cve": lambda: Observables.generator(
|
|
369
|
+
observable_type=ObservableType.CVE,
|
|
370
|
+
count=1
|
|
371
|
+
)[0],
|
|
372
|
+
"file_hash": lambda: Observables.generator(
|
|
373
|
+
observable_type=ObservableType.SHA256,
|
|
374
|
+
known=ObservableKnown.BAD,
|
|
375
|
+
count=1
|
|
376
|
+
)[0],
|
|
377
|
+
"incident_types": lambda: random.choice(INCIDENTS_TYPES),
|
|
378
|
+
"analysts": lambda: [faker.unique.first_name() for _ in range(10)],
|
|
379
|
+
"duration": lambda: random.randint(1, 5),
|
|
380
|
+
"log_id": faker.uuid4,
|
|
381
|
+
"alert_name": lambda: faker.sentence(nb_words=4),
|
|
382
|
+
"query_type": lambda: random.choice(QUERY_TYPE),
|
|
383
|
+
"database_name": lambda: random.choice(DATABASE_NAME),
|
|
384
|
+
"query": lambda: random.choice(QUERY),
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
if field in default_generators:
|
|
388
|
+
generator = default_generators[field]
|
|
389
|
+
field_value = generator() if callable(generator) else generator()
|
|
390
|
+
else:
|
|
391
|
+
field_value = faker.word()
|
|
392
|
+
|
|
393
|
+
return field_value
|
|
394
|
+
|
|
480
395
|
@classmethod
|
|
481
|
-
def syslog(
|
|
482
|
-
|
|
396
|
+
def syslog(
|
|
397
|
+
cls,
|
|
398
|
+
count: int,
|
|
399
|
+
datetime_iso: Optional[datetime] = None,
|
|
400
|
+
observables: Optional['Observables'] = None,
|
|
401
|
+
required_fields: Optional[str] = None
|
|
402
|
+
) -> List[str]:
|
|
483
403
|
"""
|
|
484
|
-
Generate fake syslog messages.
|
|
485
|
-
|
|
486
|
-
Args:
|
|
487
|
-
count: The number of syslog messages to generate.
|
|
488
|
-
datetime_iso: Optional. The starting datetime_iso for the syslog messages. If not provided, a random time during
|
|
489
|
-
the past hour from now will be used.
|
|
490
|
-
observables: Optional. An observables object. If not provided, random objservable will be generated
|
|
491
|
-
and used.
|
|
492
|
-
required_fields: Optional. A list of fields that are required to present in the generated data, whether from
|
|
493
|
-
observables or randomely.
|
|
494
|
-
Returns:
|
|
495
|
-
A list of syslog messages.
|
|
496
|
-
|
|
497
|
-
Examples:
|
|
498
|
-
>>> Events.syslog(5)
|
|
499
|
-
['Jan 01 05:32:48 myhostname sudo[1023]: username : COMMAND ; cat /etc/shadow',
|
|
500
|
-
'Jan 01 05:17:59 myhostname sudo[2019]: username : COMMAND ; find / -name \'*.log\' -exec rm -f {} \\;',
|
|
501
|
-
'Jan 01 05:46:16 myhostname sudo[3132]: username : COMMAND ; dd if=/dev/zero of=/dev/sda',
|
|
502
|
-
'Jan 01 05:08:08 myhostname sudo[4111]: username : COMMAND ; chmod -R 777 /',
|
|
503
|
-
'Jan 01 05:59:41 myhostname sudo[5195]: username : COMMAND ; chown -R nobody:nogroup /']
|
|
504
|
-
|
|
404
|
+
Generate fake syslog messages with optimizations for efficiency.
|
|
505
405
|
"""
|
|
506
406
|
syslog_messages = []
|
|
507
|
-
faker =
|
|
407
|
+
faker = Events.faker
|
|
408
|
+
|
|
409
|
+
# Predefine default datetime if not provided
|
|
508
410
|
if datetime_iso is None:
|
|
509
411
|
datetime_iso = datetime.now() - timedelta(hours=1)
|
|
510
412
|
datetime_iso += timedelta(seconds=faker.random_int(min=0, max=3599))
|
|
511
|
-
|
|
512
|
-
|
|
413
|
+
|
|
414
|
+
# Set default required fields
|
|
415
|
+
required_fields_list = required_fields.split(",") if required_fields else [
|
|
416
|
+
"pid", "host", "user", "unix_process", "unix_cmd"
|
|
417
|
+
]
|
|
418
|
+
|
|
419
|
+
# Precompute static values for required fields
|
|
420
|
+
common_fields = {}
|
|
421
|
+
for field in required_fields_list:
|
|
422
|
+
value = None
|
|
423
|
+
if observables and hasattr(observables, field):
|
|
424
|
+
obs_value = getattr(observables, field)
|
|
425
|
+
if obs_value:
|
|
426
|
+
if isinstance(obs_value, list):
|
|
427
|
+
value = random.choice(obs_value)
|
|
428
|
+
else:
|
|
429
|
+
value = obs_value
|
|
430
|
+
if value is None:
|
|
431
|
+
value = Events._set_field(field)
|
|
432
|
+
common_fields[field] = value
|
|
433
|
+
|
|
434
|
+
# Preprocess observables
|
|
435
|
+
extra_fields = []
|
|
436
|
+
if observables:
|
|
437
|
+
observables_dict = vars(observables)
|
|
438
|
+
for key, value in observables_dict.items():
|
|
439
|
+
if value and key not in required_fields_list:
|
|
440
|
+
if isinstance(value, list):
|
|
441
|
+
val = random.choice(value)
|
|
442
|
+
else:
|
|
443
|
+
val = value
|
|
444
|
+
extra_fields.append(str(val))
|
|
445
|
+
|
|
446
|
+
# Generate all syslog messages
|
|
513
447
|
for i in range(count):
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
for field in required_fields.split(","):
|
|
517
|
-
syslog_message += f" {cls.set_field(field, observables)}"
|
|
518
|
-
if observables:
|
|
519
|
-
for observable, observable_value in vars(observables).items():
|
|
520
|
-
if observable_value and observable not in required_fields.split(","):
|
|
521
|
-
syslog_message += f" {random.choice(observable_value)}"
|
|
522
|
-
syslog_messages.append(syslog_message)
|
|
523
|
-
return syslog_messages
|
|
448
|
+
# Update datetime for each log
|
|
449
|
+
current_time = (datetime_iso + timedelta(seconds=i + 1)).strftime('%b %d %H:%M:%S')
|
|
524
450
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
version: Optional[str] = None, datetime_iso: Optional[datetime] = None,
|
|
528
|
-
observables: Optional[Observables] = None, required_fields: Optional[str] = None) -> List[str]:
|
|
529
|
-
"""
|
|
530
|
-
Generates fake CEF (Common Event Format) messages.
|
|
451
|
+
# Build the syslog message efficiently
|
|
452
|
+
syslog_message_parts = [f"{current_time}"]
|
|
531
453
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
datetime_iso: Optional. The starting datetime_iso for the syslog messages. If not provided, a random time during.
|
|
535
|
-
vendor: Optional. The vendor.
|
|
536
|
-
product: Optional. The product value options include:
|
|
537
|
-
- Firewall
|
|
538
|
-
- EmailGW
|
|
539
|
-
version: Optional. The version.
|
|
540
|
-
observables: Optional. An observables object. If not provided, random objservable will be generated
|
|
541
|
-
and used.
|
|
542
|
-
required_fields: Optional. A list of fields that are required to present in the generated data, whether from
|
|
543
|
-
observables or randomely.
|
|
544
|
-
Returns:
|
|
545
|
-
A list of fake CEF messages in string format.
|
|
454
|
+
# Insert required fields
|
|
455
|
+
syslog_message_parts.extend(str(common_fields[field]) for field in required_fields_list)
|
|
546
456
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
457
|
+
# Append additional observables not in required fields
|
|
458
|
+
syslog_message_parts.extend(extra_fields)
|
|
459
|
+
|
|
460
|
+
syslog_messages.append(" ".join(syslog_message_parts))
|
|
461
|
+
|
|
462
|
+
return syslog_messages
|
|
463
|
+
|
|
464
|
+
@classmethod
|
|
465
|
+
def cef(
|
|
466
|
+
cls,
|
|
467
|
+
count: int,
|
|
468
|
+
vendor: Optional[str] = None,
|
|
469
|
+
product: Optional[str] = None,
|
|
470
|
+
version: Optional[str] = None,
|
|
471
|
+
datetime_iso: Optional[datetime] = None,
|
|
472
|
+
observables: Optional['Observables'] = None,
|
|
473
|
+
required_fields: Optional[str] = None
|
|
474
|
+
) -> List[str]:
|
|
562
475
|
cef_messages = []
|
|
563
|
-
faker =
|
|
476
|
+
faker = Events.faker
|
|
564
477
|
vendor = vendor or faker.company()
|
|
478
|
+
product = product or faker.word()
|
|
565
479
|
version = version or faker.numerify("1.0.#")
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
480
|
+
datetime_iso = datetime_iso or datetime.now() - timedelta(hours=1)
|
|
481
|
+
required_fields_list = required_fields.split(",") if required_fields else [
|
|
482
|
+
"local_ip", "local_port", "remote_ip", "remote_port", "protocol", "rule_id", "action"
|
|
483
|
+
]
|
|
484
|
+
|
|
485
|
+
common_fields = {}
|
|
486
|
+
for field in required_fields_list:
|
|
487
|
+
value = None
|
|
488
|
+
if observables and hasattr(observables, field):
|
|
489
|
+
obs_value = getattr(observables, field)
|
|
490
|
+
if obs_value:
|
|
491
|
+
if isinstance(obs_value, list):
|
|
492
|
+
value = random.choice(obs_value)
|
|
493
|
+
else:
|
|
494
|
+
value = obs_value
|
|
495
|
+
if value is None:
|
|
496
|
+
value = Events._set_field(field)
|
|
497
|
+
common_fields[field] = value
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
# Preprocess observables
|
|
501
|
+
extra_fields_str = ""
|
|
502
|
+
if observables:
|
|
503
|
+
observables_dict = vars(observables)
|
|
504
|
+
extra_fields = [
|
|
505
|
+
f"{key}={random.choice(value)}"
|
|
506
|
+
for key, value in observables_dict.items()
|
|
507
|
+
if value and key not in required_fields_list
|
|
508
|
+
]
|
|
509
|
+
if extra_fields:
|
|
510
|
+
extra_fields_str = " " + " ".join(extra_fields)
|
|
511
|
+
|
|
512
|
+
# Pre-compile the CEF message template
|
|
513
|
+
cef_template = (
|
|
514
|
+
f"CEF:0|{vendor}|{product}|{version}|{{log_id}}|{{current_datetime}}|{{severity}}|"
|
|
515
|
+
+ " ".join([f"{field}={common_fields[field]}" for field in required_fields_list])
|
|
516
|
+
)
|
|
517
|
+
|
|
518
|
+
# Generate events
|
|
578
519
|
for i in range(count):
|
|
579
|
-
datetime_iso
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
520
|
+
current_datetime = datetime_iso + timedelta(seconds=i)
|
|
521
|
+
log_id = faker.uuid4()
|
|
522
|
+
severity = common_fields.get('severity') or 'low'
|
|
523
|
+
|
|
524
|
+
cef_message = cef_template.format(
|
|
525
|
+
log_id=log_id,
|
|
526
|
+
current_datetime=current_datetime.strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
|
|
527
|
+
severity=severity
|
|
528
|
+
)
|
|
529
|
+
cef_message += extra_fields_str
|
|
588
530
|
cef_messages.append(cef_message)
|
|
531
|
+
|
|
589
532
|
return cef_messages
|
|
590
|
-
|
|
533
|
+
|
|
591
534
|
@classmethod
|
|
592
|
-
def leef(
|
|
593
|
-
|
|
594
|
-
|
|
535
|
+
def leef(
|
|
536
|
+
cls,
|
|
537
|
+
count: int,
|
|
538
|
+
datetime_iso: Optional[datetime] = None,
|
|
539
|
+
vendor: Optional[str] = None,
|
|
540
|
+
product: Optional[str] = None,
|
|
541
|
+
version: Optional[str] = None,
|
|
542
|
+
observables: Optional['Observables'] = None,
|
|
543
|
+
required_fields: Optional[str] = None
|
|
544
|
+
) -> List[str]:
|
|
595
545
|
"""
|
|
596
|
-
Generates fake LEEF (Log Event Extended Format) messages.
|
|
597
|
-
|
|
598
|
-
Parameters:
|
|
599
|
-
count (int): The number of LEEF messages to generate.
|
|
600
|
-
datetime_iso: Optional. The starting datetime_iso for the syslog messages. If not provided, a random time during.
|
|
601
|
-
vendor: Optional. The vendor.
|
|
602
|
-
product: Optional. The product.
|
|
603
|
-
version: Optional. The version.
|
|
604
|
-
observables: An observables object. If not provided, random objservable will be generated and used.
|
|
605
|
-
required_fields: Optional. A list of fields that are required to present in the generated data, whether from
|
|
606
|
-
observables or randomely.
|
|
607
|
-
|
|
608
|
-
Returns:
|
|
609
|
-
A list of generated LEEF messages.
|
|
610
|
-
|
|
611
|
-
Example:
|
|
612
|
-
To generate 10 fake LEEF messages:
|
|
613
|
-
```
|
|
614
|
-
>>> messages = Events.leef(count=2)
|
|
615
|
-
>>> print(messages)
|
|
616
|
-
['LEEF:1.0|Leef|Payment Portal|1.0|192.168.0.1|mycomputer|08:00:27:da:2e:2e|08:00:27:da:2e:2f|src=10.0.0.1
|
|
617
|
-
dst=mycomputer spt=60918 dpt=443 request=https://example.com/?q=<script>alert("xss")</script>
|
|
618
|
-
method=GET proto=HTTP/1.1 status=200 request_size=5119 response_size=6472
|
|
619
|
-
user_agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko)
|
|
620
|
-
Chrome/93.0.4577.63 Safari/537.36',
|
|
621
|
-
'LEEF:1.0|Leef|Payment Portal|1.0|192.168.0.1|mycomputer|08:00:27:da:2e:2e|08:00:27:da:2e:2f|src=10.0.0.2
|
|
622
|
-
dst=mycomputer spt=57251 dpt=443 request=https://example.com/admin.php?sessionid=12345 method=POST
|
|
623
|
-
proto=HTTP/1.1 status=404 request_size=1216 response_size=9729 user_agent=Mozilla/5.0
|
|
624
|
-
(Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3']
|
|
546
|
+
Generates optimized fake LEEF (Log Event Extended Format) messages.
|
|
625
547
|
"""
|
|
626
548
|
leef_messages = []
|
|
627
|
-
faker =
|
|
549
|
+
faker = Events.faker
|
|
628
550
|
vendor = vendor or faker.company()
|
|
551
|
+
product = product or faker.word()
|
|
629
552
|
version = version or faker.numerify("1.0.#")
|
|
553
|
+
|
|
554
|
+
# Set starting datetime and default fields if necessary
|
|
555
|
+
datetime_iso = datetime_iso or datetime.now() - timedelta(hours=1)
|
|
556
|
+
required_fields_list = required_fields.split(",") if required_fields else [
|
|
557
|
+
"local_ip", "local_port", "host", "url", "protocol", "response_code", "action"
|
|
558
|
+
]
|
|
559
|
+
|
|
560
|
+
# Precompute event_id and severity
|
|
630
561
|
event_id = faker.random_int(min=101, max=501)
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
562
|
+
severity = Events._set_field("severity")
|
|
563
|
+
|
|
564
|
+
# Precompute common fields
|
|
565
|
+
common_fields = {}
|
|
566
|
+
for field in required_fields_list:
|
|
567
|
+
value = None
|
|
568
|
+
if observables and hasattr(observables, field):
|
|
569
|
+
obs_value = getattr(observables, field)
|
|
570
|
+
if obs_value:
|
|
571
|
+
if isinstance(obs_value, list):
|
|
572
|
+
value = random.choice(obs_value)
|
|
573
|
+
else:
|
|
574
|
+
value = obs_value
|
|
575
|
+
if value is None:
|
|
576
|
+
value = Events._set_field(field)
|
|
577
|
+
common_fields[field] = value
|
|
578
|
+
|
|
579
|
+
# Preprocess extra observables
|
|
580
|
+
extra_fields = []
|
|
581
|
+
if observables:
|
|
582
|
+
observables_dict = vars(observables)
|
|
583
|
+
for key, value in observables_dict.items():
|
|
584
|
+
if value and key not in required_fields_list:
|
|
585
|
+
val = random.choice(value) if isinstance(value, list) else value
|
|
586
|
+
extra_fields.append(f" {key}={val}")
|
|
587
|
+
|
|
588
|
+
# Pre-compile the LEEF message template
|
|
589
|
+
leef_template = (
|
|
590
|
+
f"LEEF:1.0|{vendor}|{product}|{version}|{event_id}|"
|
|
591
|
+
f"severity={severity} devTime={{current_datetime}}"
|
|
592
|
+
+ "".join(f" {field}={common_fields[field]}" for field in required_fields_list)
|
|
593
|
+
+ "".join(extra_fields)
|
|
594
|
+
)
|
|
595
|
+
|
|
596
|
+
# Generate messages
|
|
640
597
|
for i in range(count):
|
|
641
|
-
datetime_iso
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
for field in required_fields.split(","):
|
|
645
|
-
leef_message += f" {field}={cls.set_field(field, observables)}"
|
|
646
|
-
if observables:
|
|
647
|
-
for observable, observable_value in vars(observables).items():
|
|
648
|
-
if observable_value and observable not in required_fields.split(","):
|
|
649
|
-
leef_message += f" {observable}={random.choice(observable_value)}"
|
|
598
|
+
current_datetime = (datetime_iso + timedelta(seconds=i)).strftime('%b %d %H:%M:%S')
|
|
599
|
+
|
|
600
|
+
leef_message = leef_template.format(current_datetime=current_datetime)
|
|
650
601
|
leef_messages.append(leef_message)
|
|
651
|
-
return leef_messages
|
|
652
602
|
|
|
603
|
+
return leef_messages
|
|
604
|
+
|
|
653
605
|
@classmethod
|
|
654
|
-
def winevent(
|
|
655
|
-
|
|
606
|
+
def winevent(
|
|
607
|
+
cls,
|
|
608
|
+
count: int,
|
|
609
|
+
datetime_iso: Optional[datetime] = None,
|
|
610
|
+
observables: Optional['Observables'] = None
|
|
611
|
+
) -> List[str]:
|
|
656
612
|
"""
|
|
657
|
-
Generates fake Windows Event Log messages.
|
|
613
|
+
Generates optimized fake Windows Event Log messages using set_field.
|
|
658
614
|
|
|
659
615
|
Args:
|
|
660
616
|
count (int): The number of fake messages to generate.
|
|
661
|
-
datetime_iso
|
|
662
|
-
observables: An observables object
|
|
617
|
+
datetime_iso (Optional[datetime]): The starting datetime for the messages.
|
|
618
|
+
observables (Optional[Observables]): An observables object with predefined values.
|
|
663
619
|
|
|
664
620
|
Returns:
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
Examples:
|
|
668
|
-
>>> Events.winevent(1)
|
|
669
|
-
['<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">...</Event>', ...]
|
|
621
|
+
List[str]: A list of fake Windows Event Log messages.
|
|
670
622
|
"""
|
|
671
623
|
winevent_messages = []
|
|
672
|
-
faker =
|
|
624
|
+
faker = Events.faker
|
|
625
|
+
|
|
626
|
+
# Set starting datetime if not provided
|
|
673
627
|
if datetime_iso is None:
|
|
674
628
|
datetime_iso = datetime.now() - timedelta(hours=1)
|
|
675
629
|
datetime_iso += timedelta(seconds=faker.random_int(min=0, max=3599))
|
|
630
|
+
|
|
631
|
+
# Define required fields
|
|
632
|
+
required_fields_list = [
|
|
633
|
+
"process_id",
|
|
634
|
+
"new_process_id",
|
|
635
|
+
"thread_id",
|
|
636
|
+
"target_pid",
|
|
637
|
+
"subject_login_id",
|
|
638
|
+
"user_id",
|
|
639
|
+
"destination_login_id",
|
|
640
|
+
"privilege_list",
|
|
641
|
+
"win_process",
|
|
642
|
+
"src_host",
|
|
643
|
+
"user_name",
|
|
644
|
+
"cmd",
|
|
645
|
+
"source_network_address",
|
|
646
|
+
"local_port",
|
|
647
|
+
"transmitted_services",
|
|
648
|
+
"file_name",
|
|
649
|
+
"src_domain"
|
|
650
|
+
]
|
|
651
|
+
|
|
652
|
+
# Precompute common fields using set_field
|
|
653
|
+
common_fields = {}
|
|
654
|
+
for field in required_fields_list:
|
|
655
|
+
value = None
|
|
656
|
+
if observables and hasattr(observables, field):
|
|
657
|
+
obs_value = getattr(observables, field)
|
|
658
|
+
if obs_value:
|
|
659
|
+
value = random.choice(obs_value) if isinstance(obs_value, list) else obs_value
|
|
660
|
+
if value is None:
|
|
661
|
+
value = Events._set_field(field)
|
|
662
|
+
common_fields[field] = value
|
|
663
|
+
|
|
664
|
+
# Preprocess extra observables not in required fields
|
|
665
|
+
extra_fields = {}
|
|
666
|
+
if observables:
|
|
667
|
+
observables_dict = vars(observables)
|
|
668
|
+
for key, value in observables_dict.items():
|
|
669
|
+
if value and key not in required_fields_list:
|
|
670
|
+
val = random.choice(value) if isinstance(value, list) else value
|
|
671
|
+
extra_fields[key] = val
|
|
672
|
+
|
|
673
|
+
# Generate events
|
|
676
674
|
for i in range(count):
|
|
677
|
-
|
|
675
|
+
# Update datetime for each event
|
|
676
|
+
current_datetime = datetime_iso + timedelta(seconds=i + 1)
|
|
677
|
+
system_time = current_datetime.strftime('%Y-%m-%d %H:%M:%S')
|
|
678
|
+
|
|
679
|
+
# Generate per-event fields
|
|
678
680
|
guid = faker.uuid4()
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
user_name = random.choice(observables.user) if observables and observables.user \
|
|
698
|
-
else faker.user_name()
|
|
699
|
-
cmd = random.choice(observables.win_cmd) if observables and observables.win_cmd \
|
|
700
|
-
else random.choice(WINDOWS_CMD)
|
|
701
|
-
source_network_address = random.choice(observables.local_ip) if observables and observables.local_ip \
|
|
702
|
-
else faker.ipv4_private()
|
|
703
|
-
file_name = random.choice(observables.file_name) if observables and observables.file_name \
|
|
704
|
-
else faker.file_name()
|
|
681
|
+
|
|
682
|
+
# Use event_id from observables if available
|
|
683
|
+
event_record_id = None
|
|
684
|
+
if observables and hasattr(observables, 'event_id') and observables.event_id:
|
|
685
|
+
event_record_id = random.choice(observables.event_id)
|
|
686
|
+
else:
|
|
687
|
+
event_record_id = Events._set_field('event_id')
|
|
688
|
+
|
|
689
|
+
# Prepare event fields
|
|
690
|
+
event_fields = {
|
|
691
|
+
'guid': guid,
|
|
692
|
+
'system_time': system_time,
|
|
693
|
+
'event_record_id': event_record_id,
|
|
694
|
+
**common_fields,
|
|
695
|
+
**extra_fields
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
# Select a random event template
|
|
705
699
|
unformatted_event = random.choice(WIN_EVENTS)
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
domain_name=domain_name, subject_login_id=subject_login_id,
|
|
711
|
-
privilege_list=privilege_list, cmd=cmd,
|
|
712
|
-
destination_login_id=destination_login_id,
|
|
713
|
-
source_network_address=source_network_address, local_port=local_port,
|
|
714
|
-
transmitted_services=transmitted_services, file_name=file_name)
|
|
700
|
+
|
|
701
|
+
# Format the event with all fields
|
|
702
|
+
win_event = unformatted_event.format(**event_fields)
|
|
703
|
+
|
|
715
704
|
winevent_messages.append(win_event)
|
|
705
|
+
|
|
716
706
|
return winevent_messages
|
|
717
707
|
|
|
718
708
|
@classmethod
|
|
719
|
-
def json(
|
|
720
|
-
|
|
721
|
-
|
|
709
|
+
def json(
|
|
710
|
+
cls,
|
|
711
|
+
count: int,
|
|
712
|
+
datetime_iso: Optional[datetime] = None,
|
|
713
|
+
vendor: Optional[str] = None,
|
|
714
|
+
product: Optional[str] = None,
|
|
715
|
+
version: Optional[str] = None,
|
|
716
|
+
observables: Optional['Observables'] = None,
|
|
717
|
+
required_fields: Optional[str] = None
|
|
718
|
+
) -> List[dict]:
|
|
722
719
|
"""
|
|
723
|
-
Generate fake JSON messages representing discovered vulnerabilities.
|
|
724
|
-
|
|
725
|
-
Args:
|
|
726
|
-
count (int): The number of JSON messages to generate.
|
|
727
|
-
datetime_iso: Optional. The starting datetime_iso for the syslog messages. If not provided, a random time during.
|
|
728
|
-
vendor: Optional. The vendor.
|
|
729
|
-
product: Optional. The product value options include:
|
|
730
|
-
- VulnScanner
|
|
731
|
-
version: Optional. The version.
|
|
732
|
-
observables: An observables object. If not provided, random objservable will be generated and used.
|
|
733
|
-
required_fields: Optional. A list of fields that are required to present in the generated data, whether from
|
|
734
|
-
observables or randomely.
|
|
735
|
-
Returns:
|
|
736
|
-
List[Dict[str, Union[str, int]]]: A list of dictionaries representing the generated JSON messages.
|
|
737
|
-
|
|
738
|
-
Example:
|
|
739
|
-
>>> fake_messages = json(5)
|
|
740
|
-
>>> len(fake_messages)
|
|
741
|
-
5
|
|
742
|
-
>>> isinstance(fake_messages[0], dict)
|
|
743
|
-
True
|
|
744
|
-
|
|
720
|
+
Generate optimized fake JSON messages representing discovered vulnerabilities.
|
|
745
721
|
"""
|
|
746
722
|
json_messages = []
|
|
747
|
-
faker =
|
|
723
|
+
faker = Events.faker
|
|
724
|
+
|
|
725
|
+
# Precompute vendor, product, and version details
|
|
748
726
|
vendor = vendor or faker.company()
|
|
727
|
+
product = product or "UnknownProduct"
|
|
749
728
|
version = version or faker.numerify("1.0.#")
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
if
|
|
754
|
-
if product == "VulnScanner"
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
729
|
+
|
|
730
|
+
# Set initial datetime and precompute required fields if not provided
|
|
731
|
+
datetime_iso = datetime_iso or datetime.now() - timedelta(hours=1)
|
|
732
|
+
required_fields_list = required_fields.split(",") if required_fields else (
|
|
733
|
+
["cve_id", "host", "file_hash"] if product == "VulnScanner" else ["user", "host"]
|
|
734
|
+
)
|
|
735
|
+
|
|
736
|
+
# Precompute static fields
|
|
737
|
+
severity = Events._set_field("severity")
|
|
738
|
+
common_fields = {}
|
|
739
|
+
for field in required_fields_list:
|
|
740
|
+
value = None
|
|
741
|
+
if observables and hasattr(observables, field):
|
|
742
|
+
obs_value = getattr(observables, field)
|
|
743
|
+
if obs_value:
|
|
744
|
+
if isinstance(obs_value, list):
|
|
745
|
+
value = random.choice(obs_value)
|
|
746
|
+
else:
|
|
747
|
+
value = obs_value
|
|
748
|
+
if value is None:
|
|
749
|
+
value = Events._set_field(field)
|
|
750
|
+
common_fields[field] = value
|
|
751
|
+
|
|
752
|
+
# Preprocess additional observables not in required_fields
|
|
753
|
+
extra_fields = {}
|
|
754
|
+
if observables:
|
|
755
|
+
observables_dict = vars(observables)
|
|
756
|
+
for key, value in observables_dict.items():
|
|
757
|
+
if value and key not in required_fields_list:
|
|
758
|
+
val = random.choice(value) if isinstance(value, list) else value
|
|
759
|
+
extra_fields[key] = val
|
|
760
|
+
|
|
761
|
+
# Loop to generate JSON events
|
|
758
762
|
for i in range(count):
|
|
759
|
-
|
|
763
|
+
# Adjust datetime for each message
|
|
764
|
+
current_datetime = datetime_iso + timedelta(seconds=i)
|
|
765
|
+
|
|
766
|
+
# Initialize event with static fields
|
|
760
767
|
event = {
|
|
761
768
|
'vendor': vendor,
|
|
762
769
|
'product': product,
|
|
763
770
|
'version': version,
|
|
764
|
-
'datetime_iso':
|
|
765
|
-
'severity':
|
|
771
|
+
'datetime_iso': current_datetime.strftime("%Y-%m-%d %H:%M:%S"),
|
|
772
|
+
'severity': severity,
|
|
773
|
+
**common_fields,
|
|
774
|
+
**extra_fields
|
|
766
775
|
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
if observables:
|
|
770
|
-
for observable, observable_value in vars(observables).items():
|
|
771
|
-
if observable_value and observable not in required_fields.split(","):
|
|
772
|
-
event[observable] = random.choice(observable_value)
|
|
776
|
+
|
|
777
|
+
# Append generated event to the list
|
|
773
778
|
json_messages.append(event)
|
|
779
|
+
|
|
774
780
|
return json_messages
|
|
775
781
|
|
|
776
782
|
@classmethod
|
|
777
783
|
def incidents(cls, count, fields: Optional[str] = None, datetime_iso: Optional[datetime] = None,
|
|
778
|
-
|
|
779
|
-
|
|
784
|
+
vendor: Optional[str] = None, product: Optional[str] = None, version: Optional[str] = None,
|
|
785
|
+
observables: Optional[Observables] = None, required_fields: Optional[str] = None) -> List[dict]:
|
|
780
786
|
"""
|
|
781
787
|
Generates a list of fake incident data.
|
|
782
788
|
|
|
783
789
|
Args:
|
|
784
790
|
count (int): The number of incidents to generate.
|
|
785
|
-
fields (str, optional):
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
version: Optional. The version.
|
|
791
|
-
datetime_iso: Optional. The starting datetime_iso for the syslog messages. If not provided, a random time during
|
|
792
|
-
observables: An observables object. If not provided, random objservable will be generated and used.
|
|
793
|
-
required_fields: Optional. A list of fields that are required to present in the generated data, whether from
|
|
794
|
-
observables or randomely.
|
|
791
|
+
fields (str, optional): Comma-separated incident fields to include. If None, all fields are included.
|
|
792
|
+
vendor, product, version (Optional[str]): Details about the event source.
|
|
793
|
+
datetime_iso (Optional[datetime]): Base timestamp for the incidents.
|
|
794
|
+
observables (Optional[Observables]): Optional observables object to provide values.
|
|
795
|
+
required_fields (Optional[str]): Required fields for the events.
|
|
795
796
|
|
|
796
797
|
Returns:
|
|
797
|
-
List[Dict]: A list of incident dictionaries.
|
|
798
|
-
- 'id' (int): A unique identifier for the incident.
|
|
799
|
-
- 'type' (str): The type of incident.
|
|
800
|
-
- 'duration' (int): The duration of the incident in hours.
|
|
801
|
-
- 'analyst' (str): The name of the analyst assigned to the incident.
|
|
802
|
-
- 'severity' (str, optional): The severity of the incident. Only included if 'severity' is specified
|
|
803
|
-
in the 'fields' argument.
|
|
804
|
-
- 'description' (str, optional): A brief description of the incident. Only included if 'description' is
|
|
805
|
-
specified in the 'fields' argument.
|
|
806
|
-
- 'events' (List[Dict], optional): A list of event dictionaries associated with the incident.
|
|
807
|
-
|
|
808
|
-
Example:
|
|
809
|
-
>>> incidents(count=3, fields='id,type,severity')
|
|
810
|
-
[
|
|
811
|
-
{'id': 1, 'type': 'Lateral Movement', 'severity': 'Critical'},
|
|
812
|
-
{'id': 2, 'type': 'Access Violation', 'severity': 'High'},
|
|
813
|
-
{'id': 3, 'type': 'Account Compromised', 'severity': 'Low'}
|
|
814
|
-
]
|
|
798
|
+
List[Dict]: A list of incident dictionaries.
|
|
815
799
|
"""
|
|
816
800
|
incidents = []
|
|
817
|
-
faker =
|
|
801
|
+
faker = Events.faker
|
|
802
|
+
datetime_iso = datetime_iso or datetime.now() - timedelta(hours=1)
|
|
803
|
+
|
|
804
|
+
# Generate analyst list if not provided in observables
|
|
805
|
+
incident_types = observables.incident_types if observables and observables.incident_types else INCIDENTS_TYPES
|
|
806
|
+
analysts = observables.analysts if observables and observables.analysts else [faker.unique.first_name() for _ in range(10)]
|
|
818
807
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
incident_types = observables.incident_types if observables and observables.incident_types \
|
|
822
|
-
else INCIDENTS_TYPES
|
|
823
|
-
analysts = observables.analysts if observables and observables.analysts \
|
|
824
|
-
else [faker.unique.first_name() for _ in range(10)]
|
|
825
|
-
analyst_incident_map = {}
|
|
826
|
-
for analyst in analysts:
|
|
827
|
-
mapped_incident_type = incident_types.pop(0)
|
|
828
|
-
analyst_incident_map[analyst] = mapped_incident_type
|
|
829
|
-
incident_types.append(mapped_incident_type)
|
|
808
|
+
incident_type_cycle = itertools.cycle(incident_types)
|
|
830
809
|
for i in range(count):
|
|
831
|
-
|
|
810
|
+
incident_id = i + 1 # Simplify unique ID generation
|
|
832
811
|
duration = random.randint(1, 5)
|
|
833
|
-
|
|
834
|
-
incident_id = random.randint(1, count)
|
|
835
|
-
if incident_id not in incident_ids:
|
|
836
|
-
incident_ids.add(incident_id)
|
|
837
|
-
break
|
|
838
|
-
incident_type = random.choice(incident_types)
|
|
812
|
+
incident_type = next(incident_type_cycle)
|
|
839
813
|
analyst = random.choice(analysts)
|
|
840
|
-
severity =
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
version=version, observables=observables, required_fields=required_fields)[0]},
|
|
870
|
-
{"event": cls.winevent(count=1, datetime_iso=datetime_iso, observables=observables)[0]},
|
|
871
|
-
{"event": cls.json(count=1, datetime_iso=datetime_iso, vendor=vendor, product=product,
|
|
872
|
-
version=version, observables=observables,
|
|
873
|
-
required_fields=required_fields)[0]}
|
|
874
|
-
]
|
|
875
|
-
else:
|
|
876
|
-
incident = {
|
|
877
|
-
"id": incident_id,
|
|
878
|
-
"type": incident_type,
|
|
879
|
-
"duration": duration,
|
|
880
|
-
"analyst": analyst
|
|
881
|
-
}
|
|
814
|
+
severity = Events._set_field('severity', observables) or faker.random_int(min=1, max=5)
|
|
815
|
+
description = Events._set_field('terms', observables) or faker.sentence(nb_words=10)
|
|
816
|
+
|
|
817
|
+
# Add base fields
|
|
818
|
+
incident = {}
|
|
819
|
+
field_list = fields.split(',') if fields else ['id', 'duration', 'type', 'analyst', 'severity', 'description', 'events']
|
|
820
|
+
if 'id' in field_list:
|
|
821
|
+
incident['id'] = incident_id
|
|
822
|
+
if 'duration' in field_list:
|
|
823
|
+
incident['duration'] = duration
|
|
824
|
+
if 'type' in field_list:
|
|
825
|
+
incident['type'] = incident_type
|
|
826
|
+
if 'analyst' in field_list:
|
|
827
|
+
incident['analyst'] = analyst
|
|
828
|
+
if 'severity' in field_list:
|
|
829
|
+
incident['severity'] = severity
|
|
830
|
+
if 'description' in field_list:
|
|
831
|
+
incident['description'] = description
|
|
832
|
+
|
|
833
|
+
# Generate associated events for each incident
|
|
834
|
+
if 'events' in field_list:
|
|
835
|
+
incident['events'] = [
|
|
836
|
+
{"event": cls.syslog(count=1, datetime_iso=datetime_iso, observables=observables, required_fields=required_fields)[0]},
|
|
837
|
+
{"event": cls.cef(count=1, datetime_iso=datetime_iso, vendor=vendor, product=product, version=version, observables=observables, required_fields=required_fields)[0]},
|
|
838
|
+
{"event": cls.leef(count=1, datetime_iso=datetime_iso, vendor=vendor, product=product, version=version, observables=observables, required_fields=required_fields)[0]},
|
|
839
|
+
{"event": cls.winevent(count=1, datetime_iso=datetime_iso, observables=observables)[0]},
|
|
840
|
+
{"event": cls.json(count=1, datetime_iso=datetime_iso, vendor=vendor, product=product, version=version, observables=observables, required_fields=required_fields)[0]}
|
|
841
|
+
]
|
|
842
|
+
|
|
882
843
|
incidents.append(incident)
|
|
844
|
+
|
|
883
845
|
return incidents
|