{"repro_id":"REPRO-2026-00365","version":6,"title":"RouterOS SSH RSA key-identity mismatch permits authentication with a forged key sharing an authorized modulus","repro_type":"security","status":"published","severity":"critical","description":"CVE-2026-67276 only: MikroTik RouterOS SSH RSA public-key authentication bypass.","root_cause":"## Summary\n\nCVE-2026-67276 is an SSH RSA public-key authentication bypass in MikroTik RouterOS. Current-run production-path testing demonstrated that RouterOS CHR 7.23.3 accepts an attacker-offered RSA key whose modulus equals an authorized key but whose exponent is changed from 65537 to 1. Because signature validation uses the offered exponent, a client can construct a valid PKCS#1 v1.5 encoded signature without the authorized private key. In two fresh 7.23.3 QEMU states, the forged SSH authentication opened a command channel and returned RouterOS-originated `/system resource print` output. The same input was rejected before command-channel creation in two fresh RouterOS CHR 7.23.4 states.\n\n## Impact\n\n- **Component:** MikroTik RouterOS SSH server, RSA public-key user authentication.\n- **Confirmed affected target:** RouterOS CHR 7.23.3.\n- **Vendor-fixed negative control:** RouterOS CHR 7.23.4.\n- **Risk:** Critical authentication/authorization bypass over the network. An attacker who knows a target username and that account's authorized RSA public modulus can authenticate without the corresponding private key and execute RouterOS commands at that account's existing policy level.\n- **Scope boundary:** The controlled user belonged to RouterOS's `read` group. No privilege escalation and no other MikroTrick CVE was attempted or claimed.\n\n## Impact Parity\n\n- **Disclosed/claimed maximum impact:** Authorization/authentication bypass (`authz_bypass`) with an SSH command channel at the targeted user's existing privileges.\n- **Reproduced impact from this run:** The forged public-key request authenticated as the controlled `cveuser` account and executed `/system resource print` through a real SSH command channel in two independent vulnerable states; 7.23.4 rejected the same request twice.\n- **Parity:** `full`.\n- **Not demonstrated:** Privilege escalation, administrative-policy acquisition, compromise of another account, or any issue other than CVE-2026-67276. These are not required by the submitted claim.\n\n## Root Cause\n\nAn RSA public key is the ordered pair `(n, e)`: modulus `n` and public exponent `e`. RouterOS 7.23.3's SSH authorized-key matching accepts an offered key based on RSA key type and modulus while omitting the exponent. Signature verification subsequently uses the complete attacker-offered key, including the attacker-selected exponent.\n\nThe reproduction provisions a normal 2048-bit RSA authorized key with exponent `e=65537`, deletes its private half, and retains only the public key in the attacker's directory. The forged client offers the same modulus with `e=1`. For RSA verification, exponent one makes `signature^e mod n` equal to the signature representative itself. The attacker therefore supplies the computable EMSA-PKCS1-v1_5 encoding of the SSH user-authentication data as the signature. RouterOS 7.23.3 incorrectly associates the offered key with the authorized identity and validates this forged signature; RouterOS 7.23.4 rejects both `rsa-sha2-256` and `ssh-rsa` attempts, showing that the vendor-fixed target no longer permits this exponent substitution.\n\nRouterOS CHR is a proprietary vendor image, so there is no public source fix commit to link. The vendor bulletin identifies 7.23.4 as containing the fix: <https://mikrotik.com/supportsec/september-2026-vulnerability/>. CERT Polska's technical description is at <https://cert.pl/en/posts/2026/09/mikrotik-routeros-cve/>.\n\n## Reproduction Steps\n\n1. Run `bundle/repro/reproduction_steps.sh` from any directory. `PRUVA_ROOT` may identify the bundle root explicitly.\n2. The script verifies pinned SHA-256 values for official RouterOS CHR 7.23.3 and 7.23.4 archives, installs QEMU only if absent, pins the forged-client source to commit `3281202c8ade8e31acf007da0c71057da83f2335`, and pins Paramiko 5.0.0 and cryptography 50.0.1.\n3. It creates one ordinary RSA setup key, records exponent 65537 and a hash of its modulus, provisions a fresh controlled `read`-group user and public key through factory/setup authentication, deletes the private key, and verifies that no private-key file remains.\n4. It boots two clean copies of unmodified CHR 7.23.3 and sends the exponent-one forged request through each VM's real TCP SSH listener. Each attempt must authenticate, open an exec channel, and return target-originated version 7.23.3 output.\n5. It boots two clean copies of unmodified CHR 7.23.4 and sends the identical attack. Both algorithms must be rejected before any command channel opens.\n6. It writes `bundle/repro/runtime_manifest.json` only after all QEMU processes are stopped and hashes every finalized proof artifact. Exit status 0 means the complete vulnerable/fixed matrix passed; exit status 1 means the issue was not reproduced as required.\n\n## Evidence\n\n- **Runtime manifest:** `bundle/repro/runtime_manifest.json`\n  - `entrypoint_kind=\"tcp_peer\"`\n  - `service_started=true`, `healthcheck_passed=true`, `target_path_reached=true`\n  - Vulnerable archive target digest: `646764fb0a53e9b5a056cb9cf7420eb1629031096c7268c99fb9216c07f8e98c`\n  - Fixed archive digest (manifest note and identity log): `0d32a8da0950dee71e751281c39063f2bebee4b542291aedecc9dbfbe5d60c9d`\n- **Target identity:** `bundle/repro/target_identity.log`\n  - Raw image SHA-256: 7.23.3 `c21bf7d9e21fd8e0595875ddc06bd00e6e414a78b092bdaa245b0fe81f82614d`; 7.23.4 `e5c35c04210438db6825341fa6477c68dfe7ae91443f358cd6e5be45e0201d6b`.\n  - QEMU 10.2.1 binary SHA-256: `0cd4112a8f0cb891eb7c10e8df38c9dfeec8c7389bb22db6aa425f0d6fe733dc`.\n- **Vulnerable attempts:**\n  - `bundle/repro/vulnerable_attempt_1_attack.log` (manifest hash `4b89ba5e2f4abb1eebd4551ba3c0e8306e1a387b6ed266fec3eae76392355e7a`)\n  - `bundle/repro/vulnerable_attempt_2_attack.log` (manifest hash `769070041fabcb731c68e8b12259750a789c58ff9ae1a13bb8772793d9883fe3`)\n  - Both state `AUTHORIZED_PRIVATE_KEY_PRESENT=false`, `AUTHORIZED_ORIGINAL_EXPONENT=65537`, `ATTACKER_OFFERED_EXPONENT=1`, `AUTHENTICATED as 'cveuser'`, and include target-originated `version: 7.23.3 (stable)` and `platform: MikroTik` output.\n- **Fixed negative controls:**\n  - `bundle/repro/fixed_attempt_1_attack.log` (manifest hash `0d6adc714f103587070ef2592e9ca4a193439a673679de10e94469d870216d9a`)\n  - `bundle/repro/fixed_attempt_2_attack.log` (manifest hash `774b847e3250beb0d5e50f23eba24bedf029d6abf67871dd493ec8e77091810a`)\n  - Both report authentication rejection for `rsa-sha2-256` and `ssh-rsa`, then `ATTACK_RESULT=rejected_before_command_channel`.\n- **Setup/TCP evidence:** `bundle/repro/*_setup.log` records the fresh role/version/endpoint, `TCP_LISTENER_REACHED=true`, controlled account creation, imported RSA-2048 key, fingerprint, and `SETUP_PHASE_COMPLETE=true`.\n- **Summary:** `bundle/repro/proof_summary.log` records the four-attempt matrix and explicitly limits the observed impact to `authz_bypass`.\n- **Diagnostics:** `bundle/logs/reproduction_steps.log` contains build/download/runtime diagnostics but is intentionally not manifest-bound while active.\n\nKey vulnerable excerpt:\n\n```text\nAUTHORIZED_PRIVATE_KEY_PRESENT=false\nAUTHORIZED_ORIGINAL_EXPONENT=65537\nATTACKER_OFFERED_EXPONENT=1\n[+] AUTHENTICATED as 'cveuser' via forged e=1 key (rsa-sha2-256)\n--- post-auth command output ---\nversion: 7.23.3 (stable)\nplatform: MikroTik\nATTACK_RESULT=accepted_command_channel_opened\n```\n\nKey fixed-control excerpt:\n\n```text\nTARGET_VERSION=7.23.4\n[-] rsa-sha2-256: authentication rejected (Authentication failed.)\n[-] ssh-rsa: authentication rejected (Authentication failed.)\nATTACK_RESULT=rejected_before_command_channel\n```\n\n## Recommendations / Next Steps\n\n- Upgrade affected 7.x long-term systems to RouterOS 7.23.4 or a later vendor-fixed release. Follow MikroTik's current channel-specific upgrade guidance for other release trains.\n- Compare canonical complete RSA public-key identities during authorization, including both modulus and exponent, rather than treating the modulus alone as the identity.\n- Bind signature verification to the exact authorized key that matched, not to unchecked attributes from the client-offered key.\n- Add regression tests with equal moduli and unequal exponents, including canonical and non-canonical SSH mpint encodings, and require rejection before `SSH_MSG_USERAUTH_SUCCESS` or channel creation.\n- Until systems are upgraded, restrict RouterOS SSH management access to trusted management networks and review authorized keys and authentication logs.\n\n## Additional Notes\n\n- **Idempotency:** The finalized reproduction script completed successfully twice consecutively. Each invocation created two new vulnerable and two new fixed VM disk copies and independently reproduced the same result matrix.\n- **Real boundary:** This is a production-path test of the unmodified vendor CHR images. Attacker data crossed a localhost host-forwarded TCP socket into RouterOS's real SSH server; the vulnerable parser/authentication path was not invoked directly.\n- **Setup separation:** Factory password handling, user creation, and key import occur only in per-target setup logs. The attacker invocation receives only the controlled username and authorized public-key file; it does not receive any setup password. The authorized private key is removed before the first attacker request.\n- **Sanitizers/mocks:** No sanitizer, mocked service, reimplemented RouterOS authentication function, or host-only marker was used. The primary oracle is RouterOS SSH authentication plus RouterOS-originated command output, paired with fixed-version rejection.\n","cve_id":"CVE-2026-67276","cwe_id":"CWE-287","source_url":"https://cert.pl/en/posts/2026/09/vulnerabilities-in-mikrotik-routeros-actively-exploited/","reproduced_at":"2026-09-24T17:06:18.260577+00:00","duration_secs":2055.0,"tool_calls":314,"handoffs":2,"total_cost_usd":15.946253,"agent_costs":{"claim_matcher":0.02061,"judge":0.55573,"learning_policy":0.020545,"repro":12.9634,"support":0.294049,"vuln_variant":2.091919},"cost_breakdown":{"claim_matcher":{"gpt-5.4-mini-2026-03-17":0.02061},"judge":{"gpt-5.6-sol":0.55573},"learning_policy":{"gpt-5.4-mini-2026-03-17":0.020545},"repro":{"gpt-5.6-sol":12.9634},"support":{"gpt-5.6-sol":0.294049},"vuln_variant":{"gpt-5.6-sol":2.091919}},"vulnerable_version_variant_outcome":"unknown","fix_bypass_outcome":"unknown","variant_disclosure_state":"unknown","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-24T17:06:19.122288+00:00","retracted":false,"artifacts":[{"path":"bundle/repro/rca_report.md","filename":"rca_report.md","size":9502,"category":"analysis"},{"path":"bundle/repro/reproduction_steps.sh","filename":"reproduction_steps.sh","size":17551,"category":"reproduction_script"},{"path":"bundle/repro/fixed_attempt_1_qemu.log","filename":"fixed_attempt_1_qemu.log","size":0,"category":"log"},{"path":"bundle/repro/fixed_attempt_1_setup.log","filename":"fixed_attempt_1_setup.log","size":1288,"category":"log"},{"path":"bundle/repro/fixed_attempt_2_qemu.log","filename":"fixed_attempt_2_qemu.log","size":0,"category":"log"},{"path":"bundle/repro/fixed_attempt_2_setup.log","filename":"fixed_attempt_2_setup.log","size":1288,"category":"log"},{"path":"bundle/repro/proof_summary.log","filename":"proof_summary.log","size":675,"category":"log"},{"path":"bundle/repro/runtime_manifest.json","filename":"runtime_manifest.json","size":3088,"category":"other"},{"path":"bundle/repro/validation_verdict.json","filename":"validation_verdict.json","size":1317,"category":"other"},{"path":"bundle/repro/vulnerable_attempt_1_qemu.log","filename":"vulnerable_attempt_1_qemu.log","size":0,"category":"log"},{"path":"bundle/repro/vulnerable_attempt_1_setup.log","filename":"vulnerable_attempt_1_setup.log","size":1293,"category":"log"},{"path":"bundle/repro/vulnerable_attempt_2_qemu.log","filename":"vulnerable_attempt_2_qemu.log","size":0,"category":"log"},{"path":"bundle/repro/vulnerable_attempt_2_setup.log","filename":"vulnerable_attempt_2_setup.log","size":1293,"category":"log"}]}