storybookjs / telejson

πŸ›° JSON parse & stringify with support for cyclic objects, functions, dates, regex, infinity, undefined, null, NaN, Classes, Instances
MIT License
169 stars 29 forks source link

Security Fix for Arbitrary Code Execution - huntr.dev #61

Closed huntr-helper closed 3 years ago

huntr-helper commented 3 years ago

@zpbrent (https://huntr.dev/users/zpbrent) has fixed a potential Arbitrary Code Execution vulnerability in your repository πŸ”¨. For more information, visit our website (https://huntr.dev/) or click the bounty URL below...

Q | A Version Affected | 5.1.0 Bug Fix | YES Original Pull Request | https://github.com/418sec/telejson/pull/2

If you are happy with this disclosure, we would love to get a CVE assigned to the vulnerability. Feel free to credit @zpbrent, the discloser found in the bounty URL (below) and @huntr-helper.

User Comments:

πŸ“Š Metadata *

The telejson.reviver() which is used to parse string data back to json structure can be abused to execute arbitrary code when the lazyEval option is set to false (i.e., disabled). The root cause is the attackers can purposely inject a bracket at the end of the function property (invoking IIFE), that may be stringified by telejson.replacer() or telejson.stringify(). Even worse, despite the default value of lazyEval option is set to true for telejson.parse(), the telejson.reviver() have that vaule as false by default.

Bounty URL: https://www.huntr.dev/bounties/1-npm-telejson/

βš™οΈ Description *

Sanitize the brackets at the end of the function property for the input string to telejson.reviver(), since the normal use of telejson.replacer() and telejson.stringify() cannot make brackets at the end of the function property for the json objects.

πŸ’» Technical Description *

const sourceSanitized = source.replace(/[(\(\))|\\| |\]]*$/,''); This fix has considered the bypass possibility such as multiple ( ) \ ] ` and spaces, in case they apper at the end. Any more?

πŸ› Proof of Concept (PoC) *

// PoC.js
telejson=require('telejson');
str = '{"fn":"_function_fn|function () {require(\'child_process\').exec(\'touch HACKED\');}()"}';
JSON.parse(str, telejson.reviver({}), 2);

After running node PoC.js, the file HACKED can be illegally created.

πŸ”₯ Proof of Fix (PoF) *

// PoF.js
telejson=require('telejson');
str = '{"fn":"_function_fn|function () {require(\'child_process\').exec(\'touch HACKED\');}()"}';
JSON.parse(str, telejson.reviver({}), 2);

After running node PoC.js, the file HACKED cannot be created.

πŸ‘ User Acceptance Testing (UAT)

image