Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract additional fields #432

Merged
merged 1 commit into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading