GHSA-477h-4r7f-fvrx: Low severity npm/pbkdf2 vulnerability
Summary This is the same bug as Django had (CVE-2013-1443).
Details A long password can cause a DoS because it is not using cached HMAC, length limits, or pre-hashing passwords longer than the block size of the hash function as per HMAC spec. This line of code hashes the full password each iteration: https://github.com/browserify/pbkdf2/blob/1c3b1f526b052a29b3b42120c9821895772df7e8/lib/sync.js#L60
Also see https://github.com/browserify/pbkdf2/issues/82
PoC The first key will take a lot longer to generate when not using the native code and uses code from /lib/sync.js (ie when this if statement is true): https://github.com/browserify/pbkdf2/blob/1c3b1f526b052a29b3b42120c9821895772df7e8/index.js#L33-L37
js var pbkdf2 = require('pbkdf2'); var createHash = require('create-hash'); var pw = ".".repeat(1048576); // 1 MiB
var t0 = performance.now(); var key1 = pbkdf2.pbkdf2Sync(pw, "salt", 1000, 32, "sha256"); var t1 = performance.now(); pw = createHash('sha256').update(pw).digest(); // HMAC specification for keys larger than block size var key2 = pbkdf2.pbkdf2Sync(pw, "salt", 1000, 32, "sha256"); var t2 = performance.now();
console.log("First took: " + (t1 - t0)); console.log("Second took: " + (t2 - t1)); console.log("Generated keys:"); console.log(key1); console.log(key2);
Impact DoS
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/pbkdf2to a version that resolves this vulnerability.Fixed in 3.1.7 - Compensating control
Before PBKDF2/HMAC processing, pre-hash passwords larger than the hash function’s block size (for example, `pw = createHash('sha256').update(pw).digest();`) and enforce a password length limit to prevent excessive processing.
Event History
Frequently Asked Questions
Which deployments are most exposed to the performance impact?
Deployments that execute the JavaScript synchronous implementation in /lib/sync.js rather than native code are exposed. The proof of concept notes that the slowdown occurs when the code path selects /lib/sync.js.
What input would an attacker need to supply?
An attacker would need to cause the application to derive a key from a very long password. The supplied example uses a 1 MiB password with 1,000 PBKDF2 iterations and shows that processing the original password takes substantially longer than processing its SHA-256 digest.
What can be done if the affected code path cannot be replaced immediately?
Pre-hash passwords that exceed the hash function's block size before passing them to PBKDF2, consistent with the HMAC specification described in the advisory. This avoids hashing the full long password during every iteration.
How can an environment determine whether it is using the affected path?
Check whether its pbkdf2 calls resolve to the JavaScript implementation in /lib/sync.js instead of native code. A controlled comparison of a long password against its SHA-256 digest can also reveal the disproportionate delay described in the proof of concept.