Skip to content

Commit 527a9a0

Browse files
rvald26claudeKbayero
authored
fix(rules/linux): correct detection fields, dedup, and adversary on 27 Linux rules (#2269)
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> Co-authored-by: Yorjander Hernandez Vergara <99102374+Kbayero@users.noreply.github.com>
1 parent 42a8668 commit 527a9a0

27 files changed

Lines changed: 124 additions & 282 deletions

rules/linux/bruteforce_attack.yml

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Rule version v1.0.1
1+
# Rule version v1.0.2
22

33
dataTypes:
44
- "linux"
@@ -15,35 +15,18 @@ description: "Identifies multiple SSH login failures followed by a successful on
1515
references:
1616
- "https://attack.mitre.org/tactics/TA0006/"
1717
- "https://attack.mitre.org/techniques/T1110/"
18-
where: equals("action", "system.auth") && regexMatch("log.message", "([Ss]ession opened)") && exists("origin.user") && exists("log.hostId")
18+
where: |
19+
contains("log.message", "Failed password") || (equals("action", "USER_AUTH") && contains("log.userauth.result", "fail"))
1920
afterEvents:
2021
- indexPattern: v11-log-linux-*
2122
with:
22-
- field: origin.user
23+
- field: dataSource.keyword
2324
operator: filter_term
24-
value: '{{.origin.user}}'
25-
- field: log.hostId
26-
operator: filter_term
27-
value: '{{.log.hostId}}'
25+
value: '{{.dataSource}}'
2826
- field: log.message
2927
operator: filter_match
3028
value: 'Failed password'
3129
within: 15m
3230
count: 10
33-
or:
34-
- indexPattern: v11-log-linux-*
35-
with:
36-
- field: origin.user
37-
operator: filter_term
38-
value: '{{.origin.user}}'
39-
- field: log.hostId
40-
operator: filter_term
41-
value: '{{.log.hostId}}'
42-
- field: log.message
43-
operator: filter_match
44-
value: 'authentication failure'
45-
within: 15m
46-
count: 10
47-
groupBy:
48-
- origin.ip
49-
- origin.user
31+
deduplicateBy:
32+
- dataSource

rules/linux/debian_family/crontab_persistence.yml

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Rule version v1.0.0
1+
# Rule version v1.0.1
22

33
dataTypes:
44
- linux
@@ -24,14 +24,6 @@ description: |
2424
5. Review other persistence mechanisms on the host
2525
6. If unauthorized, remove the cron entry and investigate the source of compromise
2626
where: |
27-
(contains("log.process", "crontab") || contains("log.process", "cron") || contains("log.process", "atd")) &&
28-
(contains("log.message", "REPLACE") ||
29-
contains("log.message", "INSTALL") ||
30-
contains("log.message", "cron.d") ||
31-
contains("log.message", "crontab") ||
32-
contains("log.message", "at job") ||
33-
(contains("log.message", "EDIT") && contains("log.message", "crontab")) ||
34-
(contains("log.message", "BEGIN EDIT") || contains("log.message", "END EDIT")))
35-
groupBy:
36-
- origin.host
37-
- origin.user
27+
contains("origin.process", "crontab") && (contains("log.message", "REPLACE") || contains("log.message", "INSTALL") || contains("log.message", "LIST") || contains("log.message", "EDIT"))
28+
deduplicateBy:
29+
- dataSource
Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Rule version v1.0.0
1+
# Rule version v1.0.1
22

33
dataTypes:
44
- linux
@@ -27,32 +27,6 @@ description: |
2727
7. Analyze network connections for command and control communications
2828
8. Update security tools and perform full system scan
2929
where: |
30-
(contains("log.file_path", "/usr/bin/passwd") &&
31-
equals("log.event_type", "file_modify") &&
32-
!equals("log.process_name", "dpkg")) ||
33-
(contains("log.file_path", "/etc/ld.so.preload") &&
34-
oneOf("log.event_type", ["file_create", "file_modify"])) ||
35-
(oneOf("log.process_name", ["reptile", "bdvl", "azazel", "jynx", "xorddos"]) ||
36-
contains("log.file_path", "reptile") ||
37-
contains("log.file_path", "bdvl")) ||
38-
(contains("log.command_line", "insmod") &&
39-
(contains("log.command_line", "rootkit") ||
40-
contains("log.command_line", "hide") ||
41-
contains("log.command_line", "backdoor"))) ||
42-
(contains("log.file_path", "/proc/") &&
43-
contains("log.file_path", "/maps") &&
44-
contains("log.message", "deleted")) ||
45-
(oneOf("log.network_port", [31337, 12345, 6666]) &&
46-
equals("log.event_type", "network_listen")) ||
47-
(contains("log.file_path", "/dev/ptmx") &&
48-
equals("log.event_type", "file_create") &&
49-
!equals("log.user", "root")) ||
50-
(contains("log.message", "LKM") &&
51-
(contains("log.message", "rootkit") ||
52-
contains("log.message", "hiding"))) ||
53-
(regexMatch("log.file_path", "/lib/modules/.*/.*\\.ko") &&
54-
equals("log.event_type", "file_create") &&
55-
!equals("log.process_name", "dpkg"))
56-
groupBy:
57-
- lastEvent.log.process_name
58-
- origin.host
30+
regexMatch("origin.process", "/(reptile|bdvl|azazel|jynx|xorddos)") || (contains("origin.command", "insmod") && regexMatch("origin.command", "(rootkit|hide|backdoor)")) || (contains("origin.command", "ld.so.preload") && regexMatch("origin.command", "(>>|tee|echo)"))
31+
deduplicateBy:
32+
- dataSource

rules/linux/debian_family/ebpf_rootkit_detection.yml

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Rule version v1.0.0
1+
# Rule version v1.0.1
22

33
dataTypes:
44
- linux
@@ -24,15 +24,6 @@ description: |
2424
5. Investigate for signs of process hiding or network traffic manipulation
2525
6. If malicious, reboot the system and perform forensic analysis
2626
where: |
27-
(contains("log.message", "bpf(") || contains("log.message", "BPF") ||
28-
contains("log.message", "ebpf") || contains("log.message", "bpftool")) &&
29-
(contains("log.message", "PROG_LOAD") || contains("log.message", "prog_load") ||
30-
contains("log.message", "BPF_PROG_TYPE_TRACING") ||
31-
contains("log.message", "BPF_PROG_TYPE_KPROBE") ||
32-
contains("log.message", "BPF_PROG_TYPE_XDP") ||
33-
contains("log.message", "attached") || contains("log.message", "loaded")) &&
34-
!(contains("log.process", "systemd") || contains("log.process", "cilium") ||
35-
contains("log.process", "falco") || contains("log.process", "bpftrace"))
36-
groupBy:
37-
- origin.host
38-
- origin.user
27+
regexMatch("origin.command", "bpftool .*(prog|map).*(load|loadall|attach)") && !regexMatch("origin.command", "(cilium|falco|bpftrace)")
28+
deduplicateBy:
29+
- dataSource

rules/linux/debian_family/ld_preload_hijacking.yml

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Rule version v1.0.0
1+
# Rule version v1.0.1
22

33
dataTypes:
44
- linux
@@ -25,12 +25,6 @@ description: |
2525
6. Remove the malicious preload entry and the shared library
2626
7. Audit all running processes for injected libraries
2727
where: |
28-
(contains("log.message", "ld.so.preload") ||
29-
contains("log.message", "LD_PRELOAD") ||
30-
contains("log.message", "ld.so.conf")) &&
31-
(contains("log.message", "modified") || contains("log.message", "write") ||
32-
contains("log.message", "opened") || contains("log.message", "export") ||
33-
contains("log.message", "changed"))
34-
groupBy:
35-
- origin.host
36-
- origin.user
28+
(contains("origin.command", "ld.so.preload") || contains("origin.command", "LD_PRELOAD") || contains("origin.command", "ld.so.conf")) && regexMatch("origin.command", "(>>|tee|echo|sed |cp |mv )")
29+
deduplicateBy:
30+
- dataSource

rules/linux/debian_family/process_masquerading.yml

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Rule version v1.0.0
1+
# Rule version v1.0.1
22

33
dataTypes:
44
- linux
@@ -23,11 +23,6 @@ description: |
2323
5. If confirmed malicious, terminate the process and remove the binary
2424
6. Check for other masquerading processes on the system
2525
where: |
26-
(contains("log.message", "/proc/self/comm") ||
27-
contains("log.message", "/proc/self/exe") ||
28-
contains("log.message", "prctl") && contains("log.message", "PR_SET_NAME")) &&
29-
(contains("log.message", "write") || contains("log.message", "modified") ||
30-
contains("log.message", "open"))
31-
groupBy:
32-
- origin.host
33-
- origin.user
26+
regexMatch("log.execve.a0", "^\\[(kworker|kthreadd|ksoftirqd|migration|rcu_|kswapd|watchdog|kdevtmpfs|kauditd|kcompactd|kintegrityd|khugepaged|kblockd|kthrotld)")
27+
deduplicateBy:
28+
- dataSource

rules/linux/debian_family/reverse_shell_detection.yml

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Rule version v1.0.0
1+
# Rule version v1.0.1
22

33
dataTypes:
44
- linux
@@ -25,16 +25,6 @@ description: |
2525
6. Perform full incident response on the compromised host
2626
7. Block the C2 IP address at the network perimeter
2727
where: |
28-
regexMatch("log.message", "(?i)bash\\s+-i\\s+>&\\s+/dev/tcp/") ||
29-
regexMatch("log.message", "(?i)python[23]?\\s+-c\\s+.*socket.*connect") ||
30-
regexMatch("log.message", "(?i)nc\\s+(-e|--exec|-c)\\s+") ||
31-
regexMatch("log.message", "(?i)ncat\\s+(-e|--exec)\\s+") ||
32-
regexMatch("log.message", "(?i)socat\\s+.*exec.*tcp") ||
33-
regexMatch("log.message", "(?i)perl\\s+-e\\s+.*socket.*INET") ||
34-
regexMatch("log.message", "(?i)php\\s+-r\\s+.*fsockopen") ||
35-
regexMatch("log.message", "(?i)ruby\\s+-rsocket\\s+-e") ||
36-
regexMatch("log.message", "(?i)mkfifo\\s+.*nc\\s+") ||
37-
regexMatch("log.message", "(?i)\\b0<&\\d+-;exec\\s+\\d+<>/dev/tcp/")
38-
groupBy:
39-
- origin.host
40-
- origin.ip
28+
regexMatch("origin.command", "(bash -i.*/dev/tcp|python.* -c .*socket.*connect|nc .*-e|ncat .*-e|socat.*exec.*tcp|perl.*-e.*socket|php.*-r.*fsockopen|ruby.*-rsocket)")
29+
deduplicateBy:
30+
- dataSource

rules/linux/debian_family/shell_rc_file_modification.yml

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Rule version v1.0.0
1+
# Rule version v1.0.1
22

33
dataTypes:
44
- linux
@@ -23,12 +23,6 @@ description: |
2323
5. Review all shell RC files for the affected user and system-wide profiles
2424
6. Remove malicious entries and investigate the compromise vector
2525
where: |
26-
(contains("log.message", ".bashrc") || contains("log.message", ".bash_profile") ||
27-
contains("log.message", ".profile") || contains("log.message", "/etc/profile.d/") ||
28-
contains("log.message", ".zshrc") || contains("log.message", ".zprofile") ||
29-
contains("log.message", "/etc/bash.bashrc") || contains("log.message", "/etc/profile")) &&
30-
(contains("log.message", "modified") || contains("log.message", "opened for writing") ||
31-
contains("log.message", "write") || contains("log.message", "changed"))
32-
groupBy:
33-
- origin.host
34-
- origin.user
26+
regexMatch("origin.command", "(tee|>>|cp |sed |vi |vim |nano |echo).*(.bashrc|.bash_profile|.zshrc|.profile|/etc/profile)")
27+
deduplicateBy:
28+
- dataSource

rules/linux/debian_family/ssh_authorized_keys_modification.yml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Rule version v1.0.0
1+
# Rule version v1.0.1
22

33
dataTypes:
44
- linux
@@ -25,10 +25,6 @@ description: |
2525
6. Remove unauthorized keys and rotate affected credentials
2626
7. Monitor for subsequent SSH connections from unknown sources
2727
where: |
28-
(contains("log.message", "authorized_keys") || contains("log.message", "authorized_keys2")) &&
29-
(contains("log.message", "modified") || contains("log.message", "opened for writing") ||
30-
contains("log.message", "changed") || contains("log.process", "sshd") ||
31-
contains("log.message", ".ssh") && contains("log.message", "write"))
32-
groupBy:
33-
- origin.host
34-
- origin.user
28+
contains("origin.command", "authorized_keys")
29+
deduplicateBy:
30+
- dataSource

rules/linux/debian_family/ssh_tunneling_port_forwarding.yml

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Rule version v1.0.0
1+
# Rule version v1.0.1
22

33
dataTypes:
44
- linux
@@ -24,14 +24,6 @@ description: |
2424
5. If unauthorized, terminate the SSH session and block the connection
2525
6. Review SSH configuration to restrict port forwarding if not needed
2626
where: |
27-
contains("log.process", "sshd") &&
28-
(regexMatch("log.message", "(?i)ssh\\s+.*-[LRD]\\s+") ||
29-
contains("log.message", "port forwarding") ||
30-
contains("log.message", "Local forwarding") ||
31-
contains("log.message", "Remote forwarding") ||
32-
contains("log.message", "Dynamic forwarding") ||
33-
contains("log.message", "tunnel") ||
34-
regexMatch("log.message", "(?i)open forward.*port"))
35-
groupBy:
36-
- origin.host
37-
- origin.ip
27+
regexMatch("origin.command", "ssh .*-[LRD] ")
28+
deduplicateBy:
29+
- dataSource

0 commit comments

Comments
 (0)