haadi@portfolio:~$ cat wazuh-privilege-escalation-rules.md
Security research · Detection engineering
Detecting Linux privilege escalation with custom Wazuhrules
Three rules for sudo abuse the default ruleset doesn't cover, how each was tuned against false positives, tested against a real simulated attack, and mapped to ATT&CK.
Three custom rules covering common ways a Linux account gets escalated sudo access, none of which are meaningfully covered by Wazuh's default ruleset on their own.
All three build on existing default rules using <if_sid> /
<if_matched_sid> rather than parsing raw log lines from scratch: see
local_rules.xml for the full definitions.
The rules
| Rule ID | Scenario | Built on | Level | MITRE ATT&CK |
|---|---|---|---|---|
100101 | Multiple failed sudo authentication attempts | Default rule 5401 + frequency=2, timeframe=60 | 12 | T1548.003 |
100102 | User added to the sudo group | Default rule 5402 + match on usermod -aG sudo | 12 | T1098 |
100103 | Unauthorized user attempted to use sudo | Default rule 5405 | 11 | T1548.003 |
Why these three
A single failed sudo attempt is normal: everyone mistypes a password. A single unauthorized sudo attempt from an account that was never given access is not. The tuning on each rule reflects that difference:
- 100101 requires the failure to repeat twice within 60 seconds before firing, so it catches a brute-force pattern without alerting on every typo.
- 100102 is scoped to the exact
usermod -aG sudocommand rather than any group change, since group modifications happen for all kinds of harmless reasons (docker,www-data, etc.). - 100103 has no frequency requirement at all: a denied sudo attempt from an account with no sudo access is inherently suspicious on the first try, so waiting for repetition would only slow detection down.
Installing
# Copy into Wazuh's local rules file (custom rules go here, not the
# default rule files, so they survive a Wazuh update)
sudo cp local_rules.xml /var/ossec/etc/rules/local_rules.xml
# Restart the manager to load the new rules
sudo systemctl restart wazuh-manager
Testing
Each rule was verified against a real simulated attack on a throwaway Linux account. Commands used and expected results:
100101: repeated failed sudo auth
su - testuser
sudo ls # enter wrong password
sudo ls # enter wrong password again within 60s
Expect: alert on Rule 100101, Level 12.
100102: user added to sudo group
sudo adduser employee3
sudo usermod -aG sudo employee3
Expect: alert on Rule 100102, Level 12.
100103: unauthorized sudo attempt
sudo adduser guest1
su - guest1
sudo ls # guest1 is not in sudoers
Expect: alert on Rule 100103, Level 11.
Screenshots of each detection are in
../screenshots/custom-detection-rules/.
Notes · things that tripped me up
- Rule
100102didn't fire on the first attempt: the match condition was checking a slightly different field than the one the default decoder actually populates. Pulling the raw decoded event for a manual test and reading the actual field name fixed it. - Rule
100101's timing needs the two failed attempts close together: if the gap between them is longer than thetimeframe, Wazuh treats them as two unrelated single events instead of one pattern.
Originally published on GitHub
view-source