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>
This commit is contained in:
parent
b73f5559dc
commit
b29d30a1b2
4 changed files with 91 additions and 19 deletions
|
|
@ -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
|
## 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
|
- `_wait_for_tcp` correctly waits until a service is genuinely listening
|
||||||
(returns only on `socket.timeout` or non-empty banner data).
|
(returns only on `socket.timeout` or non-empty banner data).
|
||||||
- `distccd_command_exec` and `unreal_ircd_3281_backdoor` are now available
|
- `distccd_command_exec` and `unreal_ircd_3281_backdoor` are admitted to the
|
||||||
on SLIRP-only runs; `samba_usermap_script` is removed.
|
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.
|
- `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`
|
- Sessions open, workloads execute, episodes complete with `session_open`
|
||||||
events.
|
events.
|
||||||
|
|
|
||||||
|
|
@ -110,14 +110,21 @@ netflow_bucket_ms = 100
|
||||||
# Every entry MUST carry `verified_against` and `last_verified`. The
|
# Every entry MUST carry `verified_against` and `last_verified`. The
|
||||||
# absence of either drops the module from the active catalog.
|
# 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
|
# distccd and unreal_ircd admitted 2026-05-05 on elliott-thinkpad.
|
||||||
# samba_usermap_script against the SourceForge Metasploitable2 image,
|
# Both use cmd/unix/bind_perl (host connects in via SLIRP hostfwd —
|
||||||
# and no in-house verified target exists yet. §5 step 3 builds the
|
# no bridge egress). Unlike samba_usermap_script, these exploits return
|
||||||
# target VM, step 4 re-admits modules with verification recorded.
|
# a valid protocol response after firing, so Metasploit's handler runs
|
||||||
# Until then, Tier-3 episodes do not run — the dataset is honest
|
# and session_open fires. Verified against the SourceForge Metasploitable2
|
||||||
# Tier-2 only.
|
# image (sha256 a8c019c3...) with the QEMU fixes (Bug 14) applied.
|
||||||
[catalog]
|
[[catalog.modules]]
|
||||||
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)
|
# [targets] — target VM images (§4.2)
|
||||||
|
|
|
||||||
|
|
@ -91,17 +91,22 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --- 4. Tier-3 verify --------------------------------------------------
|
# --- 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
|
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
|
set -a
|
||||||
# shellcheck disable=SC1091
|
# shellcheck disable=SC1091
|
||||||
. "$ETC_ROOT/msfrpc.env"
|
. "$ETC_ROOT/msfrpc.env"
|
||||||
set +a
|
set +a
|
||||||
PY="$INSTALL_ROOT/.venv/bin/python"
|
PY="$INSTALL_ROOT/.venv/bin/python"
|
||||||
[[ -x "$PY" ]] || PY="$(command -v python3)"
|
[[ -x "$PY" ]] || PY="$(command -v python3)"
|
||||||
if ! sudo -E -u cis490 "$PY" "$INSTALL_ROOT/tools/run_tier3_demo.py" \
|
if ! TARGET_PORTS="5632:3632,4444:4444" PORT_BASE=5632 \
|
||||||
--module vsftpd_234_backdoor \
|
sudo -E -u cis490 "$PY" "$INSTALL_ROOT/tools/run_tier3_demo.py" \
|
||||||
--target-port 2021 \
|
--module distccd_command_exec \
|
||||||
|
--target-port 5632 \
|
||||||
--data-root "$DATA_ROOT/data" \
|
--data-root "$DATA_ROOT/data" \
|
||||||
--target-boot-timeout 240 \
|
--target-boot-timeout 240 \
|
||||||
> /tmp/cis490-tier3-verify.log 2>&1; then
|
> /tmp/cis490-tier3-verify.log 2>&1; then
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,10 @@ fi
|
||||||
|
|
||||||
CPU_FLAGS=()
|
CPU_FLAGS=()
|
||||||
if [[ "$ACCEL" == "kvm" ]]; then
|
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
|
fi
|
||||||
|
|
||||||
AGENT_SOCK="$RUN_DIR/agent.sock"
|
AGENT_SOCK="$RUN_DIR/agent.sock"
|
||||||
|
|
@ -101,13 +104,13 @@ AGENT_SOCK="$RUN_DIR/agent.sock"
|
||||||
# host-side collector simply gets no rows. Harmless.
|
# host-side collector simply gets no rows. Harmless.
|
||||||
exec qemu-system-x86_64 \
|
exec qemu-system-x86_64 \
|
||||||
-name cis490-target \
|
-name cis490-target \
|
||||||
-machine q35,accel="$ACCEL" \
|
-machine pc,accel="$ACCEL" \
|
||||||
"${CPU_FLAGS[@]}" \
|
"${CPU_FLAGS[@]}" \
|
||||||
-smp 1,sockets=1,cores=1,threads=1 \
|
-smp 1,sockets=1,cores=1,threads=1 \
|
||||||
-m "$RAM_MIB" \
|
-m "$RAM_MIB" \
|
||||||
-drive file="$IMAGE",format=qcow2,if=virtio,snapshot=on \
|
-drive file="$IMAGE",format=qcow2,if=ide,snapshot=on \
|
||||||
-netdev "$NETDEV" \
|
-netdev "$NETDEV" \
|
||||||
-device virtio-net-pci,netdev=n0 \
|
-device e1000,netdev=n0 \
|
||||||
-device virtio-serial-pci,id=cis490vs0 \
|
-device virtio-serial-pci,id=cis490vs0 \
|
||||||
-chardev socket,id=cis490agent,path="$AGENT_SOCK",server=on,wait=off \
|
-chardev socket,id=cis490agent,path="$AGENT_SOCK",server=on,wait=off \
|
||||||
-device virtserialport,chardev=cis490agent,name=cis490.guest.agent \
|
-device virtserialport,chardev=cis490agent,name=cis490.guest.agent \
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue