HIGH prototype pollutionbasic auth

Prototype Pollution with Basic Auth

How Prototype Pollution Manifests in Basic Auth

Prototype pollution in Basic Auth contexts creates unique attack vectors that exploit the way authentication systems handle user-provided data. When Basic Auth credentials are processed by Node.js applications, they often flow through deserialization routines that can be manipulated to inject malicious properties into JavaScript's prototype chain.

The most common Basic Auth prototype pollution occurs when applications parse Authorization headers and convert the Base64-decoded payload into objects. Consider this vulnerable pattern:

const { username, password } = JSON.parse(atob(credentials));
// Malicious payload: eyJ1c2VybmFtZSI6InRlc3QiLCJjb250ZXh0Ijp7InByb3RvIjoidmFsI
// Decodes to: { "username": "test", "__proto__": { "admin": true } }

Once the malicious object is created, the admin property becomes available on all objects through prototype inheritance. In Basic Auth systems, this can bypass authorization checks:

function checkAuth(user) {
  if (user.admin) { // Now true due to prototype pollution
    return 'admin';
  }
  return 'user';
}

Another attack pattern involves polluting the constructor property of the prototype. Basic Auth middleware that performs role-based access control might check user roles like this:

const user = getUserFromDatabase(username);
if (user.role === 'admin') {
  // Access granted
}

With prototype pollution, an attacker can set constructor.prototype.role = 'admin', causing all user objects to appear as administrators regardless of their actual database values.

Express.js applications using Basic Auth middleware are particularly vulnerable when they merge request data without proper validation. The pollution can spread through the request object:

app.use((req, res, next) => {
  const auth = req.headers.authorization;
  if (auth) {
    const [username, password] = Buffer.from(auth.split(' ')[1], 'base64')
      .toString()
      .split(':');
    req.user = { username, password };
    // Prototype pollution here if username/password contain malicious objects
  }
  next();
});

The pollution becomes especially dangerous when Basic Auth systems use the polluted properties for database queries or configuration objects, potentially leading to data exfiltration or privilege escalation.

Basic Auth-Specific Detection

Detecting prototype pollution in Basic Auth systems requires examining both the authentication flow and the data processing pipeline. The first step is identifying where Base64-decoded credentials are converted to objects or merged with existing data structures.

Static analysis should focus on these patterns:

// Dangerous patterns to flag
const user = { ...JSON.parse(atob(credentials)) };
Object.assign(target, JSON.parse(atob(credentials)));
const obj = eval('(' + atob(credentials) + ')');

Dynamic testing involves sending specially crafted Basic Auth headers that attempt to set prototype properties. A test payload might look like:

const malicious = Buffer.from(JSON.stringify({
  username: 'test',
  __proto__: { admin: true }
})).toString('base64');

middleBrick's scanner specifically tests for these Basic Auth prototype pollution patterns by attempting to inject properties like admin, constructor, and prototype through the Authorization header. The scanner checks if these properties persist in the application's response or affect authorization decisions.

Runtime detection should monitor for unusual property access patterns on objects that originate from authentication data. Tools like Object.prototype.watch (in older environments) or Proxy-based monitoring can detect when prototype properties are being accessed unexpectedly.

Network-level detection is also valuable. Basic Auth endpoints that accept credentials and return different responses based on injected properties indicate a successful prototype pollution attack. The scanner verifies this by checking for response variations when sending payloads with different prototype properties.

middleBrick's Basic Auth-specific checks include:

  • Prototype property injection attempts (__proto__, constructor, prototype)
  • Authorization bypass detection through property manipulation
  • Response analysis for signs of prototype pollution success
  • Cross-referencing findings with OpenAPI specifications to identify risky parameter handling

The scanner's LLM security module also checks if prototype pollution attempts are logged or exposed in error messages, which could leak sensitive information about the application's internal structure.

Basic Auth-Specific Remediation

Remediating prototype pollution in Basic Auth systems requires a defense-in-depth approach that validates and sanitizes all credential data before processing. The most effective strategy combines input validation, safe parsing, and secure coding practices.

First, never parse credential data as JSON or other structured formats unless absolutely necessary. Basic Auth credentials should be treated as simple strings:

const [username, password] = Buffer.from(auth.split(' ')[1], 'base64')
  .toString()
  .split(':');

If you must parse structured data from credentials, use a safe parser that prevents prototype pollution:

const parseSafe = require('parse-safe'); // Library that prevents prototype pollution
const credentials = parseSafe(atob(authHeader.split(' ')[1]));

Implement strict property validation on all objects derived from user input:

function validateUserObject(obj) {
  const allowedProperties = ['username', 'password', 'role'];
  const keys = Object.keys(obj);
  for (const key of keys) {
    if (!allowedProperties.includes(key) || key.startsWith('__')) {
      throw new Error('Invalid property in user object');
    }
  }
  return obj;
}

Prevent prototype pollution at the object creation level:

function createUser(username, password) {
  const user = Object.create(null); // No prototype chain
  user.username = username;
  user.password = password;
  return user;
}

For applications that must handle complex credential structures, use Object.freeze on critical objects:

const config = Object.freeze({
  adminRole: 'admin',
  maxLoginAttempts: 5
});

middleBrick's remediation guidance includes specific code examples for each vulnerability found. For prototype pollution in Basic Auth, the scanner recommends:

  • Replacing unsafe object merging with explicit property assignment
  • Using Object.create(null) for credential objects
  • Implementing property whitelist validation
  • Adding runtime checks for unexpected prototype properties

The scanner also provides compliance mappings showing how these fixes address OWASP API Top 10 risks and help meet regulatory requirements like PCI-DSS and SOC2.

For CI/CD integration, middleBrick can automatically fail builds when prototype pollution vulnerabilities are detected in Basic Auth endpoints, ensuring these issues are caught before deployment.

Frequently Asked Questions

How can I test if my Basic Auth endpoint is vulnerable to prototype pollution?
Send a Base64-encoded payload containing __proto__ properties through the Authorization header. For example, encode { "__proto__": { "admin": true } } and check if the application's authorization logic is affected. middleBrick automates this testing with specialized payloads and verifies if the pollution persists in application responses.
Does prototype pollution in Basic Auth affect all programming languages?
No, prototype pollution is specific to JavaScript and environments where objects inherit from prototypes. Languages like Python, Java, or Go don't have this vulnerability pattern. However, if your Basic Auth system uses JavaScript on the backend (Node.js, browser-based auth), you need to implement these specific protections.