Skip to content

fix(rules/linux): correct detection fields, dedup & adversary on 27 validated Linux rules#2269

Merged
Kbayero merged 2 commits into
v11from
feature/linux-rules-detection-dedup-adversary
Jun 25, 2026
Merged

fix(rules/linux): correct detection fields, dedup & adversary on 27 validated Linux rules#2269
Kbayero merged 2 commits into
v11from
feature/linux-rules-detection-dedup-adversary

Conversation

@rvald26

@rvald26 rvald26 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes the detection logic, alert deduplication, and adversary attribution of 27 Linux (rules/linux/) correlation rules. Every changed rule was validated by firing real telemetry on a live UTMStack Linux agent and confirming the alert in the SIEM. Only where / grouping / adversary were changed — impact, category, technique, description, references are preserved.

Root causes (all from how the Linux agent normalizes auditd)

The agent feeds v11-log-linux-* from auditd (structured fields; command line in origin.command; no log.message) and journald (log.message, no action). This broke four classes of rule logic:

  1. Wrong field for command execution. Command lines are in origin.command (auditd execve), not log.message — a command only reaches log.message when run via sudo (which echoes … COMMAND=… to journald). So rules matching log.message for command detection fired only for privileged/sudo runs and missed unprivileged execution. → switched to origin.command (and origin.process / log.execve.a0 where appropriate, e.g. process-masquerading detects a spoofed argv[0] kernel-thread name in log.execve.a0).
  2. Non-existent log.process (the field is origin.process) — used by several persistence rules.
  3. Duplicate-alert spam. groupBy used origin.ip / origin.user / origin.host, which are empty on the agent's execve telemetry → grouping is disabled → one alert per event (a single action produced 79–158 alerts). → switched to deduplicateBy: [dataSource] (the only always-populated host key). Measured after the fix: the same bursts collapse to ~1–2 alerts per host (e.g. 79→2, 158→1).
  4. Empty adversary. Netcat (file_transfer_or_listener_established_via_netcat) and EarthWorm (tunneling_via_earthworm) used adversary: target, but target.* is empty on local Linux events → the alert had no adversary. → set adversary: origin so it is populated from origin.process / origin.command.

Brute-force (bruteforce_attack) additionally rewrites where to detect failed auth (Failed password / USER_AUTH failure) and re-points its afterEvents threshold to correlate by the populated dataSource (the original correlated by origin.user/log.hostId, which are empty).

Validation

Each of the 27 rules was deployed to a live SIEM and confirmed firing on a real payload generated on a Linux agent; the dedup change was verified to collapse a multi-event burst to a single alert per host. Full methodology, telemetry model, and per-rule results are documented in the workshop validation notes.

Scope

These are the 27 rules whose shipped logic could not fire (or duplicated) on the agent's auditd/journald telemetry. The remaining rules/linux/ rules either already fire as-shipped or target platforms not exercised here (RHEL/OpenShift/SELinux/Secure Boot, kernel-fault telemetry) and are left unchanged.

🤖 Generated with Claude Code

…7 Linux rules

Validated by firing real telemetry on a live Linux agent (auditd + journald
normalization). Three classes of issues were fixed; only detection logic /
grouping / adversary changed — impact, category, technique, description and
references are preserved.

- Wrong field for command execution: command lines are in `origin.command`
  (auditd execve), not `log.message` (only `sudo` echoes a command into
  journald). Rules matching `log.message` missed unprivileged execution →
  switched to `origin.command` / `origin.process` / `log.execve.a0`.
- Non-existent `log.process` (it is `origin.process`) on several rules.
- Duplicate-alert spam: `groupBy` used `origin.ip`/`origin.user`/`origin.host`,
  all empty on the agent's execve telemetry → grouping disabled → one alert per
  event. Switched to `deduplicateBy: [dataSource]` (the only always-populated
  host key). Measured: a burst that produced 79/158 alerts now produces ~1-2.
- Empty adversary: netcat (427) and earthworm (441) used `adversary: target`,
  but `target.*` is empty on local Linux events → set `adversary: origin`.
- Brute-force (423): rewrote `where` to detect failed auth and re-pointed the
  `afterEvents` threshold to correlate by the populated `dataSource`.

Each fixed rule was deployed to a live SIEM and confirmed firing on a real
payload generated on the agent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

❌ Go dependencies check failed

There are outdated Go dependencies, or modules that could not be inspected.
Run bash .github/scripts/go-deps.sh --update --discover locally and
commit the updated go.mod / go.sum files.

Script output
🔍 Discovered 25 Go projects

📦 Dependencies with updates available:

  📁 ./agent:
     - github.com/elastic/go-sysinfo: v1.15.4 → v1.15.5
     - gorm.io/gorm: v1.31.1 → v1.31.2

  📁 ./as400:
     - github.com/elastic/go-sysinfo: v1.15.4 → v1.15.5
     - gorm.io/gorm: v1.31.1 → v1.31.2

  📁 ./utmstack-collector:
     - github.com/elastic/go-sysinfo: v1.15.4 → v1.15.5
     - gorm.io/gorm: v1.31.1 → v1.31.2

  📁 ./installer:
     - github.com/cloudfoundry/gosigar: v1.3.121 → v1.3.122

  📁 ./plugins/gcp:
     - google.golang.org/api: v0.285.0 → v0.286.0

  📁 ./plugins/modules-config:
     - github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs: v1.77.0 → v1.78.0
     - google.golang.org/api: v0.285.0 → v0.286.0

  📁 ./plugins/aws:
     - github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs: v1.77.0 → v1.78.0

  📁 ./agent-manager:
     - gorm.io/gorm: v1.31.1 → v1.31.2

�[0;31m❌ Please update dependencies before merging.�[0m

@github-actions

Copy link
Copy Markdown

✅ AI review — Approved

No issues detected in this diff.

architecture (gemini-3-flash-lite) — clean

Summary: No reviewable changes in this diff (excluded paths only).

No findings.

bugs (gemini-3-flash-lite) — clean

Summary: No reviewable changes in this diff (excluded paths only).

No findings.

security (gemini-3-flash-lite) — clean

Summary: No reviewable changes in this diff (excluded paths only).

No findings.

@github-actions

Copy link
Copy Markdown

⛔ Permission denied

Only members of @utmstack/administrators or @utmstack/core-developers can merge PRs into this repository.

PR author: @rvald26

The comments above (deps + AI review) are still valid — if you address them, the checks will re-run automatically, but final approval is left to an administrator.

@utmstack/administrators please review.

@utmstackprapprover utmstackprapprover Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Author is not in @utmstack/administrators nor @utmstack/core-developers — admin review required.

@Kbayero Kbayero merged commit 527a9a0 into v11 Jun 25, 2026
2 checks passed
@Kbayero Kbayero deleted the feature/linux-rules-detection-dedup-adversary branch June 25, 2026 17:58

@utmstackprapprover utmstackprapprover Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Author is not in @utmstack/administrators nor @utmstack/core-developers — admin review required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants