
Someone broke into our server in November. Here is how we threw them out and rebuilt it in a day.
React2Shell is still being exploited in November 2026. Its patch is almost a year old, and the attacker who hit us has a Monero wallet that is mining from about two dozen machines right now. Below you will find fresh indicators of compromise from our incident, which we could not find published anywhere else: see "Indicators of compromise" further down.
Between 8 and 14 November 2026, that attacker got into our production server through a public Next.js bug called React2Shell (CVE-2025-55182). They stole what they could read, and on 14 November they dropped a cryptominer.
On the same day the server was stopped, we rebuilt it from zero. By the end of 14 November (UTC) every one of our apps was back online on a fresh server, every site on HTTPS, every stolen key being replaced, and the box now watching itself.
This post is the timeline, what the attack looks like, and exactly what we changed. If you self-host Next.js, the part about the logs is the one to read.
The attack
React2Shell is a remote code execution bug in React Server Components, the code Next.js uses to run server-side React. It was fixed upstream in Next.js 15.2.6. The attacker used it against one of our Next.js sites.
Timeline, from the web server logs and file timestamps on the old disk:
- 12 November, 11:35:43 UTC: one source sends the exploit to our site, then probes for .git and .env files. One second later a credential stealer script is written to the temp folder and run. It reads environment files, SSH keys and tokens and tries to upload them to a command server. Its own error file shows those uploads failed.
- 14 November, 11:12 UTC: a second source sends ten POST requests to a made-up path, /adfa. An XMRig miner is dropped and starts mining Monero.
- 14 November: the server is stopped by our hosting provider, the same day the miner landed.
What the logs hid
This is the part worth knowing if you run Next.js yourself.
The output of the attacker's commands came back inside the error "digest" field of the response. Every exploit request looked like a normal HTTP 200 in the access log. Counting failed logins or 4xx errors shows nothing. The log looks clean while the attack is happening.
So a log watcher alone will not catch this. You need something that watches what the server does, not only what it answers.
How we traced it
We mounted the old disk read-only and walked every step: the scan, the exploit, the stealer, the miner. Then we wrote a scanner for every trace this attack leaves on disk and ran it against the old disk. Every known trace was found, zero missed. The same scanner came back clean on the new server before any app went on it.
We treated every secret on the old server as stolen. Not "probably fine". Stolen.
What we rebuilt, 14 November
We did not clean the old server. We installed a fresh one and brought the apps over one by one, under new rules.
One locked user per app. The old setup ran the apps under one Linux user. The new one gives every app its own user: no shell, no login, no sudo. Each app runs as a hardened systemd service: no new privileges, read-only system, no access to home folders, private temp, no capabilities, a memory cap. The app cannot write its own code, so an attacker cannot plant something that survives a restart. Each app also has its own database login that owns only its own database.
Secrets out of the code. Environment files no longer sit in the app's code folder. They live in a root-managed place, and each app can read only its own file. A daily encrypted backup of them goes off the box.
Every stolen key replaced. Database passwords, session and signing secrets, payment webhook secrets, Google sign-in secrets, mail app passwords, Apple sign-in keys, cloud and backup keys, deploy keys. Old keys revoked or disabled at the provider, not just swapped on our side. Every user of two of our apps had to log in again because we replaced their session secret. That is the point.
App ports closed to the internet. Apps listen on the box only. From outside, only the web server answers. It runs fresh configs (the old ones were treated as untrusted), with rate limits, security headers, and a guard that drops this exploit's request shape before it reaches any app.
Every Next.js app patched, twice over. React2Shell is fixed on every app. And on 15 November two more critical, unauthenticated remote code execution bugs landed in Next.js's image optimizer (/_next/image): GHSA-2xp9-vwfh-vxw4 and GHSA-2464-fhr4-w9xw. We swept all our Next apps the same day. Apps on current lines moved to the fixed releases (15.5.29, 16.4.6). Older apps where no fix exists got the image optimizer switched off, one config line that closes the hole. Every build passed before it shipped.
No deploys from the internet onto the box. Self-hosted CI runners are gone from production. Deploys come in through one locked-down deploy path, using per-repo read-only keys that cannot read each other's repos.
Fewer servers. The site that was hit needs no server code, so it is now plain static files served by nginx. No Node process, nothing to exploit.
The box watches back now
Falco and auditd run on the server, watching what processes do and what files and accounts change. Both were tested by firing harmless fake events before we trusted them. They start in observe mode: every alarm is logged and checked before any rule is allowed to act on its own, because a false alarm on a production box is an outage.
zetta-sentinel, our own watchdog, is being finished now. It is written in Rust and sits on top of Falco and auditd. It looks for things that never happen on a healthy server: an app starting a shell, running something from a temp folder, talking to a host it has no reason to talk to, burning CPU with no traffic, touching files it has no business near. Alerts go out by email. It falls back to its own checks if Falco or auditd ever stops, and alerts when that happens. It is installed on the box; it goes live in observe mode first, one rule at a time.
zetta-patchbot is next: on a separate machine, never on the server it protects, it will bump Next.js and React when a fix ships, build, test and open a pull request. A radar on public advisory feeds tells us about a new bug the day it appears.
Making a stolen secret worth nothing
There is a hard truth here: no secret an app reads is unstealable, because the app has to read it to use it. So the goal is a break-in that steals nothing reusable. Four properties:
- Isolated: one app cannot read another's. Done.
- Not stored as plain text on disk. Next.
- Bound to the server: a key that only works from our box is dead anywhere else. Next, provider by provider.
- Short-lived: a key that expires before anyone can use it. Later.
What we are sharing
The same night, we reported the attacking addresses and the stealer's upload server to their networks: Google Cloud, M247 and Cloudzy, with exact times, request lines and file hashes, and asked each to take the hosts down and preserve their logs. Both attacking addresses are listed on AbuseIPDB. The miner's wallet goes to its mining pool next. Legal routes only. We are not going after anyone.
We built a small guard for people who self-host Next.js: it checks your installed versions against advisories and ships web server rules and log patterns for this exploit shape. It is not public yet. The sentinel and the patch bot will be open-sourced once they have run on our real server and proved themselves.
Indicators of compromise (fresh, not published anywhere else)
As of 15 November 2026 we found no public record of these values. If you run Next.js, search your logs and disks for them. Times are UTC.
Where the attacks came from
- 34.40.134.70 sent the 12 November exploit and dropped the credential stealer.
- 217.138.216.212 sent the 14 November exploit and dropped the miner. It is a known scanner on public threat feeds, run from M247 (Berlin).
- Request pattern: POST /adfa, ten requests in about five seconds. Earlier probing with the same path started on 8 November.
- User agent: Mozilla/5.0 (compatible; EnvScanner/2.0)
The credential stealer (12 November)
- Dropped as a hidden script in the temp folder, named /tmp/.<hex>.sh (ours was a nine-character hex name, about 94 KB). It collects environment files, SSH keys, passwords and cloud credentials, and writes them to a hidden loot folder next to it.
- Upload address hard-coded in the script: http://153.75.95.223:8080. That address is in the network of Cloudzy (RIPE object AE-CLOUDZY-19910923, routed by AS14956). Some threat feeds still label it with an older owner; the registry says Cloudzy.
- Stealer SHA-256: 2ccff5c692bbc10b07bb2ef7923cdee599d8841d2bb4a6c3f1c62f0ef35e38ea
The miner (14 November)
- XMRig 6.22.0, copied to a hidden folder at ~/.cache/.sys/xmrig one second after the archive xmrig.tar.gz landed in the temp folder, and started at once.
- Pool: gulf.moneroocean.stream:10128
- Wallet: 8B6PDz5F9K6cAi7AzpV4HNiu588sinxeDUM6AAJhpZdw3qi2N2A8gwa3mD5kphJDkAALarNRuJNi9Fj2zzYGuyR2JEPx1b3
- Miner binary SHA-256: fd11982f252c060a1372e81d5be57589647052b56281a5c54975ca22164f7726
- Archive SHA-256: cb49ae0793b257fd95892cb5eb777b9fe0d61a4015c7926cb68a3d353ed6accd
Why this is a warning
On 15 November the pool's public numbers showed that wallet mining at about 128 kH/s from 24 named workers, with its last share on 14 November. The hash total fits a campaign that began around 8 November. That is roughly two dozen other machines working for the same attacker, and some of them are probably unpatched Next.js servers whose owners have not noticed. If you find any of the values above, assume a full compromise, not just a miner. We reported the source addresses to their networks and the wallet to its pool.
If you self-host Next.js
- Upgrade now. React2Shell is fixed in 15.2.6 and later. The two image optimizer bugs are fixed in 15.5.28 / 16.4.1 and later; on lines with no fix, set images.unoptimized: true.
- Do not trust a clean access log. This attack returns HTTP 200.
- Give every app its own locked user. No self-hosted CI runners on the production box.
- Keep app ports off the internet. Only the web server should answer.
- Block outbound traffic from app users by default. A miner, a reverse shell and a data upload all need to get out.
- Keep secrets out of the code folder, and bind each key to your server where the provider allows it.
- If a site needs no server code, do not run one.
We got hit, we traced every step, we rebuilt in a day, and the server watches back now. Questions welcome.
2025-05-15

Why Learning to Code is Essential in the Age of AI (And How ZettaByte Empowers You)
As AI reshapes tech, coding remains a critical skill. Discover why human ingenuity thrives alongside AI and how ZettaByte prepares learners for the future.💡💻
2025-03-23

From Idea to Implementation: Understanding the Software Development Life Cycle (SDLC)
Discover the Software Development Life Cycle (SDLC) and how it transforms ideas into functional software. Learn about planning, design, development, testing, and deployment to ensure project success. 🚀
2025-03-20

How Customer Data & Machine Learning Can Enhance Customer Experience
Discover how combining customer data with machine learning can revolutionize customer experience. Learn actionable strategies to deliver personalized services, predict customer needs, and boost satisfaction.
2025-03-16

How to Create a Software Development Project Plan: A Step-by-Step Guide
Learn how to create a comprehensive software development project plan to ensure success. Discover key steps, tools, and strategies to manage timelines, resources, and risks effectively.
2025-03-13

The Importance of User-Centered Design in Software Development 🎯
Discover the importance of User-Centered Design (UCD) in software development and how it drives success. Learn how prioritizing user needs enhances UX, boosts engagement, and delivers competitive advantage.
2025-03-09

Digital Transformation for SMEs: Strategies to Boost Growth & Profitability
Discover how SMEs can leverage digital transformation to enhance efficiency, reduce costs, and drive sustainable growth. Learn actionable strategies to overcome challenges and thrive in a competitive market.
2025-03-06

ERP vs. Traditional Systems: Why Your Business Needs an Upgrade
Discover the key differences between ERP and traditional systems, and learn why upgrading to an ERP solution can transform your business operations, efficiency, and growth.
2025-03-04

Protect Your Business: How to Create a Cybersecurity Strategy That Works in 2025
Learn how to create a robust cybersecurity strategy for your small business. Discover key steps, tools, and best practices to protect your operations, data, and reputation from cyber threats.
2025-02-27

THE FUTURE OF POS TECHNOLOGY: What Your Business Deserves in 2024
Discover how cutting-edge POS technology can revolutionize your business operations. Explore benefits, key features, and why Zettabyte Incorp is your partner for tailored POS solutions. Innovative POS Technology Is What Your Business Deserves
2025-02-23

Dynamic Design Made Simple: Motion UI for React Developers
Discover how Motion UI transforms static web interfaces into dynamic, engaging experiences for React developers. Learn about popular libraries like Framer Motion, React Spring, and GSAP, and elevate your app’s design with seamless animations.
2025-02-20

Scaling Customer Success Without Losing the Personal Touch: How Zettabyte Can Help
Discover how AI-powered ERP systems are revolutionizing business operations in 2025. Learn about their benefits, key features, and how ZettaByte Technology can help you implement cutting-edge ERP solutions for your business.
2025-02-16

Why Choosing the Right Software Development Vendor Matters
Choosing the right software development vendor is crucial for your business success. Learn the key factors to consider, from experience and tech stack to pricing and communication, and find a reliable partner for your project.
2025-02-13

A Unified Approach to IT Success: Enterprise, Solution, and Technical Explained
What makes IT systems successful? Meet the three key architects—enterprise, solution, and technical—who align business goals with technology to drive innovation and efficiency.
2025-02-09

Scaling Customer Success Without Losing the Personal Touch: How Zettabyte Can Help
Learn how Zettabyte enables businesses to scale customer success while maintaining a personal touch. Explore effective tech-touch strategies that enhance customer engagement and streamline support process
2025-02-06

Google Search Ranks AI Spam Above Original Reporting: A Growing Concern
Google adjusted its policies to target AI spam earlier this year, but plagiarizing content still comes up higher in search results months later—Discover the growing concern of Google prioritizing AI-generated content over original reporting in search results.
2025-01-31

The Rise of DeepSeek R1: Challenging ChatGPT in Software Development
Among the emerging players, DeepSeek R1 is positioning itself as a strong competitor to ChatGPT. Learn how Zettabyte Software Company can leverage AI to enhance productivity, streamline processes, and drive innovation
2025-01-30

From Chaos to Clarity: How ZettaByte Transforms Your Data into a Strategic Asset
Learn the importance of data management for boosting efficiency, empowering decision-making, and ensuring compliance. Explore practical strategies and essential tools to unlock the full potential of your data.
2025-01-28

Navigating Canada’s Immigration Challenges: The Role of Technology in Addressing Economic and Housing Crises
While immigration has long been a cornerstone of Canada’s growth, the current situation demands innovative solutions to ensure a balanced and sustainable future. At ZettaByte Technology, we believe that technology can play a pivotal role in addressing these issues. Here’s how we’re leveraging our expertise to make a difference.