diff --git a/TIER3-BRINGUP.md b/TIER3-BRINGUP.md index 12fa397..bac0a61 100644 --- a/TIER3-BRINGUP.md +++ b/TIER3-BRINGUP.md @@ -259,13 +259,70 @@ exploit fires, so Metasploit's handler is called and sessions open. --- +## Bug 14 — QEMU launch config incompatible with Metasploitable2 (boot hang) + +**Symptom:** Every `_wait_for_tcp` probe returns `b''` for the full timeout +(even after the Bug 10 fix). No service — FTP, Samba, distccd, IRC — ever +becomes reachable. The VM consumes CPU (QEMU runs) but nothing listens. + +**Root cause (three compounding issues in `launch_target.sh`):** + +1. `-drive if=virtio` presents the disk as `/dev/vda`. Metasploitable2's GRUB + was built for VMware SCSI (`/dev/sda`). Ubuntu 8.04's kernel command line + says `root=/dev/sda1`. The kernel can't mount root on `/dev/vda` → kernel + panic immediately after decompression. Services never start. + +2. `-machine q35` is a PCIe chipset (Sandy Bridge era). Old ISA-emulated + devices and BIOS assumptions in Ubuntu 8.04 break under q35. + +3. `-cpu host` exposes AVX/XSAVE and other modern CPU features. Linux 2.6.24 + doesn't know how to save/restore these in context switches; the kernel + freezes or mishandles the first SIMD operation during boot. + +**Fix:** Three changes in `vm/launch_target.sh`: +- `-machine q35` → `-machine pc` (i440fx, the classic PC compatible machine) +- `-drive if=virtio` → `-drive if=ide` (Ubuntu 8.04 libata presents this as + `/dev/sda`, matching the GRUB `root=` line) +- `-cpu host` (KVM) → `-cpu kvm32` (safe 32-bit KVM model, no exotic flags) +- `-device virtio-net-pci` → `-device e1000` (Intel e1000: universally + supported since Linux 2.2, in every kernel config Metasploitable2 uses) + +**Files:** `vm/launch_target.sh` + +--- + +## Bug 15 — Tier-3 verify uses vsftpd (bridge-only, always fails on SLIRP) + +**Symptom:** `install-tier-3-4.sh` verify step always fails. The vsftpd +module's backdoor opens port 6200 (hardcoded in the binary and the MSF +module). On SLIRP, all slots would need to share the same host port 6200, +which QEMU refuses. The verify is killed by `_wait_for_tcp` or by the exploit +itself never reaching a session. + +**Root cause:** The verify step was left on `vsftpd_234_backdoor` after Bug 5 +marked that module `requires_bridge = true`. The verify subprocess doesn't +have a bridge configured and doesn't set up the extra hostfwd for port 6200. + +**Fix:** Changed verify to `distccd_command_exec` with correct SLIRP port +mappings: `TARGET_PORTS="5632:3632,4444:4444"` and `--target-port 5632`. +distccd doesn't hardcode a backdoor port — the bind shell uses the +fleet-assigned `LPORT`. No bridge needed. + +**Files:** `scripts/install-tier-3-4.sh` + +--- + ## Net result after all fixes -With fixes 1–13 applied: +With fixes 1–15 applied: +- Metasploitable2 boots correctly under KVM (pc machine, kvm32 CPU, ide disk, + e1000 network). Services start ~60–70 s after QEMU launch. - `_wait_for_tcp` correctly waits until a service is genuinely listening (returns only on `socket.timeout` or non-empty banner data). -- `distccd_command_exec` and `unreal_ircd_3281_backdoor` are now available - on SLIRP-only runs; `samba_usermap_script` is removed. +- `distccd_command_exec` and `unreal_ircd_3281_backdoor` are admitted to the + module catalog; both are SLIRP-compatible with `cmd/unix/bind_perl`. +- `samba_usermap_script` removed from catalog (NoReply, sessions never open). - `msgpack.unpackb` accepts integer session ID keys without crashing. +- The verify step uses `distccd_command_exec` on SLIRP+hostfwd. - Sessions open, workloads execute, episodes complete with `session_open` events. diff --git a/manifest.toml b/manifest.toml index 10ed310..25835a8 100644 --- a/manifest.toml +++ b/manifest.toml @@ -110,14 +110,21 @@ netflow_bucket_ms = 100 # Every entry MUST carry `verified_against` and `last_verified`. The # absence of either drops the module from the active catalog. # -# Empty as of 2026-05-04: PIPELINE.md §3 found 0/67 session_open on -# samba_usermap_script against the SourceForge Metasploitable2 image, -# and no in-house verified target exists yet. §5 step 3 builds the -# target VM, step 4 re-admits modules with verification recorded. -# Until then, Tier-3 episodes do not run — the dataset is honest -# Tier-2 only. -[catalog] -modules = [] +# distccd and unreal_ircd admitted 2026-05-05 on elliott-thinkpad. +# Both use cmd/unix/bind_perl (host connects in via SLIRP hostfwd — +# no bridge egress). Unlike samba_usermap_script, these exploits return +# a valid protocol response after firing, so Metasploit's handler runs +# and session_open fires. Verified against the SourceForge Metasploitable2 +# image (sha256 a8c019c3...) with the QEMU fixes (Bug 14) applied. +[[catalog.modules]] +name = "distccd_command_exec" +verified_against = "metasploitable2-sourceforge-a8c019c3" +last_verified = "2026-05-05" + +[[catalog.modules]] +name = "unreal_ircd_3281_backdoor" +verified_against = "metasploitable2-sourceforge-a8c019c3" +last_verified = "2026-05-05" # --------------------------------------------------------------------- # [targets] — target VM images (§4.2) diff --git a/scripts/install-tier-3-4.sh b/scripts/install-tier-3-4.sh index 49dbc88..14b6014 100755 --- a/scripts/install-tier-3-4.sh +++ b/scripts/install-tier-3-4.sh @@ -91,17 +91,22 @@ else 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 (vsftpd_234_backdoor)" + 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 ! sudo -E -u cis490 "$PY" "$INSTALL_ROOT/tools/run_tier3_demo.py" \ - --module vsftpd_234_backdoor \ - --target-port 2021 \ + 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 diff --git a/vm/launch_target.sh b/vm/launch_target.sh index 055e881..2e9efcd 100755 --- a/vm/launch_target.sh +++ b/vm/launch_target.sh @@ -89,7 +89,10 @@ fi CPU_FLAGS=() if [[ "$ACCEL" == "kvm" ]]; then - CPU_FLAGS=(-cpu host) + # kvm32: safe 32-bit KVM model. -cpu host exposes XSAVE/AVX/etc. that + # Ubuntu 8.04's 2.6.24 kernel (Metasploitable2) can't handle, causing + # a boot hang before any services start. + CPU_FLAGS=(-cpu kvm32) fi AGENT_SOCK="$RUN_DIR/agent.sock" @@ -101,13 +104,13 @@ AGENT_SOCK="$RUN_DIR/agent.sock" # host-side collector simply gets no rows. Harmless. exec qemu-system-x86_64 \ -name cis490-target \ - -machine q35,accel="$ACCEL" \ + -machine pc,accel="$ACCEL" \ "${CPU_FLAGS[@]}" \ -smp 1,sockets=1,cores=1,threads=1 \ -m "$RAM_MIB" \ - -drive file="$IMAGE",format=qcow2,if=virtio,snapshot=on \ + -drive file="$IMAGE",format=qcow2,if=ide,snapshot=on \ -netdev "$NETDEV" \ - -device virtio-net-pci,netdev=n0 \ + -device e1000,netdev=n0 \ -device virtio-serial-pci,id=cis490vs0 \ -chardev socket,id=cis490agent,path="$AGENT_SOCK",server=on,wait=off \ -device virtserialport,chardev=cis490agent,name=cis490.guest.agent \