FIXES: Added wazuh integration and loads more
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
# Created by Shuffle, AS. <frikky@shuffler.io>.
|
||||
|
||||
WPYTHON_BIN="framework/python/bin/python3"
|
||||
|
||||
SCRIPT_PATH_NAME="$0"
|
||||
|
||||
DIR_NAME="$(cd $(dirname ${SCRIPT_PATH_NAME}); pwd -P)"
|
||||
SCRIPT_NAME="$(basename ${SCRIPT_PATH_NAME})"
|
||||
|
||||
case ${DIR_NAME} in
|
||||
*/active-response/bin | */wodles*)
|
||||
if [ -z "${WAZUH_PATH}" ]; then
|
||||
WAZUH_PATH="$(cd ${DIR_NAME}/../..; pwd)"
|
||||
fi
|
||||
|
||||
PYTHON_SCRIPT="${DIR_NAME}/${SCRIPT_NAME}.py"
|
||||
;;
|
||||
*/bin)
|
||||
if [ -z "${WAZUH_PATH}" ]; then
|
||||
WAZUH_PATH="$(cd ${DIR_NAME}/..; pwd)"
|
||||
fi
|
||||
|
||||
PYTHON_SCRIPT="${WAZUH_PATH}/framework/scripts/${SCRIPT_NAME}.py"
|
||||
;;
|
||||
*/integrations)
|
||||
if [ -z "${WAZUH_PATH}" ]; then
|
||||
WAZUH_PATH="$(cd ${DIR_NAME}/..; pwd)"
|
||||
fi
|
||||
|
||||
PYTHON_SCRIPT="${DIR_NAME}/${SCRIPT_NAME}.py"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
${WAZUH_PATH}/${WPYTHON_BIN} ${PYTHON_SCRIPT} "$@"
|
||||
@@ -0,0 +1,177 @@
|
||||
#!/usr/bin/env python
|
||||
# Created by Shuffle, AS. <frikky@shuffler.io>.
|
||||
# Based on the Slack integration using Webhooks
|
||||
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
import os
|
||||
|
||||
try:
|
||||
import requests
|
||||
from requests.auth import HTTPBasicAuth
|
||||
except Exception as e:
|
||||
print("No module 'requests' found. Install: pip install requests")
|
||||
sys.exit(1)
|
||||
|
||||
# ADD THIS TO ossec.conf configuration:
|
||||
# <integration>
|
||||
# <name>custom-shuffle</name>
|
||||
# <hook_url>http://<IP>:3001/api/v1/hooks/<HOOK_ID></hook_url>
|
||||
# <level>3</level>
|
||||
# <alert_format>json</alert_format>
|
||||
# </integration>
|
||||
|
||||
# Global vars
|
||||
|
||||
debug_enabled = False
|
||||
pwd = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||
json_alert = {}
|
||||
now = time.strftime("%a %b %d %H:%M:%S %Z %Y")
|
||||
|
||||
# Set paths
|
||||
log_file = '{0}/logs/integrations.log'.format(pwd)
|
||||
|
||||
|
||||
def main(args):
|
||||
debug("# Starting")
|
||||
|
||||
# Read args
|
||||
alert_file_location = args[1]
|
||||
webhook = args[3]
|
||||
|
||||
debug("# Webhook")
|
||||
debug(webhook)
|
||||
|
||||
debug("# File location")
|
||||
debug(alert_file_location)
|
||||
|
||||
# Load alert. Parse JSON object.
|
||||
with open(alert_file_location) as alert_file:
|
||||
json_alert = json.load(alert_file)
|
||||
debug("# Processing alert")
|
||||
debug(json_alert)
|
||||
|
||||
debug("# Generating message")
|
||||
msg = generate_msg(json_alert)
|
||||
if isinstance(msg, str):
|
||||
if len(msg) == 0:
|
||||
return
|
||||
debug(msg)
|
||||
|
||||
debug("# Sending message")
|
||||
send_msg(msg, webhook)
|
||||
|
||||
|
||||
def debug(msg):
|
||||
if debug_enabled:
|
||||
msg = "{0}: {1}\n".format(now, msg)
|
||||
print(msg)
|
||||
f = open(log_file, "a")
|
||||
f.write(msg)
|
||||
f.close()
|
||||
|
||||
# Skips container kills to stop self-recursion
|
||||
def filter_msg(alert):
|
||||
# These are things that recursively happen because Shuffle starts Docker containers
|
||||
# Docker integration rules: https://github.com/wazuh/wazuh-ruleset/blob/ae36745db1d3f312db0392f5925c2f2b0ec009a9/rules/0560-docker_integration_rules.xml
|
||||
skip = ["87924", "87900", "87901", "87902", "87903", "87904", "86001", "86002", "86003", "87932", "80710", "87929", "87928",]
|
||||
if alert["rule"]["id"] in skip:
|
||||
return False
|
||||
|
||||
#try:
|
||||
# if "docker" in alert["rule"]["description"].lower() and "
|
||||
#msg['text'] = alert.get('full_log')
|
||||
#except:
|
||||
# pass
|
||||
#msg['title'] = alert['rule']['description'] if 'description' in alert['rule'] else "N/A"
|
||||
|
||||
return True
|
||||
|
||||
def generate_msg(alert):
|
||||
if not filter_msg(alert):
|
||||
print("Skipping rule %s" % alert["rule"]["id"])
|
||||
return ""
|
||||
|
||||
level = alert['rule']['level']
|
||||
|
||||
if (level <= 4):
|
||||
color = "good"
|
||||
elif (level >= 5 and level <= 7):
|
||||
color = "warning"
|
||||
else:
|
||||
color = "danger"
|
||||
|
||||
msg = {}
|
||||
msg['color'] = color
|
||||
msg['pretext'] = "WAZUH Alert"
|
||||
msg['title'] = alert['rule']['description'] if 'description' in alert['rule'] else "N/A"
|
||||
msg['text'] = alert.get('full_log')
|
||||
msg['rule_id'] = alert["rule"]["id"]
|
||||
msg['timestamp'] = alert["timestamp"]
|
||||
msg['id'] = alert['id']
|
||||
msg["all_fields"] = alert
|
||||
|
||||
#msg['fields'] = []
|
||||
# msg['fields'].append({
|
||||
# "title": "Agent",
|
||||
# "value": "({0}) - {1}".format(
|
||||
# alert['agent']['id'],
|
||||
# alert['agent']['name']
|
||||
# ),
|
||||
# })
|
||||
#if 'agentless' in alert:
|
||||
# msg['fields'].append({
|
||||
# "title": "Agentless Host",
|
||||
# "value": alert['agentless']['host'],
|
||||
# })
|
||||
|
||||
#msg['fields'].append({"title": "Location", "value": alert['location']})
|
||||
#msg['fields'].append({
|
||||
# "title": "Rule ID",
|
||||
# "value": "{0} _(Level {1})_".format(alert['rule']['id'], level),
|
||||
#})
|
||||
|
||||
#attach = {'attachments': [msg]}
|
||||
|
||||
return json.dumps(msg)
|
||||
|
||||
|
||||
def send_msg(msg, url):
|
||||
headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'}
|
||||
res = requests.post(url, data=msg, headers=headers)
|
||||
debug(res)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
# Read arguments
|
||||
bad_arguments = False
|
||||
if len(sys.argv) >= 4:
|
||||
msg = '{0} {1} {2} {3} {4}'.format(
|
||||
now,
|
||||
sys.argv[1],
|
||||
sys.argv[2],
|
||||
sys.argv[3],
|
||||
sys.argv[4] if len(sys.argv) > 4 else '',
|
||||
)
|
||||
debug_enabled = (len(sys.argv) > 4 and sys.argv[4] == 'debug')
|
||||
else:
|
||||
msg = '{0} Wrong arguments'.format(now)
|
||||
bad_arguments = True
|
||||
|
||||
# Logging the call
|
||||
f = open(log_file, 'a')
|
||||
f.write(msg + '\n')
|
||||
f.close()
|
||||
|
||||
if bad_arguments:
|
||||
debug("# Exiting: Bad arguments.")
|
||||
sys.exit(1)
|
||||
|
||||
# Main function
|
||||
main(sys.argv)
|
||||
|
||||
except Exception as e:
|
||||
debug(str(e))
|
||||
raise
|
||||
@@ -1,7 +1,5 @@
|
||||
<integration>
|
||||
<name>Shuffle</name>
|
||||
<name>custom-shuffle</name>
|
||||
<hook_url>http://<IP>:3001/api/v1/hooks/webhook_<HOOK_ID></hook_url>
|
||||
<level>2</level>
|
||||
<group>multiple_drops|authentication_failures</group>
|
||||
<alert_format>json</alert_format>
|
||||
</integration>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
requests
|
||||
@@ -1,44 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Based on
|
||||
# https://wazuh.com/blog/how-to-integrate-external-software-using-integrator/
|
||||
|
||||
import sys
|
||||
import json
|
||||
import requests
|
||||
from requests.auth import HTTPBasicAuth
|
||||
|
||||
# Set the project attributes
|
||||
project_alias = 'TI'
|
||||
issue_name ='FIM'
|
||||
|
||||
# Read configuration parameters
|
||||
alert_file = open(sys.argv[1])
|
||||
user = sys.argv[2].split(':')[0]
|
||||
api_key = sys.argv[2].split(':')[1]
|
||||
hook_url = sys.argv[3]
|
||||
|
||||
# Read the alert file
|
||||
alert_json = json.loads(alert_file.read())
|
||||
alert_file.close()
|
||||
|
||||
# Extract issue fields
|
||||
alert_level = alert_json['rule']['level']
|
||||
description = alert_json['rule']['description']
|
||||
path = alert_json['syscheck']['path']
|
||||
|
||||
# Generate request
|
||||
msg_data = {}
|
||||
msg_data['fields'] = {}
|
||||
msg_data['fields']['project'] = {}
|
||||
msg_data['fields']['project']['key'] = project_alias
|
||||
msg_data['fields']['summary'] = 'FIM alert on [' + path + ']'
|
||||
msg_data['fields']['description'] = '- State: ' + description + '\n- Alert level: ' + str(alert_level)
|
||||
msg_data['fields']['issuetype'] = {}
|
||||
msg_data['fields']['issuetype']['name'] = issue_name
|
||||
headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'}
|
||||
|
||||
# Send the request
|
||||
requests.post(hook_url, data=json.dumps(msg_data), headers=headers, auth=(user, api_key))
|
||||
|
||||
sys.exit(0)
|
||||
@@ -1,5 +1,5 @@
|
||||
NAME=shuffle-orborus
|
||||
VERSION=0.8.31
|
||||
VERSION=0.8.32
|
||||
|
||||
echo "Running docker build with $NAME:$VERSION"
|
||||
#docker rmi frikky/shuffle:$NAME --force
|
||||
|
||||
@@ -562,6 +562,7 @@ func zombiecheck(workerTimeout int) error {
|
||||
|
||||
stopContainers := []string{}
|
||||
removeContainers := []string{}
|
||||
log.Printf("Workertimeout: %d", int64(workerTimeout))
|
||||
for _, container := range containers {
|
||||
// Skip random containers. Only handle things related to Shuffle.
|
||||
if !strings.Contains(container.Image, baseimagename) {
|
||||
@@ -587,10 +588,10 @@ func zombiecheck(workerTimeout int) error {
|
||||
continue
|
||||
}
|
||||
|
||||
log.Printf("[INFO] NAME: %s", name)
|
||||
currenttime := time.Now().Unix()
|
||||
log.Printf("[INFO] (%s) NAME: %s. TIME: %d", container.State, name, currenttime-container.Created)
|
||||
|
||||
// Need to check time here too because a container can be removed the same instant as its created
|
||||
currenttime := time.Now().Unix()
|
||||
if container.State != "running" && currenttime-container.Created > int64(workerTimeout) {
|
||||
removeContainers = append(removeContainers, container.ID)
|
||||
containerNames[container.ID] = name
|
||||
@@ -606,6 +607,7 @@ func zombiecheck(workerTimeout int) error {
|
||||
}
|
||||
|
||||
// FIXME - add killing of apps with same execution ID too
|
||||
log.Printf("[INFO] Should STOP %d containers.", len(stopContainers))
|
||||
for _, containername := range stopContainers {
|
||||
log.Printf("[INFO] Stopping and removing container %s", containerNames[containername])
|
||||
go dockercli.ContainerStop(ctx, containername, nil)
|
||||
@@ -617,6 +619,7 @@ func zombiecheck(workerTimeout int) error {
|
||||
Force: true,
|
||||
}
|
||||
|
||||
log.Printf("[INFO] Should REMOVE %d containers.", len(removeContainers))
|
||||
for _, containername := range removeContainers {
|
||||
go dockercli.ContainerRemove(ctx, containername, removeOptions)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user