Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prototype injection vulnerability #12

Open
sabberworm opened this issue May 10, 2021 · 0 comments
Open

Prototype injection vulnerability #12

sabberworm opened this issue May 10, 2021 · 0 comments

Comments

@sabberworm
Copy link

I recently opened a PR (scssyworks/deparam.js#24) on deparam.js, another fork of jQuery BBQ’s deparam. The PR fixes a prototype pollution vulnerability that happens because browsers support the non-standard-but-de-facto -universal __proto__ magic property to access an object’s prototype.

I found that objects created using Object.create(null) don’t have this vulnerability:

diff --git a/src/deparam.js b/src/deparam.js
index 76c4166..a7ada2e 100644
--- a/src/deparam.js
+++ b/src/deparam.js
@@ -10,7 +10,7 @@ const coerce_types = {'true': !0, 'false': !1, 'null': null};
 
 export default function (params, coerce) {
   // console.log(params)
-  const obj = {};
+  const obj = Object.create(null);
 
   // Iterate over all name=value pairs.
   params.replace(/\+/g, ' ').split('&').forEach(function (v) {
@@ -65,7 +65,7 @@ export default function (params, coerce) {
         for (let i = 0; i <= keys_last; i++) {
           key = keys[i] === '' ? cur.length : keys[i];
           cur = cur[key] = i < keys_last
-            ? cur[key] || (keys[i + 1] && isNaN(keys[i + 1]) ? {} : [])
+            ? cur[key] || (keys[i + 1] && isNaN(keys[i + 1]) ? Object.create(null) : [])
             : val;
         }

This fixes the problem for the following cases:

deparam('__proto__[test]=1'); // Will put test on Object.prototype
deparam('test[__proto__][test]=1'); // Will put test on Object.prototype

It’s still present in arrays, however:

deparam('test[]=1&test[__proto__][test]=2'); // Will put test on Array.prototype
deparam('test[]=1&test[__proto__][__proto__][test]=2'); // Will put test on Object.prototype

https://github.com/scssyworks/deparam.js coerces arrays to objects as soon as a non-numeric index is accessed, so the fix from there is not directly translatable to this project.


Let me take this moment to say that introducing __proto__ was one of the great mistakes in the history of JavaScript… Granted, Symbol hadn’t been invented yet so obj[Symbol.proto] or similar might have seemed non-trivial at the time but the now-standard way Object.getPrototypeOf(obj)/Object.setPrototypeOf(obj, {}) was definitely an option back then…

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

No branches or pull requests

1 participant