dicer icon indicating copy to clipboard operation
dicer copied to clipboard

Removed a bug which could cause a crash in HeaderParser, and as consequence could potentially crash a web server based on it

Open RolandHeinze opened this issue 3 years ago • 20 comments

Function HeaderParser.prototype._parseHeader() uses a variable h, which in edge cases is used before it is initialized. As a consequence the statement

this.header[h][this.header[h].length - 1] += lines[i];

would crash. This can happen if an attacker uses a manipulated multipart/form-data header with a header name that starts with ' ' or '\t'. I wrote a simple HTML file that is exactly doing this using the fetch() function:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
</head>

<body onload="sectest()">
<button id="security">Security Check</button>
<script>
  function sectest() {
    const button_sectest = document.getElementById('security');
    button_sectest.onclick = send;
  }
  function send(event) {
    event.preventDefault();
    fetch('form-image', {
      method: 'POST',
      headers: {
        ['content-type']: 'multipart/form-data; boundary=----WebKitFormBoundaryoo6vortfDzBsDiro',
        ['content-length']: '145',
        host: '127.0.0.1:8000',
        connection: 'keep-alive',
      },
      body: '------WebKitFormBoundaryoo6vortfDzBsDiro\r\n Content-Disposition: form-data; name="bildbeschreibung"\r\n\r\n\r\n------WebKitFormBoundaryoo6vortfDzBsDiro--'
    });
  }
</script>
</body>
</html>

I used such an HTML file, and was able to crash Dicer and also Busboy. In particular, it happens if one uses the example server code presented on the Dicer GitHub repository. I think that it is a severe bug which should be removed as soon as possible.

Therefore, I wrote this PR. It

  • removes the mentioned bug;
  • removes a bug in the HeaderParser constructor functions which computed a wrong value for the variable end;
  • removes some unnecessary code in HeaderParser.prototype._parseHeader();
  • removes the variable _realFinish and all of it's occurances in Dicer.js as it is not necessary, increases the code size, and adds unwanted complexity;
  • removes an unnecessary else ifclause in the function Dicer.prototype._oninfo();

RolandHeinze avatar Aug 05 '21 18:08 RolandHeinze

@RolandHeinze Are you using dicer as a part of busboy or separately? Context for the question - we have forked busboy within fastify organization in order to restart development on it, and our original plan was to just embed dicer in it. However, if there is demand for fixed dicer outside of busboy, we can also provide that as a separate dependency.

kibertoad avatar Nov 28 '21 14:11 kibertoad

Hi devs, I'm starting to get Snyk High Vulnerability alerts regarding Dicer for all versions: https://snyk.io/vuln/npm%3Adicer

Any way I can help get this PR across the line?

nathan-gilbert avatar May 20 '22 17:05 nathan-gilbert

@nathan-gilbert If you're just parsing web forms (multipart or urlencoded), busboy would be a better choice.

dicer was originally created for use by busboy, but it no longer depends on it.

mscdex avatar May 20 '22 19:05 mscdex

@mscdex I'm not using dicer directly, but many of my dependencies are so it would be a much larger refactor than simply switching dicer for busboy.

nathan-gilbert avatar May 20 '22 19:05 nathan-gilbert

@nathan-gilbert If the parent dependency is an older version of busboy, releasing a new version of dicer would not help as those old versions of busboy used exact versions for the dicer dependency and not version ranges.

mscdex avatar May 20 '22 19:05 mscdex

@mscdex Yep, you're right. I thought there were more than just busboy using dicer but it doesn't look like it. I think all I need to do is upgrade busboy.

Thanks, sorry for taking up some time here.

nathan-gilbert avatar May 20 '22 19:05 nathan-gilbert

There is a Denial of Service (DoS) security flaw has been introduced in [email protected]. The details are available in the Snyk report: https://security.snyk.io/vuln/SNYK-JS-DICER-2311764 There is no fix version available. So It is impacting other modules which dependent on the multer module. So we are looking for fix version for this as soon as possible.

nsandeepn avatar May 23 '22 16:05 nsandeepn

@nsandeepn multer just needs to upgrade to the latest version of busboy. For existing multer installations, there's nothing that can be done (see https://github.com/mscdex/dicer/pull/22#issuecomment-1133276609).

mscdex avatar May 23 '22 17:05 mscdex

FYI it looks like firebase/firebase-admin-node depends on dicer directly, but only for parsing responses from the Firebase API. Should be no real danger there, just annoying to have the security warning.

Karlinator avatar May 26 '22 08:05 Karlinator

@Karlinator npm audit report

dicer * Severity: high Crash in HeaderParser in dicer - https://github.com/advisories/GHSA-wm7h-9275-46v2 fix available via npm audit fix --force Will install [email protected], which is a breaking change node_modules/dicer firebase-admin >=7.1.0 Depends on vulnerable versions of dicer node_modules/firebase-admin

2 high severity vulnerabilities

AnkurBansalSF avatar May 26 '22 09:05 AnkurBansalSF

For people getting this error in snyk, if it isn't already apparent from the comments above...

An older version of busboy used this version of dicer that is throwing this problem.

Multer really just needs to update their packages, see https://github.com/expressjs/multer/issues/1095

yurisim avatar May 26 '22 10:05 yurisim

multer just needs to upgrade to the latest version of busboy. For existing multer installations, there's nothing that can be done (see https://github.com/mscdex/dicer/pull/22#issuecomment-1133276609).

This is not as easy as said, since the change in to not use dice is part of the braking release v1.0.0, which drops the support of older node versions. Upgrading to this version in multer would also require multer to create a breaking change release. (See: https://github.com/expressjs/multer/pull/1097)

Creating a fix in dicer would enable different users to use the override feature of npm to quick-fix the issue.

Also: if you don't plan to support dicer further, i think it would be beneficial to deprecate/archive this repo and add some infos, that users can find easily.

rudxde avatar May 27 '22 11:05 rudxde

If anyone wants to patch around this in a minimal way until all their other dependencies update then we used this patch in Dicer (0.2.5):

diff --git a/node_modules/dicer/lib/Dicer.js b/node_modules/dicer/lib/Dicer.js
index 246b3ea..611cbeb 100644
--- a/node_modules/dicer/lib/Dicer.js
+++ b/node_modules/dicer/lib/Dicer.js
@@ -124,7 +124,11 @@ Dicer.prototype.setBoundary = function(boundary) {
   var self = this;
   this._bparser = new StreamSearch('\r\n--' + boundary);
   this._bparser.on('info', function(isMatch, data, start, end) {
-    self._oninfo(isMatch, data, start, end);
+    try {
+     self._oninfo(isMatch, data, start, end);
+    } catch (e) {
+      self.emit('error', e)
+    }
   });
 };

This catches the error and emits it so that Express can properly fail the request and get back to processing other requests. Arguably, this would be a good change to see in Dicer regardless.

colinhowe avatar May 27 '22 12:05 colinhowe

We also have a direct dependency on dicer in firebase-admin-node. Fixing dicer would help developers who are currently have their releases blocked on npm audit (see https://github.com/firebase/firebase-admin-node/issues/1718#issuecomment-1139958102). It will also provide a stopgap solution for package maintainers and buy some time to implement a proper fix (updating busboy etc.).

Also agree with @rudxde if you no longer recommend developers to use dicer directly, deprecating the module would help.

lahirumaramba avatar Jun 01 '22 14:06 lahirumaramba

dicer was originally created for use by busboy, but it no longer depends on it.

@mscdex: So, is dicer still going to be maintained? If no, does anything speak against marking dicer as deprecated?

Kondamon avatar Jun 03 '22 15:06 Kondamon

@Kondamon It's low priority at the moment. dicer really needs a rewrite, much like busboy had, because node streams have come a long way since I first wrote the modules.

mscdex avatar Jun 03 '22 16:06 mscdex

Presumably indirect dependencies such as this...

apollo-server > apollo-server-core >
@apollographql/graphql-upload-8-fork > busboy > dicer

...are of very little security risk remaining on dicer v0.3.1 with no fix?

hardysabs2 avatar Jun 07 '22 08:06 hardysabs2

If anyone wants to patch around this in a minimal way until all their other dependencies update then we used this patch in Dicer:

diff --git a/node_modules/dicer/lib/Dicer.js b/node_modules/dicer/lib/Dicer.js
index 246b3ea..611cbeb 100644
--- a/node_modules/dicer/lib/Dicer.js
+++ b/node_modules/dicer/lib/Dicer.js
@@ -124,7 +124,11 @@ Dicer.prototype.setBoundary = function(boundary) {
   var self = this;
   this._bparser = new StreamSearch('\r\n--' + boundary);
   this._bparser.on('info', function(isMatch, data, start, end) {
-    self._oninfo(isMatch, data, start, end);
+    try {
+     self._oninfo(isMatch, data, start, end);
+    } catch (e) {
+      self.emit('error', e)
+    }
   });
 };

This catches the error and emits it so that Express can properly fail the request and get back to processing other requests. Arguably, this would be a good change to see in Dicer regardless.

On which version of dicer did you create/apply this fix?

rafaelmaeuer avatar Jun 07 '22 14:06 rafaelmaeuer

@rafaelmaeuer 0.2.5 - I'll update my comment to say that

colinhowe avatar Jun 07 '22 14:06 colinhowe

Presumably indirect dependencies such as this...

apollo-server > apollo-server-core > @apollographql/graphql-upload-8-fork > busboy > dicer

...are of very little security risk remaining on dicer v0.3.1 with no fix?

@hardysabs2 Did you find a solution for this?

vinutha93bnvs avatar Sep 12 '22 11:09 vinutha93bnvs