Alerts to Improve Network Visibility
Alerting Made Easy
We've rolled out a lightweight alerting mechanism built right inside of SPR.
So SPR already has an event system and we wanted to improve the existing notification system as well as persist alerts for later.
We wanted something with the following properties:
- Allow powerful matching expressions
- Work with our lightweight key-value database for concurrent access
- Minimal system performance impact
- User Customizable, in UX with minimal coding
The stack
We carry extensive experience building threat detection products in the infosec space. Typically these have been substantial systems where event and graph databases manage petabytes of information, and reports get generated as part of data pipelines or by processing during ingestion.
We wanted to keep it simple. So this is the stack we've settled on for alerts:
- Run alert matching during event ingestion
- Keep using BoltDB as a KV which scales well and is already built
- Use
PaesslerAG/jsonpath
andgval
for JSONPath expressions and evaluation - Extensible later with custom operators and functions. We get this from
gval
- UX with our React frontend
For advanced users, exporting to InfluxDB, Splunk, or ELK can be done with the sprbus
tools or by pulling the API for events,
so threat detection experts can integrate SPR data into more sophisticated detection tools.
Expression Matching with JSONPath
Let's quickly take a tour of JSONPath.
JSONPath is a query syntax for matching fields of a JSON Object.
Consider the event below
{
"MAC": "30:58:90:32:7d:e5",
"Reason": "mismatch",
"Status": "",
"Type": "wpa",
"time": "2024-02-02T04:10:19.511662376Z",
"bucket": "wifi:auth:fail",
"MeaningOfLife": 42
}
To retrieve the MeaningOfLife
field, we can construct the following path:
$.MeaningOfLife
which returns 42
.
Looking at the basic operators for JSONPath, its very much built to recurse objects and iterate through arrays.
So suppose we have an array of events, we can build a filter expression to query for matches.
[
{
"MAC": "30:58:90:32:7d:e5",
"Reason": "mismatch",
"Status": "",
"Type": "wpa",
"time": "2024-02-02T04:10:19.511662376Z",
"bucket": "wifi:auth:fail",
"MeaningOfLife": 42
}
]
To pull out events with MeaningOfLife 42, we would apply this query:
$[?(@.MeaningOfLife==42)]
We could also use other mathematical comparisons
$[?(@.MeaningOfLife>0)]
Or with gval we can even add numbers
$[?(@.MeaningOfLife>(1+10))]
Other useful ways to match are regular expressions on strings:
$[?(@.Reason=~"^mismatch$")]
JSONPath in SPR
The best part is we don't need a SQL schema to get started. JSONPath work for all of the events in SPR.
It may seem a bit intimidating at first, and we hide out some of the extra syntax $[?@(.)]
. However,
this provides a lot of flexibility and is relatively easy once you get the hang of it.
To simplify rule writing we allow multiple JSONPath queries and provide toggles for inverting logic as well as Match One (OR) or Match Any (AND). Each JSONPath query can match on multiple fields too.
The JSONPath query language is also available under the events search view for searching.
Customizability & Decorators
Alerts can Notify in the UI or they can sit on the Alerts page for triaging. When defining an alert, users can fill out the 'Title' and 'Body' for the alert to display. These support a templating language, for populating text with fields from the Alert Event. Furthermore, we've added a few decorators with hashtags to convert identifiers to device icons or go from something like a MAC address to a device name or IP Address.
Templates expand event fields inside of curly brackets as elow:
MAC Mismatch IP Violation {{IP.SrcIP#Device}} {{IP.SrcIP}} {{Ethernet.SrcMAC}} to {{IP.DstIP}} {{Ethernet.DstMAC}}
Check out the guide for more details about how to configure alerts.
Need a feature?
If you'd like to see more added or have a question, don't hesitate to file a github issue or reach out on our discord