The router had been running fine, which was the problem

TL;DR A read-only audit of this hAP ac3 found the RouterBOOT bootloader still on a 6.x release under RouterOS 7, the plaintext services enabled, the bandwidth-test server on, MAC-telnet answering on every interface, NTP off, and admin reachable from anywhere. Not one exotic vulnerability among them, just accumulated factory defaults nobody had looked at. Uptime tells you the thing works. It tells you nothing about who can reach it.

A router that has run fine for years and a router nobody has looked at in years produce the same uptime graph, and the only way to tell them apart is to open it up and read what's actually enabled. This hAP ac3 had been quietly doing its job on RouterOS 7.22.1. Then I ran a read-only audit, and the job it had been doing all along turned out to include "leave the front door unlocked."

The firmware you already updated, twice, and still didn't#

First surprise, and the one almost everybody misses: /system/routerboard/print reported current-firmware at 6.47.10 and upgrade-firmware at 7.22.1.

The OS was 7.22.1. The bootloader firmware — RouterBOOT, the RouterBOARD-level code that runs before RouterOS — was still on 6.47.10. This is not the same number as the RouterOS version, it does not move when you upgrade packages, and check-for-updates never mentions it. You upgrade RouterOS for years and the bootloader sits at whatever shipped in the box.

/system/routerboard/upgrade
/system/reboot

It applies on the next boot. Nobody upgrades this because nothing tells you to.

Everything was on#

The service list is where "running fine" turns into a wince. /ip/service/print came back with SSH and Winbox enabled, and next to them:

Telnet. FTP. Plain-HTTP WebFig. The unencrypted API. All listening. The stock RouterOS input firewall drops connections that don't come from the LAN, so none of this was reachable from the internet — that's the one thing standing between this config and a bad afternoon. But "not exposed to the internet" still leaves the LAN. Plaintext telnet and FTP on the LAN means anyone who gets a foothold on any device in the house — a compromised laptop, a chatty IoT bulb — can read the router password off the wire and log in.

The cleanup, service by service. The subnet below is RouterOS's factory LAN, 192.168.88.0/24; if your LAN is a different subnet, put yours in, because a wrong subnet in these three lines locks you out of your own router:

/ip/service/disable telnet,ftp,api,api-ssl,winbox
/ip/service/set ssh address=192.168.88.0/24
/ip/service/set www address=192.168.88.0/24
/ip/ssh/set strong-crypto=yes
/user/set admin address=192.168.88.0/24
/tool/bandwidth-server/set enabled=no
/tool/mac-server/set allowed-interface-list=LAN
/tool/mac-server/mac-winbox/set allowed-interface-list=LAN

Disable the plaintext services and Winbox (unused here). Pin SSH and the web UI to the LAN subnet. Pin the admin user to the LAN so credentials can't be tried from a dst-natted path. Turn off the bandwidth-test server. Confine MAC-telnet and MAC-Winbox — the layer-2 management channels that don't need an IP to reach — to the LAN interface list instead of all. And strong-crypto=yes, which drops the weak SSH ciphers and host-key algorithms RouterOS keeps around for old clients.

While in there: the NTP client was off, so the clock was unset, which quietly breaks certificate validation and makes every log timestamp a lie. Enabled it.

The SSH key you can't paste#

Setting up key auth is where RouterOS makes you earn it. Password SSH kept failing: the password WebFig accepted was refused over SSH. And there's a second trap waiting even once password login works.

RouterOS's default is yes-if-no-key: a user accepts passwords until they have an SSH key imported, at which point password login for that user is disabled. Sensible. It also means the moment you succeed at importing a key, the password path you were using to import it closes. And you can't scp the public key over without a working password in the first place. Chicken, meet egg.

The escape is that RouterOS 7 can build a file from a string, and import reads files:

/file add name=k.pub contents="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... user@host"
/user/ssh-keys/import public-key-file=k.pub user=admin

Two lines, pasted into a terminal that doesn't depend on SSH: WebFig's, MAC-Winbox's (still allowed on the LAN after the cleanup above), or a serial console. No scp, no working password, no file transfer. /file add writes the pubkey to flash as a file; import consumes it. Key auth works on the next connection, and — per yes-if-no-key — the password door closes behind it.

The radios were being polite to attackers#

Two more, on the wireless and VPN side. The Wi-Fi was WPA2-PSK with 802.11w management-frame protection off, which leaves deauth and disassociation frames unauthenticated — the frames every "kick a client off the network" tool forges:

/interface/wireless/security-profiles/set [find default=yes] management-protection=allowed

allowed negotiates protection with clients that support it without locking out those that don't. (Full WPA3 on this hardware means migrating to MikroTik's newer WiFi package, wifi-qcom-ac for this ac chipset; the menu was called wifiwave2 before RouterOS 7.13. A separate job for a separate day.)

And the L2TP server was accepting the entire buffet of auth protocols: its authentication list read pap, chap, mschap1 and mschap2.

PAP sends the password in the clear. CHAP and MS-CHAPv1 are broken well past the point of argument. Tightened to mschap2 only. The server itself stayed: a configured vpn PPP secret said somebody used it, so it got narrowed rather than deleted. MS-CHAPv2 is still not something to lean on, which is why WireGuard went in next to it. That's the next post.

Running fine says nothing about security#

Nothing here was an exotic vulnerability. It was accumulated default state — services that ship enabled, firmware that ships old, auth protocols that ship permissive, a clock that ships unset. The router had been "running fine" precisely because nobody had ever opened it to see how much of the factory posture it was still wearing. Uptime measures whether the thing works. It says nothing about who else it works for. The audit is the only instrument that reads the second number, and running it changes nothing on the router.

Filed under: mikrotik, routeros, security, networking, ssh

Sources#

  • MikroTik: RouterBOARD — routerboard print fields; current-firmware (RouterBOOT) is versioned and upgraded separately from RouterOS via routerboard upgrade.
  • MikroTik: Services — the /ip service list, default-enabled plaintext services, and per-service address restriction.
  • MikroTik: SSH — strong-crypto, and the password-authentication setting whose yes-if-no-key default closes password login once a key is imported.
  • MikroTik: Files — /file add and the file's contents property, the workaround for importing keys without file transfer.
  • MikroTik: Wireless Interface — management-protection on the security profile (802.11w) and what allowed means for clients with and without it.
  • MikroTik: WiFi — the newer WiFi package (called wifiwave2 before 7.13), its wifi-qcom-ac driver for 802.11ac devices including the hAP ac³, and WPA3 support.