Skip to content

Instantly share code, notes, and snippets.

@3rd-Eden
Last active January 4, 2021 10:20
  • Star 24 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save 3rd-Eden/715522f6950044da45d8 to your computer and use it in GitHub Desktop.
Protecting against POODLE in node.js

Google recently announced that there is an exploit in SSLv3, this vulnerability is know as POODLE. There is no other option than to disable SSLv3 in order to combat this major flaw. There have already been guides on how to disable this in different servers. But nothing excised for Node.js yet, until now. In order to resolve this for Node.js we need to use various of undocumented options and modules.

In the index.js file below you can see an example of how you can protect your HTTPS server against the POODLE attack. It uses the secureOptions option to pass in constants in to the SSL context which is created by node.

Start the server locally by running:

sudo node index.js

And see if SSLv3 is correctly disabled by connecting with an openssl client:

openssl s_client -connect 127.0.0.1:443 -ssl3

It should respond with a handshake failure:

CONNECTED(00000003)
47309:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:/SourceCache/OpenSSL098/OpenSSL098-52/src/ssl/s3_pkt.c:546:

If we connect normally, it will just work:

openssl s_client -connect 127.0.0.1:443
'use strict';
var constants = require('constants')
, https = require('https')
, path = require('path')
, tls = require('tls')
, fs = require('fs');
//
// https and tls support the same createServer options, so it doesn't
// matter which one you create as long as you supply the `secureOptions`
//
https.createServer({
//
// This is the default secureProtocol used by Node.js, but it might be
// sane to specify this by default as it's required if you want to
// remove supported protocols from the list. This protocol supports:
//
// - SSLv2, SSLv3, TLSv1, TLSv1.1 and TLSv1.2
//
secureProtocol: 'SSLv23_method',
//
// Supply `SSL_OP_NO_SSLv3` constant as secureOption to disable SSLv3
// from the list of supported protocols that SSLv23_method supports.
//
secureOptions: constants.SSL_OP_NO_SSLv3,
cert: fs.readFileSync(path.join(__dirname, 'ssl', 'server.crt')),
key: fs.readFileSync(path.join(__dirname, 'ssl', 'server.key')),
}, function (req, res) {
res.end('works');
}).listen(443);
@indutny
Copy link

indutny commented Oct 15, 2014

Or use this patch: nodejs/node-v0.x-archive#8551

@ploer
Copy link

ploer commented Oct 15, 2014

It seems like it makes sense to set secureOptions to constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_SSLv2 to also prevent SSLv2, is there some reason that's unnecessary or a bad idea?

@baudehlo
Copy link

I just discovered that these options aren't documented under crypto.createCredentials() where they are needed for Haraka (because we have to do the TLS upgrade on a plaintext connection). I'll post an issue or PR to the core docs.

@GregTurner
Copy link

@ploer Agreed

@3rd-Eden
Copy link
Author

@ploer that's possible but you can also just set a different secureProtocol if you don't want to support any of the SSLv* versions.

@niczak
Copy link

niczak commented Feb 2, 2015

We have implemented the changes above but now when requests come into the server node crashes with the following error:

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: 140314695460672:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:../deps/openssl/openssl/ssl/s3_pkt.c:1256:SSL alert number 40

    at SlabBuffer.use (tls.js:232:18)
    at CleartextStream.read [as _read] (tls.js:452:29)
    at CleartextStream.Readable.read (_stream_readable.js:320:10)
    at EncryptedStream.write [as _write] (tls.js:366:25)
    at doWrite (_stream_writable.js:221:10)
    at writeOrBuffer (_stream_writable.js:211:5)
    at EncryptedStream.Writable.write (_stream_writable.js:180:11)
    at write (_stream_readable.js:583:24)
    at flow (_stream_readable.js:592:7)
    at Socket.pipeOnReadable (_stream_readable.js:624:5)
    at Socket.EventEmitter.emit (events.js:92:17)

Has anyone run into this before and found a solution? We have tested and verified that our node server no longer allows SSL3 but as soon as something tries to communicate that way the above happens.

@niczak
Copy link

niczak commented Feb 2, 2015

Ignore my above comment, figured out the problem. We had a method that would post back to another server (in some cases) that was forcing SSLv3. Problem solved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment