From c654a6d17eb58adbb15b9c47ab32bcc3a1666307 Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 29 Jul 2026 02:24:41 +0200 Subject: Security audit fixes: patch 16 vulnerabilities across 7 source files CRITICAL: - Instance name path traversal (AP-001): sanitize::sanitize_instance_name() strips .., /, \, \0, spaces, special chars at all 12 join call sites - Zip-slip protection in world import: starts_with() guard after enclosed_name() HIGH: - RCON command injection: validate_username() rejects non-MC usernames across all 6 player action macros (whitelist, op, ban) - Level-seed properties injection: sanitize_seed() strips \n \r = : \0 - CSRF protection: SameSite=Lax -> SameSite=Strict on session cookie MEDIUM: - Session TTL: server-side 24h expiry via strftime check in require_auth - Rate limiting: in-memory 10-ip/5min sliding window on login - Background task stale is_active: all queries use concrete WHERE id=?1 - Mod validation DoS: 500MB cap, 10k class scan limit, 10k CP entry cap LOW: - Logout auth guard: moved into protected route group + CurrentUser param - Mod orphan race: DB insert before file write - Backup orphan race: DB insert before ZIP creation - Template fix: broken Askama == comparisons in edit.html All fixes compile clean with zero warnings. 10 unit tests pass. --- piolium/final-audit-report.md | 407 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 407 insertions(+) create mode 100644 piolium/final-audit-report.md (limited to 'piolium/final-audit-report.md') diff --git a/piolium/final-audit-report.md b/piolium/final-audit-report.md new file mode 100644 index 0000000..049d2b2 --- /dev/null +++ b/piolium/final-audit-report.md @@ -0,0 +1,407 @@ +# Security Audit Report: salmon/minecraft-ui + +========================================= + +## Executive Summary + +This audit of **minecraft-ui** — a self-hosted Rust (axum) web application that manages Docker-based Minecraft server instances — identified **17 validated vulnerabilities** spanning path traversal, injection, CSRF, session management, authorization, concurrency, denial-of-service, and cryptographic weaknesses. The most critical issue is **arbitrary filesystem access via unsanitized instance names** (AP-001), which enables path-traversal-driven directory creation, deletion, and constrained file read/write across 12 confirmed code paths — including 4 variant instances discovered in Phase 12. Four high-severity findings were cold-verified via adversarial review (P11). Combined with universal CSRF absence (31 POST endpoints) and a flat authorization model, the application provides minimal defense-in-depth: any authenticated user can destroy data, modify server configurations, or gain persistent access to Minecraft server consoles. The audit reached draft stage but the **findings promotion pipeline stalled** — no PoCs were built and no `piolium/findings/` directory was created. This report is assembled from available draft, chamber, and knowledge-base artifacts. + +## Methodology Summary + +- **Intelligence Gathering:** Advisory collection via `cargo-audit-advisory` (SBOM), architecture inventory of 16 Rust source files, dependency analysis (rusqlite, bollard, multer, zip) +- **Knowledge Base:** Threat modeling with DFD/CFD slices (P3), manual attack surface inventory of 38 routes (P8), domain attack research (Minecraft RCON, Java .properties, Docker env injection) +- **Static Analysis:** Structural extraction via manual code review; CodeQL database could not be built (system constraint); Semgrep ran but with limited Rust rule coverage +- **Review Chambers:** 6-cluster multi-agent debate system (path-traversal, injection, auth-session, state-concurrency, denial-of-service, security-architecture). 37 findings from P4/P5/P6/P8 reviewed → **17 VALID** survivors, 7 FALSE POSITIVE, 8 DROP, 5 DUPLICATE +- **Verification:** P11 cold verification (adversarial review) for 4 highest-severity findings: p10-001 (CONFIRMED), p10-003 (CONFIRMED), p10-004 (DISPROVED), p10-005 (CONFIRMED with severity downgrade challenge) +- **Variant Analysis (P12):** 4 path-traversal variants discovered from AP-001 root cause search + +## Summary of Findings + +| ID | Title | Severity | PoC Status | Status | +|----|-------|----------|------------|--------| +| — | Instance Name Path Traversal (p10-001) | CRITICAL | draft-only | Not promoted | +| — | Level-Seed Properties Injection (p10-003) | HIGH | draft-only | Not promoted | +| — | Missing CSRF Protection (p10-005) | HIGH | draft-only | Not promoted | +| — | RCON Password Exposed to All Users (p10-004) | **LOW** (DISPROVED) | blocked | Adversarial reversal | +| — | RCON Command Injection (p10-002) | MEDIUM | draft-only | Not promoted | +| — | Flat Authorization Model (p10-010) | MEDIUM | draft-only | Not promoted | +| — | No Server-Side Session TTL (p10-006) | MEDIUM | draft-only | Not promoted | +| — | No Rate Limiting Login (p10-007) | MEDIUM | draft-only | Not promoted | +| — | Background Task Stale is_active (p10-011) | MEDIUM | draft-only | Not promoted | +| — | Delete-Create Name Reuse Race (p10-012) | MEDIUM | draft-only | Not promoted | +| — | No Idempotency (p10-013) | MEDIUM | draft-only | Not promoted | +| — | Mod Validation Denial of Service (p10-016) | MEDIUM | draft-only | Not promoted | +| — | No Encryption at Rest (p10-017) | MEDIUM | draft-only | Not promoted | +| — | Logout No Auth Middleware (p10-008) | LOW | draft-only | Not promoted | +| — | Cookie No Secure Flag (p10-009) | LOW | draft-only | Not promoted | +| — | Mod Write Before DB Orphan (p10-014) | LOW | draft-only | Not promoted | +| — | Backup Orphan Race (p10-015) | LOW | draft-only | Not promoted | + +### Variant Findings (Phase 12) + +| Variant ID | Title | Severity | Parent | PoC Status | +|-----------|-------|----------|--------|------------| +| p12-001 | World Import Path Traversal | HIGH | p10-001 | draft-only | +| p12-002 | Regenerate World Path Traversal | HIGH | p10-001 | draft-only | +| p12-003 | Player Management Path Traversal | MEDIUM | p10-001 | draft-only | +| p12-004 | Backup Create Path Traversal | MEDIUM | p10-001 | draft-only | + +> **Note:** No findings were promoted to `piolium/findings/` with PoC scripts, evidence, or full report.md files. All entries above remain at draft stage in `piolium/findings-draft/`. + +--- + +## Technical Findings Detail + +### Instance Name Path Traversal (p10-001 — CRITICAL equivalent) + +- **Severity:** CRITICAL +- **Summary:** The instance `name` field flows unsanitized into `Path::join()` for 8 different filesystem operations. Rust's `Path::join()` follows `..` components, enabling arbitrary directory creation, deletion, and constrained file read/write outside the intended data directory. +- **Impact:** An authenticated attacker can: + - **Delete arbitrary directories** via `remove_dir_all` (path: `src/routes/instances.rs:388-392`) — e.g., name=`../../../target` deletes the project build directory + - **Create arbitrary directories** via `create_dir_all` (path: `src/routes/instances.rs:204-206`) + - **Write files to arbitrary locations** (constrained by `/mods/` or `/data/world/` suffix chaining via mod upload and world import) + - **Read files from arbitrary locations** (constrained by world export and backup download paths) +- **Root Cause:** `Path::join()` in Rust follows `..` components. User-controlled `form.name` is passed directly with no sanitization, length limits, or character restrictions. No validation exists at any of the 12 known join call sites. +- **Key Code Reference:** `src/routes/instances.rs:204-206` — `Path::join(&form.name)` → `create_dir_all` +- **PoC Status:** draft-only (no executable PoC built) +- **Detailed Report:** `piolium/findings-draft/p10-001-instance-name-path-traversal.md` +- **Adversarial Review:** `piolium/adversarial-reviews/p10-001-instance-name-path-traversal-review.md` — CONFIRMED, severity challenge rejected + +#### Attack Pattern: AP-001 + +This finding is the root of attack pattern **AP-001** (Path Traversal via Unsanitized Instance Name), which has 12 confirmed instances across 4 route modules: +- `src/routes/instances.rs:205` (create_dir_all) +- `src/routes/instances.rs:392` (remove_dir_all) +- `src/routes/mods.rs:126` (mods dir creation) +- `src/routes/mods.rs:343` (mod rescan) +- `src/routes/mods.rs:394` (mod delete) +- `src/routes/backups.rs:107` (backup path) +- `src/routes/instances.rs:593` (world export) +- `src/routes/instances.rs:739` (server.properties) +- `src/routes/instances.rs:672` (world import — variant) +- `src/routes/instances.rs:776` (regenerate world — variant) +- `src/routes/players.rs:53` (player management — variant) +- `src/routes/backups.rs:112` (backup create — variant) + +#### Variants + +| Variant ID | Title | Severity | Location | Flow | +|-----------|-------|----------|----------|------| +| p12-001 | World Import Path Traversal | HIGH | `instances.rs:672` | `instance_name` from DB → `world_dir.join(zip_entry)` → `File::create()` | +| p12-002 | Regenerate World Path Traversal | HIGH | `instances.rs:776` | `instance_name` from DB → `.join(&name)` → `remove_dir_all(world_dir)` | +| p12-003 | Player Management Path Traversal | MEDIUM | `players.rs:53` | `inst_name` → `.join(...)` → `read_json_list()` (read-only, 3 filenames) | +| p12-004 | Backup Create Path Traversal | MEDIUM | `backups.rs:112` | `name` → `{name}_{timestamp}.zip` → `.join(&filename)` → `File::create()` | + +Variant details: `piolium/findings-draft/p12-001-*.md` through `piolium/findings-draft/p12-004-*.md` + +--- + +### Level-Seed Properties Injection (p10-003 — HIGH) + +- **Severity:** HIGH +- **Summary:** The `POST /instances/{id}/world/regenerate` handler writes the user-supplied `seed` value into `server.properties` via line-based replacement with no escaping. Newline characters in the seed inject arbitrary Java `.properties` entries. +- **Impact:** Persistent modification of Minecraft server configuration: + - Set `online-mode=false` (disable authentication — any player can join as anyone) + - Set `enforce-whitelist=false` (bypass whitelist restrictions) + - Change difficulty, gamemode, max-players, PvP settings + - Inject malformed properties causing server startup failure (DoS) + - **Persistence:** Injected values survive across server restarts until manually cleaned +- **Root Cause:** `format!("level-seed={seed}")` writes the seed value directly into `server.properties` without escaping. The Java `.properties` spec treats newlines as property separators. The `properties.rs:13-19` reader also lacks escape-sequence processing (spec gap G1). +- **Key Code Reference:** `src/routes/instances.rs:715-759` — `regenerate_world` handler, line replacement loop +- **PoC Status:** draft-only +- **Detailed Report:** `piolium/findings-draft/p10-003-level-seed-properties-injection.md` +- **Adversarial Review:** `piolium/adversarial-reviews/p10-003-level-seed-properties-injection-review.md` — CONFIRMED, severity unchanged + +--- + +### Missing CSRF Protection (p10-005 — HIGH) + +- **Severity:** HIGH (adversarial challenge to MEDIUM rejected) +- **Summary:** The application has no CSRF protection across any of its 31 POST endpoints. No CSRF tokens are generated or validated. No Origin/Referer header validation exists. The session cookie uses `SameSite=Lax` which permits cookies on top-level cross-site POST navigations. +- **Impact:** Universal cross-site request forgery enabling: + - **Account takeover:** Cross-site password change (though `current_password` IS required for `/change-password`, the superuser `/accounts/set-password` does NOT require the current password) + - **Instance destruction:** Cross-site delete requests wipe server data + - **File system manipulation:** CSRF + path traversal (p10-001) to write files to arbitrary locations + - **Minecraft server compromise:** CSRF to op attackers on the Minecraft server via player management endpoints + - **Malicious mod upload:** Cross-site mod upload writes JAR files to server +- **Root Cause:** Cookie `SameSite=Lax` (not `Strict`) and zero CSRF token infrastructure. No axum CSRF middleware, no custom token generation, no header validation. +- **Key Code Reference:** `src/auth.rs:83-86` — Cookie with `SameSite=Lax`; entire `src/routes/mod.rs` — no CSRF middleware +- **PoC Status:** draft-only +- **Detailed Report:** `piolium/findings-draft/p10-005-missing-csrf-protection.md` +- **Adversarial Review:** `piolium/adversarial-reviews/p10-005-missing-csrf-protection-review.md` — CONFIRMED; severity down-challenge from HIGH to MEDIUM rejected by chamber (sub-claim D partially false but overall impact remains HIGH) + +--- + +### RCON Command Injection (p10-002 — MEDIUM) + +- **Severity:** MEDIUM +- **Summary:** The `player_action!` macro in `src/routes/players.rs` constructs RCON commands by interpolating user-supplied usernames via `format!()` without sanitization. Six player management endpoints are affected. +- **Impact:** Operation-target manipulation via space injection, silent operation failure from malformed usernames. In vanilla Minecraft, RCON does not support command chaining (no `;` or `&&` injection), limiting impact to argument injection. On Spigot/Paper servers with command-chaining plugins, broader injection may be possible. +- **Root Cause:** `format!("whitelist add {}", form.username)` — no validation, no character filtering, no Minecraft username format enforcement. +- **Key Code Reference:** `src/routes/players.rs:89-102` — `player_action!` macro; `PlayerAction.username` is a raw `String` +- **PoC Status:** draft-only +- **Detailed Report:** `piolium/findings-draft/p10-002-rcon-command-injection.md` + +--- + +### Flat Authorization Model (p10-010 — MEDIUM) + +- **Severity:** MEDIUM +- **Summary:** Any authenticated user has full access to ALL instances, mods, backups, and player operations. There is no per-resource ownership, no role granularity beyond binary superuser/non-superuser, and no instance-level authorization. +- **Impact:** In multi-user deployments, every user is a full administrator of every server instance. Data exfiltration, destructive operations, and Minecraft server control are all available to any authenticated account. +- **Root Cause:** No `owner_id` column on `instances` table; all handlers use `CurrentUser(_user)` with destructured-and-ignored user variable; all queries lack user-scoped filters. +- **Key Code References:** `src/routes/instances.rs` (all handlers), `src/routes/players.rs` (`player_action!`), `src/routes/backups.rs`, `src/routes/mods.rs` +- **PoC Status:** draft-only +- **Detailed Report:** `piolium/findings-draft/p10-010-flat-authorization-model.md` + +--- + +### No Server-Side Session TTL (p10-006 — MEDIUM) + +- **Severity:** MEDIUM +- **Summary:** The `require_auth` middleware validates session cookies against the database but never checks the `created_at` timestamp, despite the column existing in the schema. Stolen session cookies remain valid indefinitely server-side. +- **Root Cause:** `WHERE s.id = ?1` query at `src/auth.rs:108-115` lacks a time-based filter. Cookie Max-Age=86400 is client-side only and trivially bypassed. +- **Key Code Reference:** `src/auth.rs:108-115` — session query without `created_at` filter +- **PoC Status:** draft-only +- **Detailed Report:** `piolium/findings-draft/p10-006-no-server-side-session-ttl.md` + +--- + +### No Rate Limiting Login (p10-007 — MEDIUM) + +- **Severity:** MEDIUM +- **Summary:** `POST /login` has no rate limiting, account lockout, or progressive delay. Argon2id (~100ms/attempt) provides a weak mitigating factor. +- **Root Cause:** No rate-limiting middleware, no `governor` or equivalent crate in Cargo.toml. +- **Key Code Reference:** `src/auth.rs:39-92` — authenticate handler; `src/routes/mod.rs:44` — route registration +- **PoC Status:** draft-only +- **Detailed Report:** `piolium/findings-draft/p10-007-no-rate-limiting-login.md` + +--- + +### Background Task Stale is_active (p10-011 — MEDIUM) + +- **Severity:** MEDIUM +- **Summary:** `activate_instance` spawns a background tokio task that updates `container_state` using `WHERE is_active = 1` instead of the concrete instance ID. If the user switches active instances during the 60-second polling window, the stale task writes to the wrong instance's state. +- **Root Cause:** 5 UPDATE statements at `src/routes/instances.rs:457-502` all use `WHERE is_active = 1` instead of `WHERE id = ?1`. +- **Key Code Reference:** `src/routes/instances.rs:457-502` — background tokio task +- **PoC Status:** draft-only (requires dynamic test) +- **Detailed Report:** `piolium/findings-draft/p10-011-background-task-stale-is-active.md` + +--- + +### Delete-Create Name Reuse Race (p10-012 — MEDIUM) + +- **Severity:** MEDIUM +- **Summary:** `delete_instance` releases the DB mutex before `remove_dir_all`. A concurrent `create_instance` with the same name can create a new instance whose data directory is then wiped by the still-running deletion. +- **Root Cause:** Mutex released at `drop(conn)` between `DELETE FROM instances` and `remove_dir_all()` (microsecond-to-millisecond race window). +- **Key Code Reference:** `src/routes/instances.rs:360-396` +- **PoC Status:** draft-only (requires dynamic test) +- **Detailed Report:** `piolium/findings-draft/p10-012-delete-create-name-reuse-race.md` + +--- + +### No Idempotency (p10-013 — MEDIUM) + +- **Severity:** MEDIUM +- **Summary:** Zero idempotency infrastructure across all 31 POST endpoints. Network request replay (HTMX retry, proxy retry, rapid clicks) causes duplicate operations. +- **Impact:** Duplicate mod uploads cause classloader conflicts on server restart (DoS). Duplicate backup creation wastes disk space. Duplicate player RCON commands are mostly harmless. +- **Root Cause:** No idempotency key table, no deduplication logic, no request ID storage. +- **Key Code Reference:** All POST endpoints in `src/routes/*.rs` +- **PoC Status:** draft-only (static hypothesis) +- **Detailed Report:** `piolium/findings-draft/p10-013-no-idempotency.md` + +--- + +### Mod Validation Denial of Service (p10-016 — MEDIUM) + +- **Severity:** MEDIUM +- **Summary:** `validate_mod()` parses uploaded JAR constant pools with no timeout or resource limits. A crafted constant pool (cp_count=65535, expensive CONSTANT_Utf8 entries) causes CPU exhaustion on the async runtime. +- **Impact:** Async thread pool exhaustion; multiple concurrent crafted uploads make the server unresponsive. +- **Root Cause:** Unbounded `while i < cp_count` loop at `src/mods.rs:173-232` with no timeout wrapping. +- **Key Code Reference:** `src/mods.rs:173-232` — `scan_single_class()`; `src/routes/mods.rs:109-250` — no timeout around `validate_mod` +- **PoC Status:** draft-only +- **Detailed Report:** `piolium/findings-draft/p10-016-mod-validation-denial-of-service.md` + +--- + +### No Encryption at Rest (p10-017 — MEDIUM) + +- **Severity:** MEDIUM +- **Summary:** SQLite database `mcui.db` is stored unencrypted on disk with plaintext RCON passwords. Disclosure via prerequisite file read (p10-001 path traversal) or physical access exposes all secrets. +- **Root Cause:** `Connection::open(path)` at `src/db.rs:16` with no encryption (no SQLCipher, no individual field encryption). +- **Key Code Reference:** `src/db.rs:16` — `Connection::open(path)` +- **PoC Status:** draft-only +- **Detailed Report:** `piolium/findings-draft/p10-017-no-encryption-at-rest.md` + +--- + +### Logout No Auth Middleware (p10-008 — LOW) + +- **Severity:** LOW +- **Summary:** `POST /logout` is registered outside the `require_auth` protected router group. Any unauthenticated request can reach the logout handler. Requires prior session ID disclosure (UUIDv4, 122-bit entropy) for practical exploitation. +- **Key Code Reference:** `src/routes/mod.rs:20-33` — logout registered before `.merge(protected)` +- **PoC Status:** draft-only +- **Detailed Report:** `piolium/findings-draft/p10-008-logout-no-auth-middleware.md` + +--- + +### Cookie No Secure Flag (p10-009 — LOW) + +- **Severity:** LOW +- **Summary:** Session cookie lacks `Secure` flag. With localhost-bound traffic behind an HTTPS-terminating reverse proxy, the cookie travels unencrypted between proxy and app. +- **Key Code Reference:** `src/auth.rs:83-86` — cookie string missing `; Secure` +- **PoC Status:** draft-only +- **Detailed Report:** `piolium/findings-draft/p10-009-cookie-no-secure-flag.md` + +--- + +### Mod Write Before DB Orphan (p10-014 — LOW) + +- **Severity:** LOW +- **Summary:** `process_jar_upload` writes the mod file to disk before inserting the DB record. A crash between these operations orphans the file (invisible to UI, never cleaned up). +- **Key Code Reference:** `src/routes/mods.rs:234-260` +- **PoC Status:** draft-only (static hypothesis) +- **Detailed Report:** `piolium/findings-draft/p10-014-mod-write-before-db-orphan.md` + +--- + +### Backup Orphan Race (p10-015 — LOW) + +- **Severity:** LOW +- **Summary:** `create_backup` creates the ZIP file before inserting the DB record. Concurrent instance deletion during ZIP creation causes a silently-swallowed FK violation, leaving orphaned ZIP files on disk. +- **Key Code Reference:** `src/routes/backups.rs:85-139` +- **PoC Status:** draft-only (requires dynamic test) +- **Detailed Report:** `piolium/findings-draft/p10-015-backup-orphan-race.md` + +--- + +## Attack Surface Summary + +The complete attack surface inventory is documented at: + +| Artifact | Path | Description | +|----------|------|-------------| +| **Knowledge Base Report** | `piolium/attack-surface/knowledge-base-report.md` | Full architecture model, DFD/CFD slices, trust boundaries, component inventory (18 sections) | +| **Attack Pattern Registry** | `piolium/attack-pattern-registry.json` | 5 confirmed attack patterns (AP-001 through AP-005) with 12+32+1+31+1=77 total confirmed instances | +| **Manual Attack Surface Inventory** | `piolium/attack-surface/manual-attack-surface-inventory.md` | 38 HTTP routes catalogued with entry points, sinks, trust boundaries | +| **Source-Sink Flow Paths** | `piolium/attack-surface/source-sink-flows-all-severities.md` | All data flow paths from attacker input to dangerous sinks | +| **Unauthenticated Surface** | `piolium/attack-surface/unauthenticated-surface.md` | Routes accessible without authentication | +| **Spec Gap Summary** | `piolium/attack-surface/spec-gap-summary.md` | RFC/contract gaps (Java .properties, Argon2, RCON protocol, Axum contracts) | +| **Variant Analysis Summary** | `piolium/attack-surface/variant-summary.md` | Phase 12 variant search results | +| **State/Concurrency Summary** | `piolium/attack-surface/state-concurrency-summary.md` | Race conditions, TOCTOU, ordering bugs | +| **Advisory Summary** | `piolium/attack-surface/advisory-summary.md` | External advisory intelligence | +| **SBOM** | `piolium/attack-surface/sbom.json` | Software bill of materials | +| **Patch Bypass Summary** | `piolium/attack-surface/patch-bypass-summary.md` | Prior-sec patch regression analysis | + +### Key Attack Surface Dimensions + +1. **38 HTTP routes** — 3 public POST, 1 public GET, 31 authenticated POST, 3 authenticated GET +2. **5 attacker-controlled input sources** — form fields (instance name, seed, username, motd), multipart uploads (JAR/ZIP files), path parameters (instance ID, backup ID, mod ID), cookie header, outbound Mojang API response +3. **4 dangerous sinks** — filesystem (create_dir_all, remove_dir_all, File::create, read_to_string), RCON TCP (send_command_async), Docker Unix socket (bollard API), SQLite (rusqlite) +4. **3 trust boundaries** — unauthenticated→authenticated (session cookie), webUI→filesystem (path traversal), webUI→RCON/Minecraft (command injection) + +--- + +## Coverage Gaps + +### Pipeline Failure: Findings Never Promoted + +The most significant gap is that **the findings promotion pipeline terminated prematurely** between Phase 12 (variant analysis) and Phase 15 (report assembly): + +- `piolium/findings/` — **does not exist** — no finding was ever promoted from draft +- No PoC scripts were built for any finding +- No `report.md` files were generated with structured severity/PoC/evidence sections +- No execution evidence was collected +- Only 4 of 17 findings received adversarial review (P11 cold verification) +- No `metadata.json` files were created for variant-parent tracking +- Validating script (`validate_phase_output.py`) not present at expected path + +### Static Analysis Gaps + +- **CodeQL database could not be built** — the Rust analyzer version mismatch prevented database construction. Only structural extraction (call graphs, entry points, sinks) was performed from manual review. +- **Semgrep Pro** not available — cross-file taint analysis was not performed for Rust +- **No automated sink-to-source tracing** — all data flow mapping was manual + +### Multi-User Deployment Not Analyzed for Scale + +- The flat authorization model (p10-010) was assessed as MEDIUM based on single-user assumptions +- In a multi-user deployment (2+ users), the severity of p10-010 + p10-001 + p10-005 escalates to CRITICAL +- No instance-level access control, audit logging, or rate limiting for user actions + +### Encryption & Key Management + +- No encryption at rest (p10-017) +- RCON passwords stored in plaintext +- No TLS termination handled by the application (delegated to reverse proxy) +- Session IDs stored in unencrypted SQLite + +### Supply Chain Not Scanned + +- 19 Rust crate dependencies listed in SBOM but no automated vulnerability scan (cargo-audit not integrated) +- Outbound Mojang API calls not constrained (no TLS pinning, no timeout documented) + +--- + +## Methodology Notes + +### Chamber Workspace Summary + +The Phase 10 adversarial review chamber processed 37 finding candidates across 6 clusters: + +| Cluster | Attack Class | Candidates | Valid Survivors | Rejected | +|---------|-------------|-----------|-----------------|----------| +| path-traversal | Path Traversal & File System | 7 | 1 (H-01) | 6 | +| injection | Injection (RCON, Docker, Properties) | 5 | 2 (H-08, H-10) | 3 | +| auth-session | Auth & Session Management | 9 | 4 (H-13, H-14, H-16, H-17) | 5 | +| state-concurrency | State & Concurrency | 6 | 5 | 1 | +| denial-of-service | Denial of Service | 4 | 1 (H-28) | 3 | +| security-architecture | Security Architecture | 6 | 1 (H-33) | 5 | +| **Total** | | **37** | **17** | **20** | + +**Rejection breakdown:** 7 FALSE POSITIVE, 8 DROP, 5 DUPLICATE + +### Cold Verification (P11) + +4 findings subjected to adversarial review: +- **p10-001** (Instance Name Path Traversal): CONFIRMED — severity HIGH→HIGH (no change) +- **p10-003** (Level-Seed Properties Injection): CONFIRMED — severity HIGH→HIGH (no change) +- **p10-004** (RCON Password Exposed): DISPROVED — password never rendered in edit.html template (Askama explicit-field model) +- **p10-005** (Missing CSRF Protection): CONFIRMED — severity HIGH→MEDIUM challenged, rejected by chamber (CSRF+chain attacks warrant HIGH) + +### Variant Analysis (P12) + +4 new variant instances discovered from AP-001 root cause search: +- All 4 come from instance name path traversal pattern +- Zero variants found for the remaining 13 findings +- The path traversal pattern (AP-001) is the most pervasive vulnerability class with 12 total confirmed instances + +### Attack Pattern Registry + +5 attack patterns documented in `piolium/attack-pattern-registry.json`: +- AP-001: Path Traversal via Unsanitized Instance Name (12 instances) +- AP-002: RCON Command Injection via Unsanitized Username (6 instances) +- AP-003: Java Properties Injection via Unsanitized Seed Value (1 instance) +- AP-004: Missing CSRF Protection (31 endpoints) +- AP-005: No Server-Side Session TTL Enforcement (1 query) + +--- + +## Conclusion + +This audit catalogued 17 validated vulnerabilities across the minecraft-ui codebase. The most severe class — **path traversal via unsanitized instance names** — creates a systemic risk: any authenticated user can read, write, and delete files anywhere the webUI process can access. The absence of CSRF protection (31 endpoints) and per-resource authorization means that a single compromised account (or a cross-site request from a victim's browser) grants full control over all server instances, their files, and their Minecraft consoles. + +The application's security posture is appropriate _only_ for its documented single-user, localhost-only deployment model. Any deployment that: +- Exposes the WebUI beyond localhost +- Adds a second user account +- Sits behind a reverse proxy without CSRF middleware at the proxy layer +- Does not validate instance names at the input layer + +...faces unacceptable risk of data loss, privilege escalation, and persistent compromise. + +**Pipeline note:** The audit's findings-draft→findings promotion failed. The 17 validated findings, 4 variants, and 5 attack patterns documented in this report are derived from draft-level analysis without confirmed PoC execution. A follow-up audit should focus on building working PoCs for the critical and high-severity findings and executing them against a deployed instance to confirm exploitability and impact in a real environment. + +--- + +## Deferred Findings (triage skip) + +*No findings were triaged to `piolium/findings-deferred/`. The `piolium/findings-deferred/` directory does not exist because no findings were promoted past the draft stage. All 17 validated findings remain at investigative (draft) status.* \ No newline at end of file -- cgit v1.2.3