expanded fields

This commit is contained in:
Rudi klein 2024-04-30 21:50:03 +02:00
parent 326ee6f3b2
commit c37555b092
3 changed files with 77 additions and 40 deletions

View File

@ -2,7 +2,7 @@
# This script is adapted version of the Python active response script sample, provided by Wazuh, in the documentation: # This script is adapted version of the Python active response script sample, provided by Wazuh, in the documentation:
# https://documentation.wazuh.com/current/user-manual/capabilities/active-response/custom-active-response-scripts.html) # https://documentation.wazuh.com/current/user-manual/capabilities/active-response/custom-active-response-scripts.html
# It is provided under the below copyright statement: # It is provided under the below copyright statement:
# #
# Copyright (C) 2015-2022, Wazuh Inc. # Copyright (C) 2015-2022, Wazuh Inc.
@ -16,16 +16,16 @@
# This version has changes in # This version has changes in
# 1) the first lines of code with the assignments, and # 1) the first lines of code with the assignments, and
# 2) the Start Custom Action Add section # 2) the Start Custom Action Add section
# This version is free software. Rudi Klein, april 2024 # This adapted version is free software. Rudi Klein, april 2024
import datetime
import json
import os import os
import sys import sys
import json
import datetime
from pathlib import PureWindowsPath, PurePosixPath from pathlib import PureWindowsPath, PurePosixPath
from wazuh_notifier_lib import set_env as se
from wazuh_notifier_lib import set_time as st
from wazuh_notifier_lib import import_config as ic from wazuh_notifier_lib import import_config as ic
from wazuh_notifier_lib import set_env as se
wazuh_path, ar_path, config_path = se() wazuh_path, ar_path, config_path = se()
@ -37,7 +37,9 @@ ABORT_COMMAND = 3
OS_SUCCESS = 0 OS_SUCCESS = 0
OS_INVALID = -1 OS_INVALID = -1
class message:
class Message:
def __init__(self): def __init__(self):
self.alert = "" self.alert = ""
self.command = 0 self.command = 0
@ -46,11 +48,11 @@ class message:
def write_debug_file(ar_name, msg): def write_debug_file(ar_name, msg):
with open(ar_path, mode="a") as log_file: with open(ar_path, mode="a") as log_file:
ar_name_posix = str(PurePosixPath(PureWindowsPath(ar_name[ar_name.find("active-response"):]))) ar_name_posix = str(PurePosixPath(PureWindowsPath(ar_name[ar_name.find("active-response"):])))
log_file.write(str(datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')) + " " + ar_name_posix + ": " + msg +"\n") log_file.write(
str(datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')) + " " + ar_name_posix + ": " + msg + "\n")
def setup_and_check_message(argv): def setup_and_check_message(argv):
# get alert from stdin # get alert from stdin
input_str = "" input_str = ""
for line in sys.stdin: for line in sys.stdin:
@ -63,28 +65,29 @@ def setup_and_check_message(argv):
data = json.loads(input_str) data = json.loads(input_str)
except ValueError: except ValueError:
write_debug_file(argv[0], 'Decoding JSON has failed, invalid input format') write_debug_file(argv[0], 'Decoding JSON has failed, invalid input format')
message.command = OS_INVALID Message.command = OS_INVALID
return message return Message
message.alert = data Message.alert = data
command = data.get("command") command = data.get("command")
if command == "add": if command == "add":
message.command = ADD_COMMAND Message.command = ADD_COMMAND
elif command == "delete": elif command == "delete":
message.command = DELETE_COMMAND Message.command = DELETE_COMMAND
else: else:
message.command = OS_INVALID Message.command = OS_INVALID
write_debug_file(argv[0], 'Not valid command: ' + command) write_debug_file(argv[0], 'Not valid command: ' + command)
return message return Message
def send_keys_and_check_message(argv, keys): def send_keys_and_check_message(argv, keys):
# build and send message with keys # build and send message with keys
keys_msg = json.dumps({"version": 1,"origin":{"name": argv[0],"module":"active-response"},"command":"check_keys","parameters":{"keys":keys}}) keys_msg = json.dumps(
{"version": 1, "origin": {"name": argv[0], "module": "active-response"}, "command": "check_keys",
"parameters": {"keys": keys}})
write_debug_file(argv[0], keys_msg) write_debug_file(argv[0], keys_msg)
@ -105,7 +108,7 @@ def send_keys_and_check_message(argv, keys):
data = json.loads(input_str) data = json.loads(input_str)
except ValueError: except ValueError:
write_debug_file(argv[0], 'Decoding JSON has failed, invalid input format') write_debug_file(argv[0], 'Decoding JSON has failed, invalid input format')
return message return Message
action = data.get("command") action = data.get("command")
@ -120,8 +123,34 @@ def send_keys_and_check_message(argv, keys):
return ret return ret
def main(argv): def parameters_deconstruct(event_keys):
a_id: str = str(event_keys["agent"]["id"])
a_name: str = str(event_keys["agent"]["name"])
e_level: str = str(event_keys["rule"]["level"])
e_description: str = str(event_keys["rule"]["description"])
e_id: str = str(event_keys["rule"]["id"])
e_fired_times: str = str(event_keys["rule"]["firedtimes"])
return a_id, a_name, e_id, e_description, e_level, e_fired_times
def construct_message(caller: str, a_id: str, a_name: str, e_id: str, e_description: str, e_level: str,
e_fired_times: str):
discord_accent = ""
if caller == "discord":
discord_accent = "**"
message_params: str = ("--message " + '"' +
discord_accent + "Agent: " + discord_accent + a_name + " (" + a_id + ")" + "\n" +
discord_accent + "Event id: " + discord_accent + e_id + "\n" +
discord_accent + "Description: " + discord_accent + e_description + "\n" +
discord_accent + "Threat level: " + discord_accent + e_level + "\n" +
discord_accent + "Times fired: " + discord_accent + e_fired_times + "\n" + '"')
return message_params
def main(argv):
write_debug_file(argv[0], "Started") write_debug_file(argv[0], "Started")
# validate json and get command # validate json and get command
@ -137,9 +166,10 @@ def main(argv):
""" """
alert = msg.alert["parameters"]["alert"] alert = msg.alert["parameters"]["alert"]
keys = [alert["rule"]["id"]] keys = [alert["rule"]]
""" End Custom Key """ agent_id, agent_name, event_level, event_description, event_id, event_fired_times = parameters_deconstruct(
alert)
action = send_keys_and_check_message(argv, keys) action = send_keys_and_check_message(argv, keys)
@ -155,22 +185,23 @@ def main(argv):
""" Start Custom Action Add """ """ Start Custom Action Add """
if 1 == 1: if str(ic("discord_enabled")) == "1":
caller = "discord"
discord_notifier = '{0}/active-response/bin/wazuh-discord-notifier.py'.format(wazuh_path) discord_notifier = '{0}/active-response/bin/wazuh-discord-notifier.py'.format(wazuh_path)
discord_exec = "python3 " + discord_notifier + " " discord_exec = "python3 " + discord_notifier + " "
write_debug_file(argv[0], "Start Discord notifier") write_debug_file(argv[0], "Start Discord notifier")
discord_params = "--message " + '"' + str(keys) + '"' discord_params = construct_message(caller, agent_id, agent_name, event_level, event_description, event_id,
event_fired_times)
discord_command = discord_exec + discord_params discord_command = discord_exec + discord_params
os.system(discord_command) os.system(discord_command)
if str(ic("ntfy_enabled")) == "1":
if str(ic("discord_enabled")) == "1": caller = "ntfy"
ntfy_notifier = '{0}/active-response/bin/wazuh-ntfy-notifier.py'.format(wazuh_path) ntfy_notifier = '{0}/active-response/bin/wazuh-ntfy-notifier.py'.format(wazuh_path)
ntfy_exec = "python3 " + ntfy_notifier + " " ntfy_exec = "python3 " + ntfy_notifier + " "
write_debug_file(argv[0], "Start NTFY notifier") write_debug_file(argv[0], "Start NTFY notifier")
ntfy_params = "-d __KleinTest --message " + '"' + str(keys) + '"' ntfy_params = construct_message(caller, agent_id, agent_name, event_level, event_description, event_id,
event_fired_times)
ntfier_command = ntfy_exec + ntfy_params ntfier_command = ntfy_exec + ntfy_params
os.system(ntfier_command) os.system(ntfier_command)
@ -180,7 +211,7 @@ def main(argv):
""" Start Custom Action Delete """ """ Start Custom Action Delete """
os.remove("ar-test-result.txt") pass
""" End Custom Action Delete """ """ End Custom Action Delete """
@ -193,4 +224,4 @@ def main(argv):
if __name__ == "__main__": if __name__ == "__main__":
main(sys.argv) main(sys.argv)

View File

@ -16,17 +16,17 @@
# with their friends and communities. It allows for receiving message using webhooks. # with their friends and communities. It allows for receiving message using webhooks.
# For more information: https://discord.com. # For more information: https://discord.com.
import requests
import getopt import getopt
import sys
import os import os
from dotenv import load_dotenv import sys
from os import getenv
from os.path import join, dirname from os.path import join, dirname
import requests
from dotenv import load_dotenv
from wazuh_notifier_lib import import_config as ic
from wazuh_notifier_lib import set_env as se from wazuh_notifier_lib import set_env as se
from wazuh_notifier_lib import set_time as st from wazuh_notifier_lib import set_time as st
from wazuh_notifier_lib import import_config as ic
from wazuh_notifier_lib import view_config as vc from wazuh_notifier_lib import view_config as vc
# Get path values # Get path values
@ -54,7 +54,7 @@ except Exception as err:
def discord_command(n_server, n_sender, n_destination, n_priority, n_message, n_tags, n_click): def discord_command(n_server, n_sender, n_destination, n_priority, n_message, n_tags, n_click):
x_message = (now_message + x_message = (now_message +
"\n\n" + "**__" + n_message + "__**\n\n" + "\n\n" + n_message + "\n\n" +
"Priority: " + n_priority + "\n" + "Priority: " + n_priority + "\n" +
"Tags: " + n_tags + "\n\n" + n_click "Tags: " + n_tags + "\n\n" + n_click
) )

View File

@ -4,7 +4,7 @@ import time
import yaml import yaml
# Set structured timestamp. # Set structured timestamp for logging and discord/ntfy message.
def set_time(): def set_time():
@ -12,8 +12,10 @@ def set_time():
now_logging = time.strftime('%Y/%m/%d %H:%M:%S') now_logging = time.strftime('%Y/%m/%d %H:%M:%S')
return now_message, now_logging return now_message, now_logging
# Define paths
# Define paths: wazuh_path = wazuh root directory
# ar_path = active-responses.log path,
# config_path = wazuh-notifier-config.yaml
def set_env(): def set_env():
@ -24,6 +26,9 @@ def set_env():
return wazuh_path, ar_path, config_path return wazuh_path, ar_path, config_path
# Import configuration settings from wazuh-notifier-config.yaml
def import_config(key): def import_config(key):
try: try:
_, _, config_path = set_env() _, _, config_path = set_env()
@ -36,7 +41,8 @@ def import_config(key):
return None return None
# Showing yaml config # Show configuration settings from wazuh-notifier-config.yaml
def view_config(): def view_config():