Skip to content
nohupped edited this page Nov 6, 2016 · 2 revisions

Why this program:

OSSec is an alert logger. However, each single alert generated by ossec is treated as an alert, and there is no built in aggregation that can be configured, which says. generate alert for event x only if it crosses a threshold of n number in the last m minutes. This program requires ossec to forward alerts as Syslog output

Work flow:

When an alert is generated by ossec and send to a udp port, it is of the format

<132>Sep 29 08:13:48 Server1 ossec: {"crit":3,"id":5402,"component":"Some-Server-001->127.0.0.1","classification":" syslog,sudo","description":"Successful sudo to ROOT executed","message":"Sep 29 08:12:07 Some-Server-001 sudo: some.user : TTY=pts/3 ; PWD=/home/some.user ; USER=root ; COMMAND=/usr/bin/strace"}

  • Gossecer will start a udp server in a separate goroutine, and reads the above alert into a string. To convert this to a valid json, it split this string with delimiter as syshostname + " ossec: ", (For the above sample alert, it will match with Server1 ossec:), and the second element of the slice is json unmarshalled into a struct along with the epoch value of current time in nano seconds as CurrentEventOccurrenceTime and writes to a channel itemschan.
  • A second goroutine will run a closure that receives this data from the channel, normalize the message according to /etc/gossecer.conf file (sample included in readme), generates a key which is the md5sum of struct.Component + " " + struct.NormalizedMessage fields of the struct, and does the redis HMSet to the key with the message, ruleset, an HIncrBy field COUNTER and TotalCount,and a redis RPush array of struct.HashKey + ":" + "EventOccurrenceTime" and the value as CurrentEventOccurrenceTime. A default TTL of 300 seconds is set. A First event occurrence time is also stored by taking the 1st value of the RPush array.
  • A third goroutine will run a closure that checks the counter of the alerts. It validates if the Currenttime - each of the time recorded in the RPush for the same alert falls within the threshold defined in the gossecer.conf file, and discards the older alerts with an LPop, and decrements the counter accordingly.
  • A fourth goroutine will send a udp alert to a configured IP and Port number as defined in the gossecer.conf file of the format map[string]interface{}{"Hostname" : struct.Component, "Syslogcrit": struct.Crit, "TotalEventOccurance": struct.TotalCount, "EventOccurance": struct.Counter, "EventThreshold": struct.Threshold, "TimesAlerted": struct.Alerted, "RuleID": struct.Id, "Message": struct.Message}

This can be read by another program, and define an action item (like a nagios alert, IRC bots, etc.) and the frequency of alert can be controlled by doing a modulus on TimesAlerted field.

Clone this wiki locally