CIS490/scripts/install-tier-3-4.sh
Elliott Kolden b29d30a1b2 Tier-3: fix QEMU boot, catalog admission, verify module
Bug 14 (vm/launch_target.sh): Metasploitable2 requires -machine pc
(i440fx), -cpu kvm32, -drive if=ide, and -device e1000. The previous
config (-machine q35, -cpu host, -drive if=virtio, virtio-net-pci)
caused a kernel panic at boot because /dev/vda != the grub root=/dev/sda1.
Services never started; the b'' probe fix (Bug 10) then correctly waited
out the full timeout with no result.

Bug 15 (scripts/install-tier-3-4.sh): verify step used vsftpd_234_backdoor
which is requires_bridge=true and has a hardcoded port-6200 backdoor.
Changed to distccd_command_exec with TARGET_PORTS="5632:3632,4444:4444".

manifest.toml: admit distccd_command_exec and unreal_ircd_3281_backdoor
to the module catalog. Both use cmd/unix/bind_perl (bind shell, no guest
egress, SLIRP-safe). distccd returns a valid protocol response so MSF's
handler runs and session_open fires. Verified against Metasploitable2
sourceforge image sha256 a8c019c3.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 16:41:41 -06:00

178 lines
8.1 KiB
Bash
Executable file

#!/usr/bin/env bash
# Tier-3 + Tier-4 deploy orchestrator. Idempotent. ZERO operator
# interaction — including no API key, no signup, no manual upload.
#
# Steps (each idempotent on its own):
# 1. install-msfrpcd.sh — auto-install metasploit-framework via
# Rapid7 omnibus + drop systemd unit
# 2. fetch-metasploitable2.sh — pull the disk image from the
# SourceForge public mirror (TOFU)
# 3. setup_bridge.sh — bring up br-malware host-only bridge
# for callback-payload modules
# 4. Tier-3 verify — fire vsftpd_234_backdoor against the
# freshly-fetched VM, confirm session
# lands and an episode is recorded
# 5. Tier-4 deploy — clone theZoo (public security-research
# repo, no auth), extract one real
# binary per manifest family, stage at
# samples/store/<sha256>, rewrite
# manifest.toml in place. MANDATORY:
# the deploy fails if zero samples land.
#
# Inputs (env, all optional):
# SKIP_VERIFY — set to skip the live Tier-3 fire test
# SKIP_BRIDGE — set to skip bridge setup (limits to non-callback modules)
# SKIP_TIER4 — set to skip Tier-4 deploy entirely (DEPRECATED;
# leaves you with mimic-only data, defeats the project)
#
# Run as root from anywhere on the lab host. Sub-scripts handle their
# own root checks.
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
INSTALL_ROOT="${INSTALL_ROOT:-/opt/cis490}"
DATA_ROOT="${DATA_ROOT:-/var/lib/cis490}"
ETC_ROOT="${ETC_ROOT:-/etc/cis490}"
log() { printf '[install-tier-3-4] %s\n' "$*" >&2; }
die() { log "FATAL: $*"; exit 1; }
[[ $EUID -eq 0 ]] || die "must run as root"
# Resolve script paths — prefer $INSTALL_ROOT (production) over
# $REPO_ROOT (dev clone) so a re-run under systemd uses the same
# scripts the orchestrator does.
script_path() {
local name="$1"
if [[ -x "$INSTALL_ROOT/scripts/$name" ]]; then echo "$INSTALL_ROOT/scripts/$name"; return
elif [[ -x "$REPO_ROOT/scripts/$name" ]]; then echo "$REPO_ROOT/scripts/$name"; return
elif [[ -x "$INSTALL_ROOT/vm/$name" ]]; then echo "$INSTALL_ROOT/vm/$name"; return
elif [[ -x "$REPO_ROOT/vm/$name" ]]; then echo "$REPO_ROOT/vm/$name"; return
else die "$name not found in $INSTALL_ROOT or $REPO_ROOT"
fi
}
# --- 1. msfrpcd --------------------------------------------------------
log "[1/5] install metasploit-framework + msfrpcd unit"
"$(script_path install-msfrpcd.sh)"
if ! systemctl is-active --quiet cis490-msfrpcd; then
log "starting cis490-msfrpcd"
systemctl enable --now cis490-msfrpcd
fi
sleep 3
if ! ss -ltn 2>/dev/null | grep -q ':55553'; then
log "cis490-msfrpcd not listening on 127.0.0.1:55553 yet — waiting up to 30s"
for _ in $(seq 1 30); do
ss -ltn 2>/dev/null | grep -q ':55553' && break
sleep 1
done
fi
ss -ltn 2>/dev/null | grep -q ':55553' || \
die "msfrpcd never bound to :55553 — check 'journalctl -u cis490-msfrpcd'"
log "msfrpcd ✓"
# --- 2. metasploitable2 image ------------------------------------------
log "[2/5] fetch Metasploitable2 disk image"
OUT_DIR="$DATA_ROOT/vm/images"
install -d -m 0755 -o cis490 -g cis490 "$OUT_DIR"
OUT_DIR="$OUT_DIR" "$(script_path fetch-metasploitable2.sh)"
chown cis490:cis490 "$OUT_DIR/metasploitable2.qcow2" 2>/dev/null || true
log "metasploitable2.qcow2 ✓"
# --- 3. bridge ---------------------------------------------------------
if [[ -z "${SKIP_BRIDGE:-}" ]]; then
log "[3/5] bring up br-malware host-only bridge"
"$(script_path setup_bridge.sh)" || log "bridge setup failed (non-fatal); only non-callback modules will fire"
log "br-malware ✓"
else
log "[3/5] SKIP_BRIDGE set — limiting to non-callback modules"
fi
# --- 4. Tier-3 verify --------------------------------------------------
# Uses distccd_command_exec (SLIRP-safe bind_perl, no bridge required).
# vsftpd_234_backdoor hardcodes port 6200 which collides across SLIRP
# slots and requires the host-only bridge — not usable as a SLIRP verify.
# distccd: service on guest:3632 → host:5632; bind shell on guest:4444.
if [[ -z "${SKIP_VERIFY:-}" ]]; then
log "[4/5] verify Tier-3 fire (distccd_command_exec)"
set -a
# shellcheck disable=SC1091
. "$ETC_ROOT/msfrpc.env"
set +a
PY="$INSTALL_ROOT/.venv/bin/python"
[[ -x "$PY" ]] || PY="$(command -v python3)"
if ! TARGET_PORTS="5632:3632,4444:4444" PORT_BASE=5632 \
sudo -E -u cis490 "$PY" "$INSTALL_ROOT/tools/run_tier3_demo.py" \
--module distccd_command_exec \
--target-port 5632 \
--data-root "$DATA_ROOT/data" \
--target-boot-timeout 240 \
> /tmp/cis490-tier3-verify.log 2>&1; then
log "verify run failed — log at /tmp/cis490-tier3-verify.log; dumping last 30 lines:"
tail -30 /tmp/cis490-tier3-verify.log >&2 || true
die "Tier-3 fire failed"
fi
if grep -q '^episode_id = ' /tmp/cis490-tier3-verify.log; then
log "Tier-3 verified ✓ ($(grep '^episode_id = ' /tmp/cis490-tier3-verify.log))"
else
log "verify run finished but no episode_id seen — log at /tmp/cis490-tier3-verify.log"
fi
else
log "[4/5] SKIP_VERIFY set"
fi
# --- 5. Tier-4 deploy (MANDATORY, no auth required) --------------------
if [[ -n "${SKIP_TIER4:-}" ]]; then
log "[5/5] SKIP_TIER4 set — leaving this host on Tier 2/3 mimic-only."
log " This is NOT the recommended configuration; the project's"
log " training target is real-binary episodes."
else
log "[5/5] Tier-4 deploy (real malware fetch from theZoo — mandatory)"
command -v git >/dev/null || die "git not installed; need it to clone theZoo"
PY="$INSTALL_ROOT/.venv/bin/python"
[[ -x "$PY" ]] || PY="$(command -v python3)"
# theZoo clone lives on shared persistent storage so re-runs don't
# re-download. cis490 user owns it for periodic git pull.
THEZOO_DIR="${THEZOO_DIR:-/var/lib/cis490/theZoo}"
install -d -o cis490 -g cis490 -m 0755 "$(dirname "$THEZOO_DIR")"
if ! sudo -E -u cis490 "$PY" \
"$INSTALL_ROOT/tools/auto_fetch_samples.py" \
--thezoo-clone-dir "$THEZOO_DIR" \
> /tmp/cis490-tier4-deploy.log 2>&1; then
log "Tier-4 fetch failed — last 30 lines of /tmp/cis490-tier4-deploy.log:"
tail -30 /tmp/cis490-tier4-deploy.log >&2 || true
die "Tier-4 deploy failed; without real binaries this host produces only mimics"
fi
REAL_COUNT="$(ls "$INSTALL_ROOT/samples/store/" 2>/dev/null | wc -l)"
if [[ "$REAL_COUNT" -lt 1 ]]; then
log "auto_fetch_samples.py exited 0 but samples/store/ is empty — see /tmp/cis490-tier4-deploy.log"
tail -30 /tmp/cis490-tier4-deploy.log >&2 || true
die "Tier-4 deploy failed: no real binaries staged"
fi
log "Tier-4 ✓ ($REAL_COUNT real binaries staged in $INSTALL_ROOT/samples/store/)"
fi
# Restart the orchestrator now so the next wave actually runs Tier-3
# against the freshly-staged msfrpcd + samples. Skipped only if the
# unit isn't enabled yet (first install hasn't run `systemctl enable`).
if systemctl is-enabled --quiet cis490-orchestrator 2>/dev/null; then
log "restarting cis490-orchestrator to pick up new modules + samples"
systemctl restart cis490-orchestrator || \
log "WARN: orchestrator restart failed — check 'journalctl -u cis490-orchestrator'"
fi
log ""
log "================================================================="
log " Tier-3 deploy complete on $(hostname)"
log "================================================================="
log " - metasploit-framework + cis490-msfrpcd.service active"
log " - $OUT_DIR/metasploitable2.qcow2 staged"
log " - bridge: $(ip link show br-malware >/dev/null 2>&1 && echo up || echo skipped)"
log " - Tier-4: $(ls "$INSTALL_ROOT/samples/store/" 2>/dev/null | wc -l) real binaries staged"
log "================================================================="