How I Hacked MikroTik with MikroTrick

First day of KHS (KazHackStan)

The first day of KazHackStan (KHS) started with hardware tasks. One of the first challenges that caught my attention was MikroTik because of the newly disclosed CVE-2026-67276, reported with a CVSS severity of 9.2. I already had my own exploit, so I decided to investigate the RouterOS target.

Getting access

CVE-2026-67276 concerns SSH RSA public-key authentication. The issue is not that RSA itself was broken; it is that the vulnerable SSH implementation did not consistently validate the complete RSA public key during authentication.

An RSA public key includes a modulus (n) and a public exponent (e). According to the vulnerability description, the affected implementation matched an authorized key using its key type and modulus but failed to compare the exponent in the same way. Signature verification then used the exponent supplied by the client.

That mismatch creates the authentication-bypass condition. In ordinary RSA verification, the server checks a relation equivalent to:

m = s^e mod n

where s is the signature integer and m is the encoded message recovered from it. If a crafted key with e = 1 is accepted, the operation becomes:

s^1 mod n = s

The normal RSA verification step is effectively bypassed. The exploit constructs the expected PKCS#1 v1.5 encoded digest and submits it as the signature value. Under the vulnerable key-matching behavior, an attacker who knows the modulus of an authorized RSA key may be able to authenticate without having the corresponding private key.

This is a flaw in how the SSH implementation validates and uses the key, not a general break of correctly implemented RSA.

What my exploit does

The supplied full_exploit.py implements the authentication-bypass attempt in several stages:

  1. SSH banner check. It connects to the SSH service and tries to identify RouterOS and its version from the banner.
  2. RSA modulus input. It can load a public key with --pubkey, accept a modulus through --modulus-hex, or generate a local RSA key pair as a fallback. For the bypass to match an authorized key, the modulus must correspond to the relevant authorized RSA key; a newly generated modulus will not normally match a key already configured on the target.
  3. Forged public-key blob. The forged_public_blob() function builds an SSH RSA key representation with exponent one and the selected modulus.
  4. Forged signature. emsa_pkcs1_v15() builds the encoded digest, while forged_signature() wraps it in the SSH signature structure.
  5. Authentication attempt. The attempt() function uses Paramiko to submit the crafted public key and checks whether the server reports successful authentication.
  6. Optional command execution. If --exec is provided, the script opens an SSH session channel and sends that command after authentication.

The version check is a useful preliminary heuristic, not definitive proof. Banner parsing may not reveal the exact installed release, and a version match alone does not prove that a target is exploitable. The affected and fixed versions should be checked against the current vendor and CERT advisory.

Creating the hacker user

After gaining access during the CTF, I created a user named hacker. The screenshot from the session shows the RouterOS prompt as [hacker@MikroTik], confirming that the subsequent commands were run in that session.

The supplied Python file does not hard-code the user-creation command. It accepts the username through --username and can pass a post-authentication command through --exec. The command used to create the account was therefore a separate action from the RSA signature-forgery logic.

For documentation, a RouterOS account-creation command has this general form:

/user add name=hacker group=<CTF_GROUP> password=<CTF_PASSWORD>

This is a reconstructed command template, not a verbatim command recovered from the supplied source. Before publishing it as the exact command used in the challenge, verify it against your terminal history or notes. Do not publish a real password.

Flag 1: reading flag.txt

Once I had the RouterOS prompt, I used:

/file print detail

The command displayed the file metadata and its contents, including the first flag:

khs{e1_m0dulus_match_n0_exp0nent_ssh_bypass}

The flag itself reflects the core bug: matching the RSA modulus without correctly checking the public exponent.

First flag shown in the RouterOS terminal

Flag 2: investigating /ppp

I continued exploring because the challenge had a second flag. While investigating the RouterOS command tree and drawing on MikroTik CTF write-ups, I looked at the PPP configuration area. I then ran:

/ppp secret print detail

The output included a PPP secret entry whose password field contained the second flag:

khs{arg_1nject10n_user_dash2_r00t_takeover}

Second flag shown in the PPP secret output

The flag wording hints at argument injection and user takeover. However, the displayed output by itself demonstrates that the flag was stored in the PPP secret’s password field; it does not, by itself, prove a separate argument-injection vulnerability was exploited. I keep that distinction clear in the technical analysis.

Results

I submitted the report and achieved +2,500 points.

The interesting part of this challenge was how a small inconsistency in SSH public-key validation could become an access-control failure. The experience also reinforced the value of following the evidence after initial access: the first flag was available through the file listing, while the second required exploring another RouterOS configuration area.

Technical notes and limitations

  • The supplied source implements the SSH authentication attempt and an optional single post-authentication command via --exec; it does not itself implement an interactive terminal or contain a hard-coded user-creation command. The interactive prompt in the screenshots may come from a separate session or a different version of the tooling.
  • The source’s fallback key generation creates a new modulus. That modulus will not ordinarily match a target’s already-authorized RSA key, so the successful CTF path should be documented with the actual modulus/key input used.
  • Keep the account-creation command, exact target version, exploit output, and any additional claims aligned with the original CTF evidence.
  • The broader name MikroTrick can refer to a chain of RouterOS vulnerabilities. Do not attribute every behavior in a multi-vulnerability chain to CVE-2026-67276 alone.

References