Skip to content

Fix proto method clobbering#1066

Open
GrosSacASac wants to merge 6 commits intomasterfrom
fix-proto-method-clobbering
Open

Fix proto method clobbering#1066
GrosSacASac wants to merge 6 commits intomasterfrom
fix-proto-method-clobbering

Conversation

@GrosSacASac
Copy link
Contributor

Thanks for Byambadalai @ByamB4 for the report


Denial of Service via crafted form field
names.

Summary

formidable uses plain {} objects to store parsed form fields.
User-controlled field names overwrite inherited Object.prototype
methods (toString, valueOf, hasOwnProperty, constructor), potentially
causing unsafe downstream code to crash with TypeError.

Result

TypeError crashes on String() coercion and hasOwnProperty() calls.

Example

import http from 'http';

import formidable from '../src/index.js';


const server = http.createServer((req, res) => {
    const form = formidable();
    form.parse(req, (err, fields, files) => {

        if (err) {
            console.error(err);
            res.writeHead(err.httpCode || 400, { 'Content-Type': 'text/plain' });
            res.end(String(err));
            return;
        }
        try {
            String(fields);
        } catch (e) {
            console.log('CRASH:', e.message);
        }
        try {
            fields.hasOwnProperty('x');
        } catch (e) {
            console.log('CRASH:', e.message);
        }
        // res.end('ok');

        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ fields, files }, null, 2));
    });
});
server.listen(3000);
curl -X POST -H "Content-Type: application/json" -d '{"toString":"x","hasOwnProperty":"x"}' http://localhost:3000`

Impact

Any application using formidable where downstream code calls
hasOwnProperty(), String(), or uses string concatenation/template
literals on the parsed fields object will crash with TypeError.

Common vulnerable patterns in downstream code:

  • if (fields.hasOwnProperty("name")) {} - TypeError
  • const msg = "Data: " + fields - TypeError
  • String(fields) or template literal interpolation - TypeError

Fix

fields and files now use Object.create(null) as a basis.

This means the error that could appear when receiving specifically crafted input, will now always appear instead.

This will hopefully force you to use safer code that does not use unsafe methods, on user input.

Upgrade Guide

If you already use a good linter, no further action is required.

Otherwise read below:

Find every occurence where fields and files are used in your code as a whole object. Adhere to the following:

Old and New

old:

if (fields.hasOwnProperty("name")) {}

new:

if (Object.hasOwn(fields, "name")) {}

old:

const msg = "Data: " + fields

new:

Convert to String individual fields instead, that are known and validated before
const msg = "Data: " + fields.a + fields.b

old:

const msg = `Data: ${fields}`

new:

Convert to String individual fields instead, that are known and validated before
const msg = `Data: ${fields.a} ${fields.b}` etc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant