{"repro_id":"REPRO-2026-00344","version":6,"title":"MikroTik RouterOS CVE-2026-67279 + CVE-2026-86060 unauthenticated privileged command-execution chain","repro_type":"security","status":"published","severity":"high","description":"# CVE-2026-67279 - RouterOS pre-authentication SSH rekey state confusion","root_cause":"## Summary\n\nCVE-2026-67279 is a pre-authentication state-machine vulnerability in the MikroTik RouterOS SSH server. On RouterOS CHR 7.23.3, a rejected authentication attempt for the dash-led username `-2` leaves that username pending; a client-requested SSH rekey then incorrectly makes the SSH connection protocol reachable while the transport remains unauthenticated. The client can open a session channel, request a PTY, and submit an exec request. The pending `-2` reaches RouterOS's legacy login helper, where it means “read trusted login fields from file descriptor 2”; attacker-supplied NUL-delimited name/policy fields therefore establish a privileged RouterOS command context. This run dispatched `/file add` and independently observed the resulting RouterOS-managed file. RouterOS CHR 7.23.4 rejected the same sequence during rekey before channel creation.\n\n## Impact\n\n- **Affected component:** MikroTik RouterOS SSH server and its `/nova/bin/login` handoff.\n- **Affected versions:** CERT Polska lists RouterOS 7.0.0 through 7.23.3, 7.24 through 7.24.1, and 6.0.0 through 6.49.20 as affected. This run tested official CHR 7.23.3 as vulnerable and official CHR 7.23.4 as fixed.\n- **Risk:** An unauthenticated network client can cross the real TCP SSH boundary, reach connection-protocol session/exec handling, and change RouterOS-managed file state. This is a high-risk management-plane authentication/workflow failure. The observed command is RouterOS command dispatch, not an arbitrary host-OS shell.\n\n## Impact Parity\n\n- **Disclosed/claimed maximum impact:** Unauthenticated RouterOS command dispatch with creation, overwrite, or reconstruction of a file in the managed file namespace (`claimed_impact_class=code_execution`).\n- **Reproduced impact from this run:** One rejected `-2` authentication request was followed by an unauthenticated client-requested rekey, confirmed session channel, PTY, exec request for `/file add`, fd-2 policy-field injection, and independent serial-console observation of the created file. Two clean CHR 7.23.3 attempts reproduced the result.\n- **Parity:** full.\n- **Not demonstrated:** Arbitrary host-OS command execution, a native shell outside RouterOS, or use of CVE-2026-67276 was neither required nor claimed.\n\n## Root Cause\n\nThe defect is a composition of RouterOS SSH/login workflow state:\n\n1. A password authentication request for username `-2` is rejected, but 7.23.3 retains the requested username in session state.\n2. A client-requested key exchange before successful authentication incorrectly advances or re-enables connection-protocol handling. `Transport.is_authenticated()` remained false in every recorded state.\n3. The server accepts SSH message 90 (session channel open), a PTY request, and SSH message 98 (`exec`) after that rekey.\n4. The retained `-2` is eventually supplied as a positional argument to `/nova/bin/login`. Its legacy dash-number form means “read trusted name and policy fields from descriptor 2.” In the PTY child, descriptor 2 refers to the attacker-controlled terminal.\n5. The bytes `30 00 34323934393637323935 00 04 04` represent effective name `0`, decimal policy `4294967295`, and canonical-terminal EOF framing. The policy value enables the `/file add` command submitted in the exec request.\n\nThe fixed 7.23.4 server rejects the same client-requested rekey after the rejected authentication attempt (`SSHException: Negotiation failed`) before a channel or exec request can be sent. RouterOS is proprietary, so no public source fix commit is available. The vendor fix is shipped in 7.23.4, 7.24.2, 6.49.21, and later releases.\n\n## Reproduction Steps\n\n1. Run `bundle/repro/reproduction_steps.sh` from any directory. Set `PRUVA_ROOT` only if the bundle root cannot be inferred from the script location.\n2. The script installs QEMU if necessary, downloads official CHR 7.23.3 and 7.23.4 images, records source URLs and SHA-256 identities, and creates fresh copy-on-write guests.\n3. For two vulnerable and two fixed attempts, it boots RouterOS, verifies the reported version over the serial console, confirms the real `SSH-2.0-ROSSSH` TCP service, and sends an identical state sequence: initial KEX, one intentionally rejected password request for `-2`, client-requested rekey, session/PTY/exec, and fd-2 trusted fields.\n4. It independently queries `/file` over the RouterOS serial console. Vulnerable attempts must report `PRUVA_MARKER_COUNT=1`; fixed attempts must report `PRUVA_MARKER_COUNT=0` and must never reach a session channel.\n5. Expected final output is: `PASS: CVE-2026-67279 reproduced twice on CHR 7.23.3; CHR 7.23.4 rejected identical pre-auth SSH sequences twice.`\n\n## Evidence\n\n- `bundle/repro/proof-summary.log`: combined immutable proof and image identities.\n- `bundle/repro/vuln-{1,2}-client.json`: ordered attacker state transitions. Each records `authentication_rejected=true`, `authentication_succeeded=false`, `authenticated=false` at the rekey/channel/exec stages, `channel_open_confirmed=true`, and `exec_request_accepted=true`.\n- `bundle/repro/vuln-{1,2}-ssh-state.log`: Paramiko transport/KEX debug logs, including initial and second key exchanges and real RouterOS SSH banner.\n- `bundle/repro/vuln-{1,2}-serial-observation.log`: independent RouterOS CLI observations showing version `7.23.3 (stable)` and `PRUVA_MARKER_COUNT=1` for the unique managed files.\n- `bundle/repro/fixed-{1,2}-client.json`: fixed negative controls showing the same rejected authentication request followed by `SSHException: Negotiation failed`, with no channel, PTY, exec, or policy block.\n- `bundle/repro/fixed-{1,2}-serial-observation.log`: independent RouterOS CLI observations showing version `7.23.4 (stable)` and `PRUVA_MARKER_COUNT=0`.\n- `bundle/repro/runtime_manifest.json`: hashes all proof artifacts and binds the tested official CHR identity.\n\nPinned official archives in the final run:\n\n- CHR 7.23.3: `https://download.mikrotik.com/routeros/7.23.3/chr-7.23.3.img.zip`, SHA-256 `646764fb0a53e9b5a056cb9cf7420eb1629031096c7268c99fb9216c07f8e98c`.\n- CHR 7.23.4: `https://download.mikrotik.com/routeros/7.23.4/chr-7.23.4.img.zip`, SHA-256 `0d32a8da0950dee71e751281c39063f2bebee4b542291aedecc9dbfbe5d60c9d`.\n\n## Recommendations / Next Steps\n\n- Upgrade to RouterOS 7.23.4, 7.24.2, 6.49.21, or a later vendor-fixed release.\n- Restrict SSH management to trusted administration networks or a management VPN; do not expose TCP/22 publicly.\n- Add state-machine tests asserting that a failed authentication followed by client rekey cannot enable SSH connection-protocol messages.\n- Clear retained identity/session state after every failed authentication and enforce a successful authentication invariant at rekey completion, channel open, PTY, shell, subsystem, and exec handlers.\n- Remove or strictly authenticate the legacy `-N` trusted-descriptor login interface, and validate dash-led values before passing them to `/nova/bin/login`.\n- Review RouterOS logs/history for failed user `-2` requests and configuration actions attributed to `ssh:-2@<address>`.\n\n## Additional Notes\n\n- **Idempotency:** The final script passed twice consecutively without edits. Each pass used two fresh vulnerable overlays and two fresh fixed overlays, for four vulnerable and four fixed observations across the required consecutive verification runs.\n- **Isolation:** Guests use QEMU user networking with SSH bound only to localhost host-forward ports. No public system is contacted except MikroTik's official image download endpoint.\n- **Scope:** The proof uses one deliberately rejected password authentication request; no authentication succeeds. This is necessary to seed the pending `-2` identity and does not use the separate RSA authentication bypass CVE-2026-67276.\n- **Implementation limitation:** RouterOS source is proprietary, so root-cause details are established through protocol state evidence, runtime divergence, and public reverse-engineering context rather than a source commit.\n","cve_id":"CVE-2026-67279","source_url":"https://cert.pl/en/posts/2026/09/mikrotik-routeros-cve/","reproduced_at":"2026-09-07T14:21:58.096718+00:00","duration_secs":19563.306989,"tool_calls":1081,"handoffs":2,"total_cost_usd":369.271395,"agent_costs":{"claim_matcher":0.034407,"judge":0.57034,"learning_policy":0.01473,"repro":360.321058,"support":0.732866,"vuln_variant":7.597994},"cost_breakdown":{"claim_matcher":{"gpt-5.4-mini-2026-03-17":0.034407},"judge":{"gpt-5.6-sol":0.57034},"learning_policy":{"gpt-5.4-mini-2026-03-17":0.01473},"repro":{"gpt-5.6-sol":360.321058},"support":{"gpt-5.6-sol":0.732866},"vuln_variant":{"gpt-5.6-sol":7.597994}},"vulnerable_version_variant_outcome":"unknown","fix_bypass_outcome":"not_found","variant_disclosure_state":"not_applicable","quality":{"confidence":"high","idempotent_verified":false,"community_verifications":0},"evidence":{"workflow":{"profile":"known_vulnerability","schema_version":2,"stages":["support","claim_contract","repro","judge","vuln_variant"]}},"environment":{"sandbox_image":"ghcr.io/n3mes1s/pruva-sandbox@sha256:8096b2518d6022e13d68f885c3b8ded6b4fe607098b1a1ccbfb99abc004d1dc1"},"published_at":"2026-09-07T14:21:59.084455+00:00","retracted":false,"artifacts":[{"path":"bundle/repro/rca_report.md","filename":"rca_report.md","size":7974,"category":"analysis"},{"path":"bundle/repro/reproduction_steps.sh","filename":"reproduction_steps.sh","size":16282,"category":"reproduction_script"},{"path":"bundle/repro/fixed-1-ssh-state.log","filename":"fixed-1-ssh-state.log","size":2839,"category":"log"},{"path":"bundle/repro/fixed-2-serial-observation.log","filename":"fixed-2-serial-observation.log","size":2493,"category":"log"},{"path":"bundle/repro/fixed-2-ssh-state.log","filename":"fixed-2-ssh-state.log","size":2839,"category":"log"},{"path":"bundle/repro/runtime_manifest.json","filename":"runtime_manifest.json","size":2974,"category":"other"},{"path":"bundle/repro/validation_verdict.json","filename":"validation_verdict.json","size":1494,"category":"other"}]}