This commit is contained in:
92
main.go
92
main.go
@@ -4963,42 +4963,51 @@ func buildSQLMatchCondition(r DynamicRule) (string, []any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) runDetectionsOnce() {
|
func (s *server) runDetectionsOnce() {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), s.cfg.DetectionInterval)
|
type ruleSpec struct {
|
||||||
defer cancel()
|
name string
|
||||||
|
timeout time.Duration
|
||||||
if err := s.detector.updateAgentMetrics(ctx); err != nil {
|
fn func(context.Context) error
|
||||||
s.logger.Printf("update agent metrics: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rules := []struct {
|
rules := []ruleSpec{
|
||||||
name string
|
{"agent_offline", 15 * time.Second, s.detector.runAgentOfflineRule},
|
||||||
fn func(context.Context) error
|
{"failed_logon_spike", 45 * time.Second, s.detector.runFailedLogonSpikeRule},
|
||||||
}{
|
{"reboot_spike", 30 * time.Second, s.detector.runRebootSpikeRule},
|
||||||
{"agent_offline", s.detector.runAgentOfflineRule},
|
{"new_event_id", 60 * time.Second, s.detector.runNewEventIDRule},
|
||||||
{"failed_logon_spike", s.detector.runFailedLogonSpikeRule},
|
{"password_spray", 60 * time.Second, s.detector.runPasswordSprayRule},
|
||||||
{"reboot_spike", s.detector.runRebootSpikeRule},
|
{"success_after_failures", 90 * time.Second, s.detector.runSuccessAfterFailuresRule},
|
||||||
{"new_event_id", s.detector.runNewEventIDRule},
|
{"new_source_ip_for_user", 90 * time.Second, s.detector.runNewSourceIPForUserRule},
|
||||||
{"password_spray", s.detector.runPasswordSprayRule},
|
{"dynamic_rules", 60 * time.Second, s.detector.runDynamicRules},
|
||||||
{"success_after_failures", s.detector.runSuccessAfterFailuresRule},
|
|
||||||
{"new_source_ip_for_user", s.detector.runNewSourceIPForUserRule},
|
|
||||||
{"dynamic_rules", s.detector.runDynamicRules},
|
|
||||||
|
|
||||||
{"ueba_admin_new_host", s.detector.runAdminNewHostRule},
|
{"ueba_admin_new_host", 90 * time.Second, s.detector.runAdminNewHostRule},
|
||||||
{"ueba_offhours_login", s.detector.runOffHoursLoginRule},
|
{"ueba_offhours_login", 60 * time.Second, s.detector.runOffHoursLoginRule},
|
||||||
{"ueba_first_privileged_use", s.detector.runFirstTimePrivilegedRule},
|
{"ueba_first_privileged_use", 60 * time.Second, s.detector.runFirstTimePrivilegedRule},
|
||||||
{"ueba_new_user_context", s.detector.runUEBANewUserContextRule},
|
|
||||||
{"ueba_update", s.detector.runUEBABaselineUpdate},
|
// Diese Regel ist bei dir aktuell der Problemfall.
|
||||||
|
{"ueba_new_user_context", 180 * time.Second, s.detector.runUEBANewUserContextRule},
|
||||||
|
|
||||||
|
{"ueba_update", 120 * time.Second, s.detector.runUEBABaselineUpdate},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, rule := range rules {
|
for _, rule := range rules {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
if err := rule.fn(ctx); err != nil {
|
|
||||||
s.logger.Printf("rule %s error: %v", rule.name, err)
|
ctx, cancel := context.WithTimeout(context.Background(), rule.timeout)
|
||||||
|
err := rule.fn(ctx)
|
||||||
|
cancel()
|
||||||
|
|
||||||
|
dur := time.Since(start)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Printf("rule %s error after %s: %v", rule.name, dur, err)
|
||||||
s.detector.ruleErrorsTotal.WithLabelValues(rule.name).Inc()
|
s.detector.ruleErrorsTotal.WithLabelValues(rule.name).Inc()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.logger.Printf("rule %s completed in %s", rule.name, dur)
|
||||||
|
|
||||||
s.detector.ruleLastRunGauge.WithLabelValues(rule.name).Set(float64(time.Now().Unix()))
|
s.detector.ruleLastRunGauge.WithLabelValues(rule.name).Set(float64(time.Now().Unix()))
|
||||||
s.detector.ruleRuntimeHist.WithLabelValues(rule.name).Observe(time.Since(start).Seconds())
|
s.detector.ruleRuntimeHist.WithLabelValues(rule.name).Observe(dur.Seconds())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5061,6 +5070,8 @@ func (d *detector) runUEBANewUserContextRule(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
windowEnd := time.Now().UTC()
|
windowEnd := time.Now().UTC()
|
||||||
windowStart := windowEnd.Add(-d.cfg.UEBANewContextWindow)
|
windowStart := windowEnd.Add(-d.cfg.UEBANewContextWindow)
|
||||||
|
|
||||||
@@ -5079,23 +5090,21 @@ WHERE e.channel_name = 'Security'
|
|||||||
AND e.target_user <> ''
|
AND e.target_user <> ''
|
||||||
AND e.target_user <> '-'
|
AND e.target_user <> '-'
|
||||||
AND e.target_user NOT LIKE '%$'
|
AND e.target_user NOT LIKE '%$'
|
||||||
AND LOWER(e.target_user) NOT IN (
|
|
||||||
'system',
|
|
||||||
'localsystem',
|
|
||||||
'local service',
|
|
||||||
'network service',
|
|
||||||
'anonymous logon'
|
|
||||||
)
|
|
||||||
GROUP BY e.hostname, e.target_user, e.src_ip, e.workstation
|
GROUP BY e.hostname, e.target_user, e.src_ip, e.workstation
|
||||||
`
|
`
|
||||||
|
|
||||||
rows, err := d.db.QueryContext(ctx, q, windowStart, windowEnd)
|
rows, err := d.db.QueryContext(ctx, q, windowStart, windowEnd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("query ueba_new_user_context after %s: %w", time.Since(start), err)
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
|
rowCount := 0
|
||||||
|
newCount := 0
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
|
rowCount++
|
||||||
|
|
||||||
var host, user, srcIP, workstation string
|
var host, user, srcIP, workstation string
|
||||||
var firstSeen time.Time
|
var firstSeen time.Time
|
||||||
var count int
|
var count int
|
||||||
@@ -5118,6 +5127,8 @@ GROUP BY e.hostname, e.target_user, e.src_ip, e.workstation
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newCount++
|
||||||
|
|
||||||
score := 2.0
|
score := 2.0
|
||||||
severity := "medium"
|
severity := "medium"
|
||||||
|
|
||||||
@@ -5162,9 +5173,20 @@ GROUP BY e.hostname, e.target_user, e.src_ip, e.workstation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rows.Err()
|
if err := rows.Err(); err != nil {
|
||||||
}
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.logger.Printf(
|
||||||
|
"ueba_new_user_context processed rows=%d new_contexts=%d window=%s duration=%s",
|
||||||
|
rowCount,
|
||||||
|
newCount,
|
||||||
|
d.cfg.UEBANewContextWindow,
|
||||||
|
time.Since(start),
|
||||||
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
func riskWeight(severity string) float64 {
|
func riskWeight(severity string) float64 {
|
||||||
switch severity {
|
switch severity {
|
||||||
case "critical":
|
case "critical":
|
||||||
|
|||||||
Reference in New Issue
Block a user