CVE-2023-46234 (published 2023-10-26T15:15Z)

browserify-sign is a package to duplicate the functionality of node's crypto public key functions, much of this is based on Fedor Indutny's work on indutny/tls.js. An upper bound check issue in `dsaVerify` function allows an attacker to construct signatures that can be successfully verified by any public key, thus leading to a signature forgery attack. All places in this project that involve DSA verification of user-input signatures will be affected by this vulnerability. This issue has been patched in version 4.2.2.\n

CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N)

Weakness information:
cwe_id: CWE-347
cwe_name: Improper Verification of Cryptographic Signature
description: The product does not verify, or incorrectly verifies, the cryptographic signature for data.
extended_description: 
            
            
         
         

Fix information:
repo_url: https://github.com/browserify/browserify-sign
commit_details: repo_url: https://github.com/browserify/browserify-sign
author: roadicing
author_date: 2023-10-21 13:08:48+08:00
msg: [Fix] properly check the upper bound for DSA signatures

Co-authored-by: roadicing <roadicing@gmail.com>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
repository: repo_url: https://github.com/browserify/browserify-sign
repo_name: browserify/browserify-sign
description: createSign and createVerify in your browser
repo_language: JavaScript
owner: browserify
file_changes: filename: verify.js
change_type: ModificationType.MODIFY
diff: @@ -80,7 +80,7 @@ function dsaVerify(sig, hash, pub) {
 
 function checkValue(b, q) {
   if (b.cmpn(0) <= 0) { throw new Error('invalid sig'); }
-  if (b.cmp(q) >= q) { throw new Error('invalid sig'); }
+  if (b.cmp(q) >= 0) { throw new Error('invalid sig'); }
 }
 
 module.exports = verify;

programming_language: JavaScript
filename: index.js
change_type: ModificationType.MODIFY
diff: @@ -5,6 +5,9 @@ var asn1 = require('parse-asn1/asn1');
 var test = require('tape').test;
 var nCrypto = require('crypto');
 var semver = require('semver');
+var BN = require('bn.js');
+var parseKeys = require('parse-asn1');
+
 var bCrypto = require('../browser');
 var fixtures = require('./fixtures');
 
@@ -154,6 +157,35 @@ fixtures.valid.ec.forEach(function (f) {
       t.end();
     });
   }
+
+  var s = parseKeys(pub).data.q;
+  test(
+    f.message + ' against a fake signature',
+    { skip: !s || '(this test only applies to DSA signatures and not EC signatures, this is ' + f.scheme + ')' },
+    function (t) {
+      var messageBase64 = Buffer.from(f.message, 'base64');
+
+      // forge a fake signature
+      var r = new BN('1');
+
+      try {
+        var fakeSig = asn1.signature.encode({ r: r, s: s }, 'der');
+      } catch (e) {
+        t.ifError(e);
+        t.end();
+        return;
+      }
+
+      var bVer = bCrypto.createVerify(f.scheme);
+      t['throws'](
+        function () { bVer.update(messageBase64).verify(pub, fakeSig); },
+        Error,
+        'fake signature is invalid'
+      );
+
+      t.end();
+    }
+  );
 });
 
 fixtures.valid.kvectors.forEach(function (f) {

programming_language: JavaScript