Upload files to "configs"
This commit is contained in:
@@ -0,0 +1,421 @@
|
||||
<!-- Local rules -->
|
||||
<!-- Modify it at your will. -->
|
||||
<!-- Copyright (C) 2015, Wazuh Inc. -->
|
||||
|
||||
<!--
|
||||
================================================================
|
||||
Local rules for Wittenberger.us Homelab and CyberForce prep
|
||||
|
||||
Rule ID ranges:
|
||||
87699-87762 pfSense (overrides shipped IDs, needed for
|
||||
wrapped-log correlation)
|
||||
100000-100099 SSH
|
||||
100100-100199 Attack / reputation lookups
|
||||
100200-100299 Dovecot (mailcow noise suppression + recon)
|
||||
100300-100399 Postfix / mail correlation
|
||||
100400-100499 Gitea
|
||||
100500-100599 (reserved)
|
||||
|
||||
Deploy procedure:
|
||||
1. sudo cp local_rules.xml /var/ossec/etc/rules/
|
||||
2. sudo /var/ossec/bin/wazuh-analysisd -t
|
||||
3. sudo systemctl restart wazuh-manager
|
||||
|
||||
Author: Chris Berger
|
||||
Last updated: 2026-07-31
|
||||
================================================================
|
||||
-->
|
||||
|
||||
|
||||
<!--
|
||||
================================================================
|
||||
SSH: authentication and login events
|
||||
Range: 100000-100099
|
||||
================================================================
|
||||
-->
|
||||
<group name="local,syslog,sshd,">
|
||||
|
||||
<!-- 100001: example SSH failure rule (placeholder, from shipped local_rules.xml)
|
||||
Sample log: Dec 10 01:02:02 host sshd[1234]: Failed none for root from 1.1.1.1 port 1066 ssh2 -->
|
||||
<rule id="100001" level="5">
|
||||
<if_sid>5716</if_sid>
|
||||
<srcip>1.1.1.1</srcip>
|
||||
<description>sshd: authentication failed from IP 1.1.1.1.</description>
|
||||
<group>authentication_failed,pci_dss_10.2.4,pci_dss_10.2.5,</group>
|
||||
</rule>
|
||||
|
||||
</group>
|
||||
|
||||
|
||||
<!--
|
||||
================================================================
|
||||
pfSense: firewall drop correlation
|
||||
Range: 87699-87762 (overrides shipped IDs)
|
||||
|
||||
These rules extend Wazuh's shipped pfSense correlation to work
|
||||
with the wrapped log format arriving from the homelab pfSense
|
||||
box. Require the pfsense-wrapped decoder chain in
|
||||
local_decoder.xml.
|
||||
================================================================
|
||||
-->
|
||||
<group name="local,pfsense,firewall,">
|
||||
|
||||
<!-- 87699: bridge rule - makes pfsense-wrapped decoder trigger the pfSense rule chain -->
|
||||
<rule id="87699" level="0">
|
||||
<decoded_as>pfsense-wrapped</decoded_as>
|
||||
<description>pfSense wrapped syslog parent rule.</description>
|
||||
</rule>
|
||||
|
||||
<!-- 87761: individual firewall block event (any action=block) -->
|
||||
<rule id="87761" level="5">
|
||||
<if_sid>87699</if_sid>
|
||||
<action>block</action>
|
||||
<description>pfSense firewall drop event (wrapped).</description>
|
||||
<group>pfsense,firewall_block,pci_dss_1.4,gpg13_4.12,hipaa_164.312.a.1,nist_800_53_SC.7,tsc_CC6.7,tsc_CC6.8,</group>
|
||||
</rule>
|
||||
|
||||
<!-- 87762: brute force / scan correlation (18 blocks in 45s from same source, then ignore that source for 4min) -->
|
||||
<rule id="87762" level="10" frequency="18" timeframe="45" ignore="240">
|
||||
<if_matched_sid>87761</if_matched_sid>
|
||||
<same_srcip />
|
||||
<description>Multiple pfSense firewall block events from same source (wrapped).</description>
|
||||
<mitre>
|
||||
<id>T1110</id>
|
||||
</mitre>
|
||||
<group>pfsense,</group>
|
||||
</rule>
|
||||
|
||||
</group>
|
||||
|
||||
|
||||
<!--
|
||||
================================================================
|
||||
Attack / reputation lookups
|
||||
Range: 100100-100199
|
||||
|
||||
IP reputation matches against external threat intel feeds.
|
||||
Requires CDB lists in /var/ossec/etc/lists/ maintained via
|
||||
wazuh-makelists.
|
||||
================================================================
|
||||
-->
|
||||
<group name="attack,">
|
||||
|
||||
<!-- 100100: AlienVault OTX blacklist match on any web/attack event -->
|
||||
<rule id="100100" level="10">
|
||||
<if_group>web|attack|attacks</if_group>
|
||||
<list field="srcip" lookup="address_match_key">etc/lists/blacklist-alienvault</list>
|
||||
<description>IP address found in AlienVault reputation database.</description>
|
||||
</rule>
|
||||
|
||||
</group>
|
||||
|
||||
|
||||
<!--
|
||||
================================================================
|
||||
Dovecot: mailcow noise suppression and reconnaissance detection
|
||||
Range: 100200-100299
|
||||
|
||||
Suppression rules (100200-100203) prevent expected mailcow
|
||||
internal traffic (watchdog, health checks, own-mailbox polling)
|
||||
from creating alert noise.
|
||||
|
||||
Recon detection (100205-100206) catches port scanning against
|
||||
IMAP/POP3/managesieve endpoints - the "no auth attempts"
|
||||
signature that separates scanning from actual attacks.
|
||||
================================================================
|
||||
-->
|
||||
<group name="dovecot,local,">
|
||||
|
||||
<!-- 100200: mailcow watchdog auth attempts against watchdog@invalid - suppress -->
|
||||
<rule id="100200" level="0">
|
||||
<if_sid>9705</if_sid>
|
||||
<match>watchdog@invalid</match>
|
||||
<description>Dovecot: mailcow watchdog health check (ignored)</description>
|
||||
</rule>
|
||||
|
||||
<!-- 100201: Docker internal IMAP probe disconnects (172.22.1.x range) - suppress -->
|
||||
<rule id="100201" level="0">
|
||||
<if_sid>9707</if_sid>
|
||||
<match>rip=172.22.1.</match>
|
||||
<description>Dovecot: mailcow watchdog IMAP probe disconnect (ignored)</description>
|
||||
</rule>
|
||||
|
||||
<!-- 100202: administrator's own mailbox routine disconnects - suppress -->
|
||||
<rule id="100202" level="0">
|
||||
<if_sid>9706</if_sid>
|
||||
<match>imap(chris@wittenberger.us)</match>
|
||||
<description>Dovecot: own-mailbox routine session disconnect (ignored)</description>
|
||||
</rule>
|
||||
|
||||
<!-- 100203: managesieve health check disconnects (no auth attempts) - suppress -->
|
||||
<rule id="100203" level="0">
|
||||
<if_sid>9706</if_sid>
|
||||
<match>managesieve-login: Disconnected: Connection closed (no auth attempts</match>
|
||||
<description>Mailcow watchdog managesieve healthcheck - suppressed</description>
|
||||
</rule>
|
||||
|
||||
<!-- 100205: no-auth disconnect primitive
|
||||
Level 0 - individual events silent, correlation happens in 100206 -->
|
||||
<rule id="100205" level="0">
|
||||
<if_sid>9700</if_sid>
|
||||
<match>no auth attempts</match>
|
||||
<description>Dovecot: connection with no auth attempt from $(srcip)</description>
|
||||
<group>dovecot,recon,</group>
|
||||
</rule>
|
||||
|
||||
<!-- 100206: aggressive port scanning
|
||||
Fires when a single source triggers 20 no-auth disconnects
|
||||
within 5 minutes. Separates one-off scanners (Shodan, Censys)
|
||||
from active reconnaissance sessions. -->
|
||||
<rule id="100206" level="8" frequency="20" timeframe="300">
|
||||
<if_matched_sid>100205</if_matched_sid>
|
||||
<same_srcip />
|
||||
<description>Dovecot: aggressive port scanning from $(srcip) - possible attack precursor</description>
|
||||
<group>dovecot,recon,attack,</group>
|
||||
</rule>
|
||||
|
||||
</group>
|
||||
|
||||
|
||||
<!--
|
||||
================================================================
|
||||
Dovecot: successful login primitive (do not delete)
|
||||
Range: 100204
|
||||
|
||||
Rule 100204 is intentionally suppressed (level 0) but MUST
|
||||
continue to fire when 9701 matches. Rule 100311 (mail
|
||||
compromise correlation) uses <if_sid>100204</if_sid> to detect
|
||||
successful logins after brute force.
|
||||
================================================================
|
||||
-->
|
||||
<group name="dovecot,authentication_success,">
|
||||
|
||||
<!-- 100204: successful Dovecot login - suppressed alert, still fires for correlation -->
|
||||
<rule id="100204" level="0" overwrite="no">
|
||||
<if_sid>9701</if_sid>
|
||||
<description>Dovecot successful login - suppressed (routine IMAP polling)</description>
|
||||
</rule>
|
||||
|
||||
</group>
|
||||
|
||||
|
||||
<!--
|
||||
================================================================
|
||||
Gitea: authentication, account lifecycle, and repository events
|
||||
Range: 100400-100499
|
||||
|
||||
Rule map:
|
||||
100400 Gitea event (parent, level 0)
|
||||
100401 router polling - suppressed
|
||||
100402 router completed request - suppressed
|
||||
100410 failed authentication attempt
|
||||
100411 brute force (5+ failures in 2min)
|
||||
100420 new user created
|
||||
100421 user deleted
|
||||
100430 SSH key added
|
||||
100431 SSH key deleted
|
||||
100440 access token activity
|
||||
100450 password reset / recovery
|
||||
100460 repository deleted
|
||||
100470 2FA event
|
||||
|
||||
All rules chain off the gitea decoder (see local_decoder.xml).
|
||||
================================================================
|
||||
-->
|
||||
<group name="gitea,">
|
||||
|
||||
<!-- 100400: parent rule - any Gitea event, gates all children -->
|
||||
<rule id="100400" level="0">
|
||||
<decoded_as>gitea</decoded_as>
|
||||
<description>Gitea event (parent)</description>
|
||||
</rule>
|
||||
|
||||
<!-- 100401, 100402: suppress high-volume HTTP request logs -->
|
||||
<rule id="100401" level="0">
|
||||
<if_sid>100400</if_sid>
|
||||
<match>router: polling</match>
|
||||
<description>Gitea: router polling - suppressed</description>
|
||||
</rule>
|
||||
|
||||
<rule id="100402" level="0">
|
||||
<if_sid>100400</if_sid>
|
||||
<match>router: completed</match>
|
||||
<description>Gitea: router completed request - suppressed</description>
|
||||
</rule>
|
||||
|
||||
<!-- 100410: individual failed login -->
|
||||
<rule id="100410" level="5">
|
||||
<if_sid>100400</if_sid>
|
||||
<match>Failed authentication attempt</match>
|
||||
<description>Gitea: failed authentication attempt</description>
|
||||
<group>authentication_failed,</group>
|
||||
<mitre>
|
||||
<id>T1110</id>
|
||||
</mitre>
|
||||
</rule>
|
||||
|
||||
<!-- 100411: brute force - 5+ failed logins in 2 minutes -->
|
||||
<rule id="100411" level="10" frequency="5" timeframe="120">
|
||||
<if_matched_sid>100410</if_matched_sid>
|
||||
<description>Gitea: possible brute force (5+ failed logins in 2 min)</description>
|
||||
<group>authentication_failures,</group>
|
||||
<mitre>
|
||||
<id>T1110</id>
|
||||
</mitre>
|
||||
</rule>
|
||||
|
||||
<!-- 100420, 100421: account lifecycle -->
|
||||
<rule id="100420" level="5">
|
||||
<if_sid>100400</if_sid>
|
||||
<match>new user signed up|created user</match>
|
||||
<description>Gitea: new user account created</description>
|
||||
</rule>
|
||||
|
||||
<rule id="100421" level="7">
|
||||
<if_sid>100400</if_sid>
|
||||
<match>deleted user|DeleteUser</match>
|
||||
<description>Gitea: user account deleted</description>
|
||||
</rule>
|
||||
|
||||
<!-- 100430, 100431: SSH key management (grants repo access - worth monitoring) -->
|
||||
<rule id="100430" level="5">
|
||||
<if_sid>100400</if_sid>
|
||||
<match>add public key|added SSH key|AddPublicKey</match>
|
||||
<description>Gitea: SSH key added to account</description>
|
||||
</rule>
|
||||
|
||||
<rule id="100431" level="3">
|
||||
<if_sid>100400</if_sid>
|
||||
<match>delete public key|deleted SSH key|DeletePublicKey</match>
|
||||
<description>Gitea: SSH key removed from account</description>
|
||||
</rule>
|
||||
|
||||
<!-- 100440: access token activity (alternate auth for Gitea) -->
|
||||
<rule id="100440" level="5">
|
||||
<if_sid>100400</if_sid>
|
||||
<match>access token|AccessToken</match>
|
||||
<description>Gitea: access token activity</description>
|
||||
</rule>
|
||||
|
||||
<!-- 100450: password reset / recovery flows -->
|
||||
<rule id="100450" level="5">
|
||||
<if_sid>100400</if_sid>
|
||||
<match>ResetPasswd|recover_account</match>
|
||||
<description>Gitea: password reset / account recovery</description>
|
||||
</rule>
|
||||
|
||||
<!-- 100460: repository deletion (destructive, higher severity) -->
|
||||
<rule id="100460" level="7">
|
||||
<if_sid>100400</if_sid>
|
||||
<match>repository deleted|DeleteRepository</match>
|
||||
<description>Gitea: repository deleted</description>
|
||||
</rule>
|
||||
|
||||
<!-- 100470: 2FA state changes -->
|
||||
<rule id="100470" level="5">
|
||||
<if_sid>100400</if_sid>
|
||||
<match>TwoFactor|two-factor|TOTP</match>
|
||||
<description>Gitea: 2FA event</description>
|
||||
</rule>
|
||||
|
||||
</group>
|
||||
|
||||
|
||||
<!--
|
||||
================================================================
|
||||
Postfix / mail: brute force and compromise correlation
|
||||
Range: 100300-100399
|
||||
|
||||
All rules depend on the mailcow-postfix-sasl-fail decoder for
|
||||
srcip, src_subnet, and dstuser extraction (see local_decoder.xml).
|
||||
|
||||
Rule 100311 also requires rule 100204 (Dovecot success suppressed
|
||||
alert) to detect successful logins after brute force.
|
||||
|
||||
Rule map by attack shape:
|
||||
100310 Single-IP brute force (same_srcip)
|
||||
100311 Compromise - success after brute force from same IP
|
||||
100312 Distributed against one user (same_user, different_srcip)
|
||||
100313 Persistent single-source (100310 3x in 24h)
|
||||
100314 Subnet coordination (same_field src_subnet, 15/hour)
|
||||
100315 Confirmed credential stuffing (same_user, 10 IPs, 10min)
|
||||
100316 Volume alarm (50 failures/hour, no source correlation)
|
||||
================================================================
|
||||
-->
|
||||
<group name="local,mail,postfix,">
|
||||
|
||||
<!-- 100310: single-source brute force
|
||||
5 SASL failures from same IP within 2 minutes -->
|
||||
<rule id="100310" level="10" frequency="5" timeframe="120">
|
||||
<if_matched_sid>3332</if_matched_sid>
|
||||
<same_srcip />
|
||||
<description>Postfix SASL: brute force login attempt from $(srcip)</description>
|
||||
<group>authentication_failed,brute_force,</group>
|
||||
</rule>
|
||||
|
||||
<!-- 100311: account compromise
|
||||
Successful Dovecot login (100204) from same IP that just
|
||||
triggered brute force (100310), within 2 minutes -->
|
||||
<rule id="100311" level="14" timeframe="120">
|
||||
<if_matched_sid>100310</if_matched_sid>
|
||||
<if_sid>100204</if_sid>
|
||||
<same_srcip />
|
||||
<description>Mail: successful login after brute force from $(srcip) - ACCOUNT COMPROMISED</description>
|
||||
<group>authentication_success,brute_force_success,attack,</group>
|
||||
</rule>
|
||||
|
||||
<!-- 100312: distributed brute force against one user
|
||||
5 failures targeting same username from different IPs in 5min.
|
||||
Catches credential stuffing that rotates IPs to evade
|
||||
same_srcip rules. -->
|
||||
<rule id="100312" level="10" frequency="5" timeframe="300">
|
||||
<if_matched_sid>3332</if_matched_sid>
|
||||
<same_user />
|
||||
<different_srcip />
|
||||
<description>Postfix SASL: distributed brute force targeting user $(dstuser)</description>
|
||||
<group>authentication_failed,brute_force,distributed,</group>
|
||||
</rule>
|
||||
|
||||
<!-- 100313: persistent single-source brute force
|
||||
Same IP triggers 100310 three or more times in 24 hours.
|
||||
Confirms an ongoing adversary rather than a one-off scan. -->
|
||||
<rule id="100313" level="12" frequency="3" timeframe="86400">
|
||||
<if_matched_sid>100310</if_matched_sid>
|
||||
<same_srcip />
|
||||
<description>Postfix SASL: persistent brute force from $(srcip) - 3+ bursts in 24h</description>
|
||||
<group>authentication_failed,brute_force,persistent,</group>
|
||||
</rule>
|
||||
|
||||
<!-- 100314: subnet-coordinated brute force
|
||||
15+ failures from same /24 subnet within 1 hour.
|
||||
Catches botnets rotating through hosting provider ranges.
|
||||
Requires src_subnet field from mailcow-postfix-sasl-fail. -->
|
||||
<rule id="100314" level="12" frequency="15" timeframe="3600">
|
||||
<if_matched_sid>3332</if_matched_sid>
|
||||
<same_field>src_subnet</same_field>
|
||||
<description>Postfix SASL: coordinated brute force from subnet $(src_subnet).0/24</description>
|
||||
<group>authentication_failed,brute_force,subnet_scan,</group>
|
||||
</rule>
|
||||
|
||||
<!-- 100315: confirmed credential stuffing
|
||||
Higher-confidence version of 100312. 10 attempts against
|
||||
same user from 10 different IPs in 10 minutes. Very low
|
||||
false positive rate. -->
|
||||
<rule id="100315" level="10" frequency="10" timeframe="600">
|
||||
<if_matched_sid>3332</if_matched_sid>
|
||||
<same_user />
|
||||
<different_srcip />
|
||||
<description>Postfix SASL: credential stuffing against user $(dstuser) from multiple IPs</description>
|
||||
<group>authentication_failed,brute_force,distributed,credential_stuffing,</group>
|
||||
</rule>
|
||||
|
||||
<!-- 100316: high volume attack detection
|
||||
50 SASL failures in 1 hour regardless of source or target.
|
||||
Catches attacks that rotate BOTH IPs and usernames. -->
|
||||
<rule id="100316" level="8" frequency="50" timeframe="3600">
|
||||
<if_matched_sid>3332</if_matched_sid>
|
||||
<description>Postfix SASL: high volume of authentication failures (50+ in 1h)</description>
|
||||
<group>authentication_failed,brute_force,volume,</group>
|
||||
</rule>
|
||||
|
||||
</group>
|
||||
Reference in New Issue
Block a user