Skip to content

Commit

Permalink
Merge pull request #432 from Security-Onion-Solutions/2.4/extract-cat
Browse files Browse the repository at this point in the history
Extract additional fields
  • Loading branch information
defensivedepth authored Apr 19, 2024
2 parents c87ec2a + 2ffb0ca commit 5e161f0
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 0 deletions.
5 changes: 5 additions & 0 deletions model/detection.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ type Detection struct {
Title string `json:"title"`
Severity Severity `json:"severity"`
Author string `json:"author"`
Category string `json:"category,omitempty"`
Description string `json:"description"`
Content string `json:"content"`
IsEnabled bool `json:"isEnabled"`
Expand All @@ -113,6 +114,10 @@ type Detection struct {
Tags []string `json:"tags"`
Ruleset *string `json:"ruleset"`
License string `json:"license"`

// elastalert - sigma only
Product string `json:"product,omitempty"`
Service string `json:"service,omitempty"`
}

type DetectionComment struct {
Expand Down
12 changes: 12 additions & 0 deletions server/modules/elastalert/elastalert.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,18 @@ func (e *ElastAlertEngine) ExtractDetails(detect *model.Detection) error {
detect.Description = *rule.Description
}

if rule.LogSource.Category != nil {
detect.Category = *rule.LogSource.Category
}

if rule.LogSource.Product != nil {
detect.Product = *rule.LogSource.Product
}

if rule.LogSource.Service != nil {
detect.Service = *rule.LogSource.Service
}

if rule.Level != nil {
switch strings.ToLower(string(*rule.Level)) {
case "informational":
Expand Down
3 changes: 3 additions & 0 deletions server/modules/elastalert/elastalert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ level: high
Severity: model.SeverityHigh,
Content: data,
Description: "Always Alerts",
Product: "windows",
IsCommunity: true,
Engine: model.EngineNameElastAlert,
Language: model.SigLangSigma,
Expand Down Expand Up @@ -470,6 +471,8 @@ level: high
Content: data,
Description: "Detects when a user fails to login to the Security Onion Console (Web UI). Review associated logs for target username and source IP.",
IsCommunity: true,
Product: "kratos",
Service: "audit",
Engine: model.EngineNameElastAlert,
Language: model.SigLangSigma,
Ruleset: util.Ptr("repo-path"),
Expand Down
12 changes: 12 additions & 0 deletions server/modules/elastalert/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,17 @@ func (r *SigmaRule) ToDetection(content string, ruleset string, license string)
det.Description = *r.Description
}

if r.LogSource.Category != nil && *r.LogSource.Category != "" {
det.Category = *r.LogSource.Category
}

if r.LogSource.Product != nil && *r.LogSource.Product != "" {
det.Product = *r.LogSource.Product
}

if r.LogSource.Service != nil && *r.LogSource.Service != "" {
det.Service = *r.LogSource.Service
}

return det
}
27 changes: 27 additions & 0 deletions server/modules/suricata/suricata.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,28 @@ func (e *SuricataEngine) resetInterrupt() {
}
}

func checkAndExtractCategory(title string) string {
// Regex to extract the first two words from the title
regex, err := regexp.Compile(`^(\w+)\s+(\w+)`)
if err != nil {
log.WithError(err).Error("unable to compile suricata category extraction regex")
}

matches := regex.FindStringSubmatch(title)
if len(matches) > 1 {
firstWord := matches[1]
secondWord := matches[2]

// Check if the first word is one of the keywords
switch firstWord {
case "ET", "ETPRO", "GPL":
return firstWord + " " + secondWord // Return both words if the first is a keyword
}
}

return "" // Return empty string if no matches or keyword doesn't match
}

func (e *SuricataEngine) IsRunning() bool {
return e.isRunning
}
Expand All @@ -169,6 +191,8 @@ func (e *SuricataEngine) ExtractDetails(detect *model.Detection) error {

if strings.EqualFold(opt.Name, "msg") && opt.Value != nil {
detect.Title = util.Unquote(*opt.Value)
detect.Category = checkAndExtractCategory(detect.Title)

continue
}
}
Expand Down Expand Up @@ -516,6 +540,8 @@ func (e *SuricataEngine) ParseRules(content string, ruleset *string) ([]*model.D
title = strings.ReplaceAll(title, `\"`, `"`)
title = strings.ReplaceAll(title, `\\`, `\`)

category := checkAndExtractCategory(title)

severity := model.SeverityUnknown // TODO: Default severity?

md := parsed.ParseMetaData()
Expand All @@ -539,6 +565,7 @@ func (e *SuricataEngine) ParseRules(content string, ruleset *string) ([]*model.D

d := &model.Detection{
Author: socAuthor,
Category: category,
PublicID: sid,
Title: title,
Severity: severity,
Expand Down
2 changes: 2 additions & 0 deletions server/modules/suricata/suricata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ func TestParse(t *testing.T) {
Author: "__soc_import__",
PublicID: SimpleRuleSID,
Title: `GPL ATTACK_RESPONSE id check returned root`,
Category: `GPL ATTACK_RESPONSE`,
Severity: model.SeverityUnknown,
Content: SimpleRule,
Engine: model.EngineNameSuricata,
Expand All @@ -331,6 +332,7 @@ func TestParse(t *testing.T) {
Author: "__soc_import__",
PublicID: "20000",
Title: `a "tricky";\ msg`,
Category: ``,
Severity: model.SeverityInformational,
Content: `alert http any any <> any any (metadata:signature_severity Informational; sid:"20000"; msg:"a \"tricky\"\;\\ msg";)`,
Engine: model.EngineNameSuricata,
Expand Down

0 comments on commit 5e161f0

Please sign in to comment.