From dc2240d63574649d60408534663dac6368eecd79 Mon Sep 17 00:00:00 2001 From: igor04091968 Date: Thu, 21 May 2026 16:02:23 +0300 Subject: [PATCH] fix(hayabusa): close phase17 live production validation --- .../SUMMARY.md | 51 +++++++++++++++++++ aw-server/hayabusa/aw-hayabusa.sh | 18 +++++-- docs/runbook.md | 24 +++++++++ 3 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 .planning/phases/17-hayabusa-production-validation/SUMMARY.md diff --git a/.planning/phases/17-hayabusa-production-validation/SUMMARY.md b/.planning/phases/17-hayabusa-production-validation/SUMMARY.md new file mode 100644 index 0000000..a0aacf8 --- /dev/null +++ b/.planning/phases/17-hayabusa-production-validation/SUMMARY.md @@ -0,0 +1,51 @@ +# Phase 17 Summary: Production Validation + +## Result + +Phase 17 is closed. + +## What was proven live + +A real end-to-end forensic path was executed and closed on production infrastructure: + +1. Windows EVTX package was exported on `SHARKON2025`. +2. The real zip package was transferred to `10.10.10.13`. +3. `aw-hayabusa accept` and `aw-hayabusa process-inbox --mode incident` were run through the standard wrapper. +4. Hayabusa generated a real report set with bounded traceability metadata. +5. The result was linked back into AW-rus case management as bounded `forensics.hayabusa` metadata. + +## Live proof record + +- host: `SHARKON2025` +- case id: `30` +- intake id: `20260521T125653Z_SHARKON2025-phase17-rerun3` +- package path: `/opt/hayabusa/archive/packages/SHARKON2025/20260521T125653Z_SHARKON2025-phase17-rerun3.zip` +- sha256: `e86b9abbfc1d706ac706c6c8a89509ab17023344c50880641e9175f73f1198d4` +- report dir: `/opt/hayabusa/reports/SHARKON2025/20260521T125654Z_incident_20260521T125653Z_SHARKON2025-phase17-rerun3` +- report artifacts: + - `summary.html` + - `manifest.json` + - `run.log` + - `timeline.jsonl` + - `logon-summary-successful.csv` + - `logon-summary-failed.csv` + +## Production bugs found and fixed during validation + +- `aw-hayabusa` treated `unzip` warning return code `1` as a hard failure for Windows-created zip archives that use backslashes as path separators. +- timeline modes were using the wrong Hayabusa config path; the wrapper must pass `rules/config`, not the rules root. + +Both issues were fixed in `aw-server/hayabusa/aw-hayabusa.sh` and retested live against the same package. + +## Why this closes the phase + +- the path is no longer theoretical or docs-only; it was proven on a real Windows export package +- traceability from host to package to report directory is explicit +- AW-rus case linkage now stores bounded forensic metadata exactly as designed +- the remaining gaps are operational tuning items, not missing core implementation + +## Tuning backlog after the live run + +- keep at least one preserved sample EVTX zip for future regression reruns +- consider a self-check in `aw-hayabusa doctor` for `rules/config` completeness +- optionally persist a compact machine-readable proof manifest for future audits diff --git a/aw-server/hayabusa/aw-hayabusa.sh b/aw-server/hayabusa/aw-hayabusa.sh index 263d6dc..97e2d5d 100644 --- a/aw-server/hayabusa/aw-hayabusa.sh +++ b/aw-server/hayabusa/aw-hayabusa.sh @@ -5,6 +5,7 @@ HAYA_ROOT="${AW_HAYABUSA_ROOT:-/opt/hayabusa}" HAYA_CURRENT="${HAYA_ROOT}/current" HAYA_BIN="${HAYA_CURRENT}/hayabusa" HAYA_RULES="${HAYA_CURRENT}/rules" +HAYA_RULES_CONFIG="${HAYA_RULES}/config" HAYA_CONFIG="${HAYA_CURRENT}/config" HAYA_REPORTS_ROOT="${AW_HAYABUSA_REPORTS_ROOT:-${HAYA_ROOT}/reports}" HAYA_STATE_ROOT="${AW_HAYABUSA_STATE_ROOT:-${HAYA_ROOT}/state}" @@ -46,6 +47,7 @@ ensure_layout() { [ -x "${HAYA_BIN}" ] || fail "Hayabusa binary not found at ${HAYA_BIN}" [ -d "${HAYA_RULES}" ] || fail "Hayabusa rules directory not found at ${HAYA_RULES}" [ -d "${HAYA_CONFIG}" ] || fail "Hayabusa config directory not found at ${HAYA_CONFIG}" + [ -d "${HAYA_RULES_CONFIG}" ] || fail "Hayabusa rules config directory not found at ${HAYA_RULES_CONFIG}" mkdir -p \ "${HAYA_REPORTS_ROOT}" \ "${HAYA_STATE_ROOT}" \ @@ -223,7 +225,7 @@ run_mode() { local timeline_file="" local output_format="" local -a input_args=() - local -a common_args=("-w" "-q" "-C" "-r" "${HAYA_RULES}" "-c" "${HAYA_CONFIG}" "-O") + local -a common_args=("-w" "-q" "-C" "-r" "${HAYA_RULES}" "-O") local -a mode_args=() local -a command=() local -a logon_command=() @@ -244,19 +246,19 @@ run_mode() { timeline_file="${report_dir}/timeline.csv" output_format="csv" mode_args=("-E" "-P" "-m" "medium" "-o" "${timeline_file}" "-H" "${html_file}") - command=("${HAYA_BIN}" "csv-timeline" "${input_args[@]}" "${common_args[@]}" "${mode_args[@]}") + command=("${HAYA_BIN}" "csv-timeline" "${input_args[@]}" "${common_args[@]}" "-c" "${HAYA_RULES_CONFIG}" "${mode_args[@]}") ;; incident) timeline_file="${report_dir}/timeline.jsonl" output_format="jsonl" mode_args=("-L" "-m" "low" "-o" "${timeline_file}" "-H" "${html_file}") - command=("${HAYA_BIN}" "json-timeline" "${input_args[@]}" "${common_args[@]}" "${mode_args[@]}") + command=("${HAYA_BIN}" "json-timeline" "${input_args[@]}" "${common_args[@]}" "-c" "${HAYA_RULES_CONFIG}" "${mode_args[@]}") ;; full) timeline_file="${report_dir}/timeline.jsonl" output_format="jsonl" mode_args=("-L" "-A" "-D" "-n" "-u" "-m" "informational" "-o" "${timeline_file}" "-H" "${html_file}") - command=("${HAYA_BIN}" "json-timeline" "${input_args[@]}" "${common_args[@]}" "${mode_args[@]}") + command=("${HAYA_BIN}" "json-timeline" "${input_args[@]}" "${common_args[@]}" "-c" "${HAYA_RULES_CONFIG}" "${mode_args[@]}") ;; *) fail "Unsupported mode: ${mode}" @@ -378,7 +380,14 @@ process_one_package() { mkdir -p "${stage_dir}" package_sha256="$(sha256sum "${package_path}" | awk '{print $1}')" + local unzip_rc=0 + set +e unzip -q -o "${package_path}" -d "${stage_dir}" + unzip_rc=$? + set -e + if [ "${unzip_rc}" -gt 1 ]; then + fail "unzip failed for ${package_path} with rc=${unzip_rc}" + fi local manifest_path host evtx_root archive_pkg_dir archive_pkg_path archive_extract_dir status report_dir manifest_path="$(find_manifest_path "${stage_dir}")" @@ -476,6 +485,7 @@ main() { echo "binary=${HAYA_BIN}" echo "rules=${HAYA_RULES}" echo "config=${HAYA_CONFIG}" + echo "rules_config=${HAYA_RULES_CONFIG}" echo "reports=${HAYA_REPORTS_ROOT}" echo "state=${HAYA_STATE_ROOT}" echo "incoming=${HAYA_INCOMING_DIR}" diff --git a/docs/runbook.md b/docs/runbook.md index e9ef835..8efee5f 100755 --- a/docs/runbook.md +++ b/docs/runbook.md @@ -203,6 +203,30 @@ Acceptance для этого сценария: - артефакты трассируются от `HOST` до `report_dir`; - follow-up не тащит сырые forensic данные в обычные AW buckets. +Known-good live proof `2026-05-21`: + +- `host=SHARKON2025` +- `case_id=30` +- `intake_id=20260521T125653Z_SHARKON2025-phase17-rerun3` +- `sha256=e86b9abbfc1d706ac706c6c8a89509ab17023344c50880641e9175f73f1198d4` +- `report_dir=/opt/hayabusa/reports/SHARKON2025/20260521T125654Z_incident_20260521T125653Z_SHARKON2025-phase17-rerun3` +- `latest-intake.json` status: `ok` +- AW-rus case linkage stored under `forensics.hayabusa` + +Что реально нашли в production validation: + +- Windows zip с backslash path separators давал `unzip` warning rc=1; wrapper не должен валить intake на таком предупреждении. +- timeline режимы должны использовать `rules/config`, а не корень rules directory. + +После live proof держать как regression checks: + +```bash +aw-hayabusa doctor +aw-hayabusa inventory +cat /opt/hayabusa/state/latest-intake.json +readlink -f /opt/hayabusa/state/latest-run +``` + ### DLP не виден в вебе Быстрый чек сервера: