SoftwareBrothers / adminjs-design-system

DesignSystem on which AdminJS is based on
27 stars 33 forks source link

Prototype Pollution Vulnerability Affecting admin-bro/design-system Package, all versions #99

Open tariqhawis opened 5 months ago

tariqhawis commented 5 months ago

Overview

Affected versions of this package are vulnerable to Prototype Pollution. An attacker can manipulate the prototype of an object, potentially leading to the alteration of behavior of all objects inheriting from the affected prototype by passing specially crafted input to this function.

Details:

The vulnerability located at (@admin-bro/design-system/build/utils/combine-styles.js:26 when mergeDeep() method can be exploited to recusively copy malicouse property to the built-in Object.prototype which is usually reachable through the special properties proto and constructor.prototype. Thus, the attacker can use one of these properties to pollute the application logic that can be escalated to Denial of service, remote code execution or cross-site scripting attacks.

PoC:

(async () => {
  const lib = await import('@admin-bro/design-system');

var BAD_JSON = JSON.parse('{"__proto__":{"polluted":true}}');
var victim = {}
console.log("Before Attack: ", JSON.stringify(victim.__proto__));
try {
  lib.combineStyles (BAD_JSON)
} catch (e) { }
console.log("After Attack: ", JSON.stringify(victim.__proto__));
delete Object.prototype.polluted;
})();

How to prevent:

  • Freeze the root prototype using Object.freeze
  • Require schema validation of JSON input.
  • Avoid using unsafe recursive merge functions.
  • Consider using objects without prototypes (for example, Object.create(null)), breaking the prototype chain and preventing pollution.
  • As a best practice use Map instead of Object
dziraf commented 5 months ago

I've just checked with the latest version of @adminjs/design-system and it doesn't seem to change anything:

Screenshot 2024-03-12 at 18 26 49

@admin-bro/design-system package that you referred as well as all other @admin-bro/* packages have been rebranded to @adminjs/* packages 3 years ago and there've been multiple releases for each one of them since then.

tariqhawis commented 5 months ago

Indeed, these tests have been done on @admin-bro/. However, although @adminjs is the new brand, the old one is still available to date in npm registry which might pose a security risk to the hundreds of users who are using it. Therefore, I advise applying npm deprecate on @admin-bro/ specifying a message indicating the new brand name.

mestrtee commented 5 months ago

Is there any updates on this issue?

dziraf commented 5 months ago

What kind of update do you need?

mestrtee commented 5 months ago

To apply npm-deprecate with a message that indicates the new brand name. Note that there still 2k weekly downloads on the mentioned package

dziraf commented 5 months ago

This won't happen anytime soon most likely. We use semantic-release to automate publishing of new releases through a separate organization account and I don't have sufficient permissions to run this command when authenticated via my NPM account. It's also unlikely I'll be granted these permissions.

We might add https://www.npmjs.com/package/semantic-release-npm-deprecate the next time we publish a new release, but still this would have to be applied to all our packages to make sense.

I doubt anyone still installs AdminBro packages accidentally since we do not maintain any AdminBro-related content anymore, there might be some unofficial articles posted somewhere but that's it. The 2K weekly downloads most likely come from apps that had been created prior to the rebranding; their creators've had 3 years to update...