Ask whoever runs your network which hosts speak MQTT. The usual answer is that none of them do, because you do not operate an industrial sensor fleet. Research that Lumen's Black Lotus Labs published on Tuesday turns that answer from a fact into a blind spot.
The report covers BambooToken, a malware family the team assesses has been operating since February 2023 and which now runs command and control over MQTT, the publish-and-subscribe protocol designed for telemetry. Lumen's write-up and the indicator list Black Lotus Labs released with it name seven command-and-control nodes, three MQTT ports (1883, 2883 and 8883), and roughly a dozen compromised enterprises across Asia and South America. Several of those nodes were still answering on September 14.
Read the victim list slowly. A hotel in Vietnam. A law firm in Chile. A biomedical company in Argentina. A financial services firm in Malaysia. Software development shops in Hong Kong and Vietnam, and a cryptocurrency site operating out of Lithuania. Alongside them, about 150 small MikroTik and DrayTek routers in Singapore, Cambodia and Vietnam, found through SNMP scanning that Lumen first observed on December 15, 2025. Those are organisations with an IT person, not a security operations centre.
Who this is for, and who can stop reading
The honest version first. If you run a company in North America or Europe on Microsoft 365, a fleet of laptops, and a firewall from a mainstream vendor, BambooToken is unlikely to turn up in your environment. It arrives by sideloading into Tendyron's OnKey USB-token software, which is banking middleware used mainly in China, or by impersonating Kingsoft Office. If neither has ever been installed on your network, you can close the tab on the malware itself.
Three groups should keep reading. The first runs MQTT deliberately: building automation, manufacturing telemetry, a product with a connected device fleet, anything with a Mosquitto or EMQX broker in it. The second has MikroTik or DrayTek gear at the edge with SNMP answering from the internet. The third is everyone else, for one reason. The question this research puts to your stack is cheap to answer and most stacks fail it: does anything you own write a log line when a workstation opens a TCP session to port 8883?
I would rather a client spend tonight answering that and find nothing than spend this quarter buying another detection product. An egress gap you have measured is a smaller problem than one you have assumed away.
The belief this breaks: command and control looks like beaconing
Most detection content rests on one mental model. An implant makes repeated outbound HTTPS connections to a domain nobody recognises. You catch it on the regularity of the interval, the age of the domain, the TLS fingerprint, or the absence of a proxy category. Every step assumes the implant talks to the attacker.
MQTT removes that assumption. A broker sits in the middle. The implant connects to the broker and subscribes to a topic; the operator connects to the same broker and publishes into it. Flow records on your side show one thing: a session to a broker. There is no second endpoint to pivot on, and the operator's address never appears in your logs at all.
The rest of the protocol solves, as ordinary features, the problems that usually give an implant away:
- Heartbeats are correct behaviour. The MQTT 5.0 standard requires a client with a non-zero Keep Alive to send a
PINGREQwhen it has nothing else to send. Regular, identical, low-volume traffic is what a healthy MQTT client looks like. Beacon-interval analytics tuned on HTTPS callbacks have no opinion about it. - Offline hosts stay reachable. A client that reconnects with Clean Start set to
0gets its session state back, and anything published at QoS 1 or 2 while it was away is delivered on reconnect. A laptop shut for a week collects its backlog on Monday morning, and the operator never had to retry against a dead host. - The ports are registered and dull.
1883and8883are the assigned MQTT and secure-MQTT ports. A proxy that sets policy by site category has no category for either, and TLS on8883hides the payload from anything doing string matching. Lumen recorded2883in use as well. - Targeting is just a string. The report lists per-infection topics keyed to a GUID, with the suffixes
/Plugin,/removePluginand/unPluginon Windows and/LUAon Linux, plus a global broadcast topic for reaching every host at once. The Windows build XOR-decodes its GUID at runtime and reuses it as a mutex.
The implant is unglamorous, and that is the point. Three handlers are implemented: SHELL spawns a command shell, FILEEX uploads, downloads, deletes and executes files, and ONLINE reports host details and keeps the heartbeat running. Dead code shows unfinished keylogging, clipboard, audio and webcam modules that nobody bothered to finish. An attacker holding a shell and file transfer on a law firm's file server has no use for the webcam.
The delivery step that never touches PowerShell
Early samples staged with PowerShell: allocate memory, run the payload, and generate precisely the process-creation telemetry that every EDR rule set was written against. Current versions dropped it. A legitimate, signed Tendyron binary, OnKeySrv.exe, loads a rogue OnKeyToken_KEB.dll placed beside it. Lumen states plainly that they do not assess Tendyron's code-signing certificate was compromised. The signature on the executable is genuine. The DLL next to it is the attacker's.
That shape outlives this campaign. The DLL name will change, the abused vendor will change, and the technique keeps working against any control that decides trust by looking at the parent process. The detection that survives is image-load telemetry. Sysmon Event ID 7 records every module loaded into a process along with its signature status, and on a normal estate a signed service loading an unsigned DLL out of a user-writable directory is a short list. Event 7 is disabled by default and needs the -l switch, and Microsoft's own documentation warns that logging every image load is expensive. Filter it to unsigned modules and it stays affordable.
Three checks you can finish tonight
Start with egress, because it is answerable from logs you already keep and it costs about ten minutes.
# 1. Does anything you own speak MQTT outbound?
# 1883 = MQTT, 8883 = secure MQTT, 2883 = also used in this campaign.
# Splunk, against a firewall or flow index:
index=firewall action=allowed dest_port IN (1883, 2883, 8883) earliest=-30d
| stats count AS sessions, dc(dest_ip) AS brokers,
earliest(_time) AS first_seen, latest(_time) AS last_seen
BY src_ip, dest_port
| sort - sessions
# Microsoft Defender for Endpoint or Sentinel:
DeviceNetworkEvents
| where Timestamp > ago(30d)
| where RemotePort in (1883, 2883, 8883)
| where ActionType == "ConnectionSuccess"
| summarize Sessions = count(), Brokers = dcount(RemoteIP),
First = min(Timestamp), Last = max(Timestamp)
by DeviceName, InitiatingProcessFileName, RemotePort
| order by Sessions desc
# Zeek, no MQTT analyzer required:
zeek-cut id.orig_h id.resp_h id.resp_p duration < conn.log \
| awk '$3 == 1883 || $3 == 2883 || $3 == 8883'
An empty result is the good outcome, and it is also the answer to the question in the previous section: your stack can see this traffic class. Any result splits two ways. A broker you own belongs in an inventory and an allowlist. A broker you do not own, reached by a workstation, is an incident.
Then the sideloading pattern
# 2. A signed service loading an unsigned DLL from a writable path.
# Requires Sysmon with image-load logging enabled (sysmon64 -l or an
# <ImageLoad> filter in the config).
$events = Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-Sysmon/Operational'; Id = 7
} -MaxEvents 50000 -ErrorAction Stop
$events | ForEach-Object {
$d = @{}
([xml]$_.ToXml()).Event.EventData.Data |
ForEach-Object { $d[$_.Name] = $_.'#text' }
[pscustomobject]$d
} | Where-Object {
$_.Signed -eq 'false' -and
$_.ImageLoaded -match '\\(Users|ProgramData|AppData|Temp)\\'
} | Select-Object Image, ImageLoaded, Company |
Sort-Object ImageLoaded -Unique | Format-Table -AutoSize
Tune the path list to your estate rather than trusting mine. The signal you want is the pairing: a process with a real vendor signature, loading a module with none, from a directory a standard user can write to.
Then the named infrastructure
Search DNS, proxy and firewall logs for the two parent domains rather than the individual hosts. Subdomains are cheap and get rotated; the registrations last longer.
c2iznja[.]com- the current parent, seen withapi80,live-hk,turbo,base64,cacheandnewdmaas subdomains.chat5188[.]tk- the 2023 and 2024 infrastructure, withapi06,api08,apisandchat. Several sit behind Cloudflare, so a DNS answer alone will not tell you much.- Hosting addresses
202.144.192[.]149,210.1.231[.]13,210.1.226[.]238,43.245.198[.]195and43.245.198[.]238, each with MQTT and an SSH service on a high port.
If you actually do run MQTT
The controls are the ones a broker deployment should already have, and rarely does.
- Name the broker. One host, one address, an egress rule to that address and nothing else on
1883,2883or8883. - Use mutual TLS for client authentication rather than a username and password carried over
8883. A shared credential in device firmware is a credential the attacker has too. - Write topic ACLs per client identifier. A client permitted to subscribe to
#reads the entire bus, including every other device's telemetry. - Ship the broker's own logs. Mosquitto records CONNECT and SUBSCRIBE with the client identifier; almost nobody collects that file, and it is where a rogue subscriber shows up first.
Put the three MQTT ports in your egress policy tonight
Lumen's own defensive advice is one line long: watch for MQTT traversing outside the network. Take it literally and finish it tonight, in this order. Run the egress query over the last thirty days. Write down every broker the results name, or write down that there were none. Then add a default-deny rule for 1883, 2883 and 8883 with an exception for the brokers on that list, and point the Sysmon image-load filter at unsigned modules while you are in the console. The whole sequence fits in an evening, and it holds against the next campaign that picks a protocol your tooling was never asked about.
If the query returns rows you cannot explain, or your logs cannot answer the question at all, that gap is worth more attention than this malware family. We work with teams on exactly that problem: deciding which traffic classes their pipeline can actually see, and closing the ones it cannot.
Drowning in alerts? We can help.
We help security teams optimize their detection pipelines and reduce alert fatigue. Book a session to discuss your SIEM environment.
