Closes the "have you tested it" gap as much as we can without x86 KVM.
The Pi is ARM64 — can't boot Metasploitable2 or run KVM-accelerated
guests. But most of the Tier-3 chain doesn't need x86:
* chunked_real_binary_upload is just shell commands over a pipe
* exploit module TOMLs and the deterministic selector are pure Python
* manifest loading + sample selection are pure Python
* msfrpcd itself runs on ARM (Ruby + Java)
* the receiver's commit gate is the same on any arch
verify_tier3_local.py exercises each of those end-to-end, in process,
on this Pi:
PASS exploits/modules/*.toml parse + selector deterministic
PASS manifest loads + selector covers every sample
PASS chunked binary upload survives a real /bin/sh round-trip
(150 KB binary, 26 chunks, sha256-verified end to end)
PASS staged samples are Linux i386 ELF (when staged)
PASS msfrpcd round-trips core.version (when listening)
PASS receiver /v1/health + gate enforces commit allow-list
Live result on this Pi today: 5 PASS, 1 SKIP (msfrpcd not installed
on the Pi, which is correct — the Pi is the receiver, not a lab
host). When run on a lab host after install-tier-3-4.sh, all 6
PASS gives full Tier-3 readiness.
What this script does NOT verify (still needs x86 KVM on a lab
host, covered by install-tier-3-4.sh's verify step):
* Metasploitable2 boots under QEMU/KVM
* vsftpd_234_backdoor lands a session against it
* the chunked-upload binary actually executes inside that session
But the chunked-upload step proves every byte of the upload path
(printf '%s', heredoc-free path, base64 decode, sha256 verify,
chmod, exec scaffold) works against a real POSIX shell. An msfrpc
session presents the same shell interface, so a passing local-sh
test is strong evidence the production path will work.
tests/test_tier3_local_verify.py wraps the deterministic steps
(module parse, manifest, chunked upload) so pytest catches
regressions automatically. 174/174 total.
Operator workflow: ssh into Pi (or lab host), run:
/opt/cis490/.venv/bin/python tools/verify_tier3_local.py
Each step prints PASS/FAIL/SKIP with detail. Exit 1 if any FAIL.
41 lines
1.4 KiB
Python
41 lines
1.4 KiB
Python
"""Pytest wrapper around tools/verify_tier3_local.py.
|
|
|
|
The verifier is its own CLI for operators. The test wrapper just runs
|
|
the steps that are deterministic without external services so a
|
|
regression (e.g. someone breaking chunked_real_binary_upload) gets
|
|
caught by `pytest` without needing msfrpcd or a populated store.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parent.parent
|
|
spec = importlib.util.spec_from_file_location(
|
|
"verify_tier3_local", REPO_ROOT / "tools" / "verify_tier3_local.py"
|
|
)
|
|
v = importlib.util.module_from_spec(spec)
|
|
sys.modules["verify_tier3_local"] = v
|
|
spec.loader.exec_module(v)
|
|
|
|
|
|
def test_module_configs_parse() -> None:
|
|
s = v.step_module_configs_parse()
|
|
assert s.outcome == "PASS", f"{s.name}: {s.detail}"
|
|
|
|
|
|
def test_manifest_distribution() -> None:
|
|
s = v.step_manifest_distribution()
|
|
assert s.outcome == "PASS", f"{s.name}: {s.detail}"
|
|
|
|
|
|
def test_chunked_upload_through_real_sh(tmp_path) -> None:
|
|
"""The big one: chunked_real_binary_upload must survive a real
|
|
/bin/sh round-trip. This is what proves the Tier-4 binary upload
|
|
path will work against an msfrpc shell session — same wire shape,
|
|
same shell semantics."""
|
|
s = v.step_chunked_upload_via_local_sh(tmp_path)
|
|
assert s.outcome == "PASS", f"{s.name}: {s.detail}"
|