Advanced Web Exploitation: Prototype Pollution & SSRF
Deconstruct complex application vulnerabilities: Server-Side Prototype Pollution in Node.js leading to Remote Code Execution (RCE), Blind SSRF bypassing cloud metadata filters (`169.254.169.254`), and GraphQL query depth circular denial of service.
What You Will Learn in This Lesson
- How recursive object merge and `Object.assign` introduce Prototype Pollution via `__proto__` and `constructor.prototype`
- Escalating Prototype Pollution to Remote Code Execution (RCE) via `child_process.fork` environment gadgets
- Advanced SSRF exploitation against AWS/GCP/Azure Instance Metadata Services (IMDSv2)
- Securing GraphQL APIs against Batching Attacks and Circular Nested Query DoS
Introduction & Core Concept
Capital One suffered one of the largest data breaches in history (100M+ customer records leaked) through a Server-Side Request Forgery (SSRF) attack that exfiltrated AWS IAM credentials from the EC2 metadata service.
Syntax & Structure
// Prototype Pollution Payload{"__proto__": {"shell": "/bin/sh", "NODE_OPTIONS": "--inspect"}}// AWS IMDSv2 Token Headercurl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"Simulating Prototype Pollution Gadget Hijacking and Hardening Defense
javascript1234567891011121314151617181920212223242526272829303132333435363738394041424344454647// Prototype Pollution Vulnerability & Defensive Mitigation Engineconst express = require('express');// VULNERABLE FUNCTION: Recursive deep merge without property sanitizationfunction vulnerableDeepMerge(target, source) {for (const key in source) {if (typeof source[key] === 'object' && source[key] !== null) {if (!target[key]) target[key] = {};vulnerableDeepMerge(target[key], source[key]);} else {target[key] = source[key];}}return target;}// HARDENED FUNCTION: Defensive Prototype-Safe Mergefunction secureDeepMerge(target, source) {for (const key in source) {// Block dangerous prototype poisoning keys!if (key === '__proto__' || key === 'constructor' || key === 'prototype') {continue;}if (typeof source[key] === 'object' && source[key] !== null) {if (!target[key]) target[key] = Object.create(null); // Dictionary with no prototype!secureDeepMerge(target[key], source[key]);} else {target[key] = source[key];}}return target;}// 1. Attacker Payload attempting to pollute global Object prototypeconst maliciousPayload = JSON.parse('{"__proto__": {"isAdmin": true, "role": "SUPERADMIN"}}');console.log("=== Server-Side Prototype Pollution Defense Engine ===");console.log("Global Object isAdmin before attack:", ({}).isAdmin); // undefined// Testing Safe Mergeconst userConfig = {};secureDeepMerge(userConfig, maliciousPayload);console.log("Global Object isAdmin after secure merge:", ({}).isAdmin); // undefined (Clean!)// Object.freeze prevention demonstrationObject.freeze(Object.prototype); // Locks root prototype permanently!console.log("✅ Object.prototype frozen permanently: System immune to prototype tampering!");
Line-by-Line Technical Breakdown
Try It Yourself (Interactive Editor)
Modify the code in real-time and click Run to test live browser output and console logs.
Common Mistakes & How to Avoid Them
#1: Relying on simple blacklist URL filters for SSRF (e.g. blocking `http://127.0.0.1`), which can be bypassed with DNS Rebinding or decimal IPs (`http://2130706433`).
Attackers register domain names with short TTL that resolve to a public IP first and a private IP (169.254.169.254) on subsequent lookups (DNS Rebinding).
if (url.includes('127.0.0.1')) block(); // Easily bypassed via 0.0.0.0 or DNS rebinding// Resolve DNS IP first, verify IP is not in private RFC1918 or link-local range, then fetchIndustry Best Practices & Professional Standards
- Execute `Object.freeze(Object.prototype)` at the entry point of Node.js microservices.
- Enforce IMDSv2 (`HttpTokens=required`) on all AWS EC2 and container instances.
- Use GraphQL query cost analysis and max depth limiters (e.g., `graphql-depth-limit`) to prevent nested query denial of service.
Lesson Summary & Core Takeaways
- Prototype Pollution corrupts global JavaScript object inheritance, leading to logic bypass and RCE.
- SSRF targets internal cloud metadata services to steal IAM credentials.
- Deep input validation, Object.freeze, and IMDSv2 mitigate advanced web attack vectors.