Merge pull request #1 from RudiKlein/Darius

Darius
This commit is contained in:
Rudi klein 2024-05-09 15:29:32 +02:00 committed by GitHub
commit f4a66df0f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 221 additions and 35 deletions

11
test.go Normal file
View File

@ -0,0 +1,11 @@
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println("hier")
os.Stderr.Write([]byte("hier2"))
}

31
wazuh-notifier-conf.yaml Executable file
View File

@ -0,0 +1,31 @@
---
#start of yaml
# This is the yaml config file for both the wazuh-ntfy-notifier.py and wazuh-discord-notifier.py.
# The yaml needs to be in the same folder as the wazuh-ntfy-notifier.py and wazuh-discord-notifier.py
# COMMON (custom-wazuh-notifiers.py) configuration settings start here.
# 1 = messages will be sent through this message server. 0 = messages will NOT be sent through this message server.
targets: "discord,ntfy"
# Exclude rules that are listed in the ossec.conf active response definition.
excluded_rules: "5401, 5403"
excluded_agents: "999"
# Priority mapping from 1-12 (Wazuh events) to 1-5 (Discord and ntfy notification)
notifier_priority_1: 12, 11, 10
notifier_priority_2: 9, 8
notifier_priority_3: 7, 6
notifier_priority_4: 5, 4
notifier_priority_5: 3 ,2, 1
sender: "Wazuh (IDS)"
click: "https://google.com"
#end of yaml
...

View File

@ -16,11 +16,11 @@ excluded_agents: "999"
# Priority mapping from 1-12 (Wazuh events) to 1-5 (Discord and ntfy notification) # Priority mapping from 1-12 (Wazuh events) to 1-5 (Discord and ntfy notification)
notifier_priority_1: 12, 11, 10 priority_1: 12, 11, 10
notifier_priority_2: 9, 8 priority_2: 9, 8
notifier_priority_3: 7, 6 priority_3: 7, 6
notifier_priority_4: 5, 4 priority_4: 5, 4
notifier_priority_5: 3 ,2, 1 priority_5: 3 ,2, 1
sender: "Wazuh (IDS)" sender: "Wazuh (IDS)"
click: "https://google.com" click: "https://google.com"

View File

@ -0,0 +1,14 @@
package log
import (
"os"
"time"
)
var f, _ = os.OpenFile("active-responses.log", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
func Log(message string) {
if _, err := f.WriteString("\n" + time.Now().Format(time.DateTime) + message); err != nil {
panic(err)
}
}

View File

@ -2,19 +2,21 @@ package main
import ( import (
"strings" "strings"
"wazuh-notify/log"
"wazuh-notify/notification" "wazuh-notify/notification"
"wazuh-notify/types" "wazuh-notify/services"
) )
var inputParams types.Params
func main() { func main() {
initNotify() inputParams := services.InitNotify()
for _, target := range strings.Split(inputParams.Targets, ",") { for _, target := range strings.Split(inputParams.Targets, ",") {
switch target { switch target {
case "discord": case "discord":
log.Log(target)
notification.SendDiscord(inputParams) notification.SendDiscord(inputParams)
case "ntfy": case "ntfy":
log.Log(target)
notification.SendNtfy(inputParams) notification.SendNtfy(inputParams)
} }
} }

View File

@ -3,26 +3,30 @@ package notification
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt"
"log" "log"
"net/http" "net/http"
"os" "os"
"strconv"
"wazuh-notify/types" "wazuh-notify/types"
) )
func SendDiscord(params types.Params) { func SendDiscord(params types.Params) {
embedDescription := fmt.Sprintf("\n\n %s \n\nPriority: %x\nTags: %s\n\n%s", embedDescription := "\n\n" +
params.Message, "**Agent:** " + params.WazuhMessage.Parameters.Alert.Agent.Name + "\n" +
params.Priority, "**Event id:** " + params.WazuhMessage.Parameters.Alert.Rule.ID + "\n" +
params.Tags, "**Description:** " + params.WazuhMessage.Parameters.Alert.Rule.Description + "\n" +
params.Click, "**Threat level:** " + strconv.Itoa(params.WazuhMessage.Parameters.Alert.Rule.Level) + "\n" +
) "**Times fired:** " + strconv.Itoa(params.WazuhMessage.Parameters.Alert.Rule.Firedtimes) +
"\n\n" +
"Priority: " + strconv.Itoa(params.Priority) + "\n" +
"Tags: " + params.Tags + "\n\n" +
params.Click
message := types.Message{ message := types.Message{
Username: params.Sender, Username: params.Sender,
Embeds: []types.Embed{ Embeds: []types.Embed{
{ {
Title: params.Destination, Title: params.Sender,
Description: embedDescription, Description: embedDescription,
}, },
}, },

View File

@ -11,7 +11,12 @@ import (
func SendNtfy(params types.Params) { func SendNtfy(params types.Params) {
payload := time.Now().Format(time.RFC3339) + "\n\n" + params.Message payload := time.Now().Format(time.RFC3339) + "\n\n" +
"Agent: " + params.WazuhMessage.Parameters.Alert.Agent.Name + "\n" +
"Event id: " + params.WazuhMessage.Parameters.Alert.Rule.ID + "\n" +
"Description: " + params.WazuhMessage.Parameters.Alert.Rule.Description + "\n" +
"Threat level: " + strconv.Itoa(params.WazuhMessage.Parameters.Alert.Rule.Level) + "\n" +
"Times fired: " + strconv.Itoa(params.WazuhMessage.Parameters.Alert.Rule.Firedtimes) + "\n"
req, _ := http.NewRequest("POST", os.Getenv("NTFY_URL"), strings.NewReader(payload)) req, _ := http.NewRequest("POST", os.Getenv("NTFY_URL"), strings.NewReader(payload))
req.Header.Set("Content-Type", "text/plain") req.Header.Set("Content-Type", "text/plain")

View File

@ -1,34 +1,56 @@
package main package services
import ( import (
"bufio"
"encoding/json"
"flag" "flag"
"github.com/joho/godotenv" "github.com/joho/godotenv"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
"log"
"os" "os"
"wazuh-notify/log"
"wazuh-notify/types" "wazuh-notify/types"
) )
var inputParams types.Params
var configParams types.Params var configParams types.Params
var wazuhData types.WazuhMessage
func initNotify() { func InitNotify() types.Params {
err := godotenv.Load() err := godotenv.Load()
if err != nil { if err != nil {
log.Fatalf(".env not found: %v", err) log.Log("env failed to load")
return } else {
log.Log("env loaded")
} }
wazuhInput()
yamlFile, err := os.ReadFile("./config.yaml") yamlFile, err := os.ReadFile("./config.yaml")
yaml.Unmarshal(yamlFile, &configParams) yaml.Unmarshal(yamlFile, &configParams)
flag.StringVar(&inputParams.Server, "server", "", "is the webhook URL of the Discord server. It is stored in .env.") log.Log("yaml loaded")
flag.StringVar(&inputParams.Url, "url", "", "is the webhook URL of the Discord server. It is stored in .env.")
flag.StringVar(&inputParams.Click, "click", configParams.Click, "is a link (URL) that can be followed by tapping/clicking inside the message. Default is https://google.com.") flag.StringVar(&inputParams.Click, "click", configParams.Click, "is a link (URL) that can be followed by tapping/clicking inside the message. Default is https://google.com.")
flag.StringVar(&inputParams.Destination, "destination", "", "is the destination (actually the originator) of the message, either an app name or a person. Default is \"Wazuh (IDS)\"")
flag.StringVar(&inputParams.Message, "message", "", "is the text of the message to be sent. Default is \"Test message\", but may include --tags and/or --click.")
flag.IntVar(&inputParams.Priority, "priority", 0, "is the priority of the message, ranging from 1 (highest), to 5 (lowest). Default is 5.") flag.IntVar(&inputParams.Priority, "priority", 0, "is the priority of the message, ranging from 1 (highest), to 5 (lowest). Default is 5.")
flag.StringVar(&inputParams.Sender, "sender", configParams.Sender, "is the sender of the message, either an app name or a person. The default is \"Security message\".") flag.StringVar(&inputParams.Sender, "sender", configParams.Sender, "is the sender of the message, either an app name or a person. The default is \"Security message\".")
flag.StringVar(&inputParams.Tags, "tags", "", "is an arbitrary strings of tags (keywords), seperated by a \",\" (comma). Default is \"informational,testing,hard-coded\".") flag.StringVar(&inputParams.Tags, "tags", "", "is an arbitrary strings of tags (keywords), seperated by a \",\" (comma). Default is \"informational,testing,hard-coded\".")
flag.StringVar(&inputParams.Targets, "targets", "", "is a list of targets to send notifications to. Default is \"discord\".") flag.StringVar(&inputParams.Targets, "targets", "", "is a list of targets to send notifications to. Default is \"discord\".")
flag.Parse() flag.Parse()
log.Log("yaml loaded")
inputParams.Targets = configParams.Targets
return inputParams
}
func wazuhInput() {
reader := bufio.NewReader(os.Stdin)
json.NewDecoder(reader).Decode(&wazuhData)
mapPriority()
inputParams.WazuhMessage = wazuhData
} }

View File

@ -0,0 +1,21 @@
package services
import "slices"
func mapPriority() {
if slices.Contains(configParams.Priority1, wazuhData.Parameters.Alert.Rule.Level) {
inputParams.Priority = wazuhData.Parameters.Alert.Rule.Level
}
if slices.Contains(configParams.Priority2, wazuhData.Parameters.Alert.Rule.Level) {
inputParams.Priority = wazuhData.Parameters.Alert.Rule.Level
}
if slices.Contains(configParams.Priority3, wazuhData.Parameters.Alert.Rule.Level) {
inputParams.Priority = wazuhData.Parameters.Alert.Rule.Level
}
if slices.Contains(configParams.Priority4, wazuhData.Parameters.Alert.Rule.Level) {
inputParams.Priority = wazuhData.Parameters.Alert.Rule.Level
}
if slices.Contains(configParams.Priority5, wazuhData.Parameters.Alert.Rule.Level) {
inputParams.Priority = wazuhData.Parameters.Alert.Rule.Level
}
}

View File

@ -1,14 +1,18 @@
package types package types
type Params struct { type Params struct {
Server string Url string
Sender string `yaml:"sender,omitempty"` Sender string `yaml:"sender,omitempty"`
Destination string
Priority int Priority int
Message string
Tags string Tags string
Click string `yaml:"click,omitempty"` Click string `yaml:"click,omitempty"`
Targets string `yaml:"targets,omitempty"` Targets string `yaml:"targets,omitempty"`
WazuhMessage WazuhMessage
Priority1 []int `yaml:"priority_1"`
Priority2 []int `yaml:"priority_2"`
Priority3 []int `yaml:"priority_3"`
Priority4 []int `yaml:"priority_4"`
Priority5 []int `yaml:"priority_5"`
} }
type Message struct { type Message struct {

View File

@ -0,0 +1,72 @@
package types
type WazuhMessage struct {
Version int `json:"version"`
Origin Origin `json:"origin"`
Command string `json:"command"`
Parameters Parameters `json:"parameters"`
}
type Origin struct {
Name string `json:"name"`
Module string `json:"module"`
}
type Parameters struct {
ExtraArgs []interface{} `json:"extra_args"`
Alert Alert `json:"alert"`
Program string `json:"program"`
}
type Alert struct {
Timestamp string `json:"timestamp"`
Rule Rule `json:"rule"`
Agent Agent `json:"agent"`
Manager Manager `json:"manager"`
ID string `json:"id"`
FullLog string `json:"full_log"`
Decoder Decoder `json:"decoder"`
Data Data `json:"data"`
Location string `json:"location"`
}
type Rule struct {
Level int `json:"level"`
Description string `json:"description"`
ID string `json:"id"`
Mitre Mitre `json:"mitre"`
Info string `json:"info"`
Firedtimes int `json:"firedtimes"`
Mail bool `json:"mail"`
Groups []string `json:"groups"`
PciDss []string `json:"pci_dss"`
Gdpr []string `json:"gdpr"`
Nist80053 []string `json:"nist_800_53"`
Tsc []string `json:"tsc"`
}
type Mitre struct {
ID []string `json:"id"`
Tactic []string `json:"tactic"`
Technique []string `json:"technique"`
}
type Agent struct {
ID string `json:"id"`
Name string `json:"name"`
}
type Manager struct {
Name string `json:"name"`
}
type Decoder struct {
Name string `json:"name"`
}
type Data struct {
Protocol string `json:"protocol"`
Srcip string `json:"srcip"`
ID string `json:"id"`
URL string `json:"url"`
}

View File

@ -45,7 +45,7 @@ def set_environment():
wazuh_path = "/var/ossec" wazuh_path = "/var/ossec"
# wazuh_path = os.path.abspath(os.path.join(__file__, "../../..")) # wazuh_path = os.path.abspath(os.path.join(__file__, "../../.."))
ar_path = '{0}/logs/active-responses.log'.format(wazuh_path) ar_path = '{0}/logs/active-responses.log'.format(wazuh_path)
config_path = 'wazuh-notifier-config.yaml'.format(wazuh_path) config_path = 'wazuh-notifier-conf.yaml'.format(wazuh_path)
return wazuh_path, ar_path, config_path return wazuh_path, ar_path, config_path