TL;DR
Attackers found a way to take control of internet-exposed MikroTik routers without a password before official fixes were publicly available. Bishop Fox reproduced the attack and found signs of compromise on real devices, confirming that this was not merely a theoretical risk.
Because routers sit between homes, organizations and the internet, a compromised device can expose traffic, credentials, and the networks behind it. Installing the update prevents new exploitation but does not remove access to an already established attacker. Organizations should patch affected routers immediately and investigate them for indicators of compromise.
Background
From Active Exploitation to a Reproducible Chain
On September 5, 2026, CERT Polska published an advisory for six vulnerabilities in MikroTik RouterOS, including vulnerabilities attackers could combine into the "MikroTrick" takeover chain. MikroTik addressed all six in the same security releases, and evidence indicates that attackers were exploiting affected routers before the vulnerabilities became public.
The technical advisory described more than one possible way to begin the attack. As such, we investigated the path with the fewest prerequisites: CVE-2026-67279, which can be triggered without credentials or information about an existing user.
We compared vulnerable and fixed RouterOS releases, traced the relevant changes through the SSH service and login process, and reproduced the behavior in a controlled lab. The analysis revealed two separate failures that become far more serious when combined. The first allows an unauthenticated connection to reach functionality that should exist only after login. The second turns attacker-controlled login data into a trusted administrative identity.
We reproduced the complete administrative takeover on vulnerable RouterOS 7.x builds. The first-stage authentication bypass also affects 6.x, but the same construction did not produce an administrative session there. The following sections explain where those behaviors diverge and how the two vulnerabilities form a working chain.
Vulnerability Chain
MikroTrick combines two failures at different trust boundaries. The first allows an unauthenticated connection to reach functionality that RouterOS should expose only after login. The second causes the login process to treat data from that connection as a trusted administrative identity.
Stage One: Rekeying Skips Authentication
CVE-2026-67279
SSH normally progresses through three distinct phases: establish an encrypted connection, authenticate a user, and then allow that user to open terminals or run commands. RouterOS correctly enforces this sequence during an ordinary connection. The problem appears when an unauthenticated client asks the server to renegotiate its encryption keys, a normal SSH operation known as rekeying.
On a vulnerable RouterOS build, completing the rekey moves the connection into the next protocol phase even though no user has authenticated. The client can then open a session channel, request a terminal, and submit an execution request.
This does not yet produce an administrator. The session has no authenticated identity or permission set. It does, however, cross the boundary that previously kept the client away from RouterOS's login process which is how the second vulnerability becomes feasible.
CERT Polska reports that this unauthenticated execution path can also manipulate files in the RouterOS-managed file namespace, including support files containing configuration and diagnostic information. Our testing confirmed the authentication-state bypass but did not exercise those file operations.
Stage Two: A Username Becomes a Trusted Instruction
CVE-2026-86060
RouterOS uses a separate helper program to establish the identity and permissions for a login session. The SSH service passes the client-supplied username to that helper as a command-line argument.
The helper also contains a legacy feature intended for trusted local programs. An argument beginning with a dash is not treated as a username. Instead, the number after the dash selects an already-open file descriptor from which the helper reads a trusted identity record containing a username and permission set.
The SSH service passed remote usernames into this interface without rejecting that special syntax. Supplying the username -2 therefore instructed the helper to read its trusted identity from file descriptor 2.
On vulnerable RouterOS 7.x builds, that descriptor is connected to the client's session terminal. The attacker can therefore provide the record that the helper believes came from a trusted local process. When that record identifies the administrator and supplies the full permission set, the helper installs those values without completing normal authentication.
Patch Analysis
The two fixes appear in different components and address different conditions. The SSH dispatcher now verifies that a session has an assigned policy before processing connection-layer requests, while the SSH login path now rejects usernames that could be interpreted as login-helper control syntax. This confirmed that “MikroTrick” combines two independent vulnerabilities rather than two symptoms of the same defect.
The following excerpts use normalized variable names for readability. The field offsets and control flow are preserved from the decompiler, and the addresses are virtual addresses from the extracted ELF files.
Fix One: Require a Session Policy Before Dispatch
In RouterOS 7.23.3, the connection-protocol dispatcher checks the connection state before dispatching an incoming packet, but it does not confirm that authentication assigned the session a policy. RouterOS 7.23.4 adds that missing check. The essential difference between the two builds is:
// 7.23.3 dispatcher: 0x08057404
// 7.23.4 dispatcher: 0x08057482
connection = *(session + 0xac);
if (*(uint8_t *)(connection + 0x78) != 0) {
// Added in 7.23.4:
if (*(uint32_t *)(connection + 0x108) == 0)
return 2;
dispatch_connection_packet(packet_type);
}
The field at connection + 0x108 contains the session's policy mask. A normally authenticated session has a policy, however, a session that reached this dispatcher through the vulnerable rekey path does not. Testing that field therefore restores the authorization invariant that the earlier state transition failed to enforce.
RouterOS 6.49.21 adds the same semantic check against the corresponding 6.x policy field at connection + 0xd8. The different offsets reflect the branch-specific structure layouts, but the security decision is identical: do not dispatch connection-layer traffic for a session with no assigned policy.
When this check fails, RouterOS returns status 2 and terminates the operation without sending a descriptive SSH error. Paramiko consequently reports the interrupted rekey as Negotiation failed. That externally observable behavior became the patched-side signature used by our safe detector.
Fix Two: Reject Helper-Control Syntax at the SSH Boundary
The fix for CVE-2026-86060 occurs before RouterOS constructs the login helper's command line. Patched SSH binaries import a new function, validLoginParamInput, from libumsg.so and call it on the client-supplied username.
The RouterOS 7.23.4 call site, near 0x08062192, reduces to:
if (!validLoginParamInput(username))
return invalid_user_input;
invoke_login_helper(username);
The new validator rejects empty usernames, leading dashes, leading or trailing spaces, and control characters:
bool validLoginParamInput(string_view username)
{
if (username.length == 0)
return false;
if (username.data[0] == '-' || username.data[0] == ' ')
return false;
if (username.data[username.length - 1] == ' ')
return false;
for (size_t i = 0; i < username.length; i++) {
unsigned char c = username.data[i];
if (c <= 0x1f || c == 0x7f)
return false;
}
return true;
}
The leading-dash check is the security-relevant change for this chain: the username -2 is rejected before the login helper is invoked.
Just as importantly, the legacy file-descriptor mode (which was unchanged) remains present in the patched login helper. The fix preserves that functionality for trusted local callers while preventing an SSH client from invoking it through the username field. This places the validation at the boundary where untrusted network input enters a trusted local interface.
Analysis of the vulnerable helper corroborates that interpretation. Its dash-handling branch removes the leading character, converts the remainder with atoi, and uses the result as a file descriptor. On 7.x, it accepts descriptors from 0 through 32, reads up to 0x1000 bytes, and interprets the first two NUL-delimited fields as a trusted username and policy mask. The 6.x implementation follows the same general design but lacks the equivalent descriptor upper-bound check.
Field Case: Persistence Outliving the Logs
During authorized testing of internet-facing MikroTik routers, Bishop Fox then encountered something more consequential: devices containing artifacts consistent with the campaign CERT Polska had reported.
The routers' volatile login history no longer covered the suspected compromise period. Their configuration, however, preserved evidence of access. RouterOS logs are memory-resident by default and may disappear when the device reboots. Nonetheless, accounts, scripts, and scheduled tasks can remain long after that history is gone.
The devices also contained a script named logrotate and a scheduler named daily-maint. Once per day, the scheduler ran the script, which recreated a second full-privilege account if it had been removed:
/system script print detail where owner="0"
0 name="logrotate" owner="0"
source=<redacted: recreates a full-privilege account if absent>
/system scheduler print detail where owner="0"
0 name="daily-maint" start-time=03:00:00 interval=1d on-event=logrotate owner="0"
The unauthorized account used a different password on each affected device. That variation is consistent with automated, per-device credential generation, although the passwords alone do not establish how the accounts were created.
The persistent objects shared another unusual property: RouterOS displayed their owner as the numeric identity 0, rather than as a named administrator.
We tested that behavior in the lab. On a vulnerable RouterOS 7.23.3 device, a scheduler created through the tested chain returned owner="0", while a scheduler created through a normal admin login returned owner="admin":
# created through the chain name="poc-test" ... owner="0" # created through a normal admin login name="normal-test" ... owner="admin"
This rendering difference provides a behavioral connection between the tested chain and the field artifacts. It is not, by itself, proof that every object with a numeric owner was created through MikroTrick. RouterOS may also contain legitimate service-created, imported, or historical objects with unfamiliar ownership.
Numeric ownership is therefore best used as a hunting lead. Defenders should examine objects with owner="0" alongside unexpected privileged accounts, scripts, scheduled tasks, configuration history, remote logs, the RouterOS flagged state, and a known-good configuration.
State Bypass Safety Check
We developed a non-invasive test for CVE-2026-67279. It sends no username, authentication attempt, command, or subsystem request. The detector compares two connections. The control completes SSH key exchange and attempts to open a session channel. The test performs an additional rekey before requesting the same channel. A vulnerable build refuses the control request but opens the channel after rekeying:
[VULNERABLE] router.example.net:22
control (no rekey): refused [Unable to open channel.]
test (rekey) : opened [channel opened without userauth (SSH-2.0-ROSSSH)]
Only that differential produces a vulnerable verdict. Timeouts, unsupported SSH algorithms, network interference, and other unmatched results remain inconclusive rather than being interpreted as patched.
We validated the behavior against RouterOS 6.49.20 and 7.23.3 and confirmed the fixed signature on 6.49.21 and 7.23.4. The 7.24 branch was outside our lab matrix and should be assessed by installed version.
Mitigation and Investigation
- Update RouterOS to 6.49.21, 7.23.4, 7.24.2, or a later release for the applicable branch. These releases address all six vulnerabilities from the advisory.
- Treat affected routers as potentially compromised. Patching prevents new exploitation but does not remove attacker-created accounts, scripts, or scheduled tasks.
- Review privileged users, configuration history, remote logs, the RouterOS flagged state, scripts, schedulers, proxies, and tunnels.
- If compromise is suspected, collect configuration and logs before resetting the device. Reconfigure from a verified baseline and rotate every password, key, or other secret the router stored or could observe.
Conclusion
MikroTrick exposes a design risk in privileged software: a feature intended only for trusted local callers becomes remote attack surface when an upstream component loses track of authentication state.
Patch status and compromise status are separate questions. The installed version establishes whether the router remains exposed; accounts, scripts, schedulers, and configuration history establish whether someone used that exposure. On RouterOS, where local logs are volatile, those durable configuration objects may be the better record.
Catching the next MikroTrick before it's turned against you means knowing which of your own internet-facing devices are exposed the moment an advisory drops, not weeks later during a scheduled scan. That’s the gap our Cosmos platform and Continuous Threat Exposure Management services are built to close.
For more vulnerability intelligence insights, visit the Bishop Fox Blog.
Subscribe to our blog
Be first to learn about latest tools, advisories, and findings.
Thank You! You have been subscribed.
Recommended Posts
You might be interested in these related posts.
CVE-2026-82329: Unauthenticated Administrative Access in JFrog Artifactory via an Empty Cluster Join Key
Mind the Config: Detecting and Weaponizing NetScaler CVE-2026-19490
Signature Optional - Analysis of CVE-2026-28323