Avoid sending TLS_EMPTY_RENEGOTIATION_INFO_SCSV cipher in TLS Client Hello

旧城冷巷雨未停 提交于 2021-02-08 12:34:07

问题


Node.js sends the TLS_EMPTY_RENEGOTIATION_INFO_SCSV cipher by default to protect itself against the POODLE attack.

I'm trying to avoid sending this cipher (even though this may pose a security risk) by overriding the TLS ciphers with a custom list of ciphers.

However, Node.js keeps sending the TLS_EMPTY_RENEGOTIATION_INFO_SCSV cipher no matter what I do. I'm trying to deliberately avoid sending this cipher to mimic the TLS negotiation of Firefox/Chrome.

Here's the code I use to modify and check which ciphers Node is sending:

var request = require('request');

var ciphers = [
    'ECDHE-ECDSA-AES128-GCM-SHA256',
    'ECDHE-RSA-AES128-GCM-SHA256',
    'ECDHE-ECDSA-AES256-SHA',
    'ECDHE-ECDSA-AES128-SHA',
    'ECDHE-RSA-AES128-SHA',
    'ECDHE-RSA-AES256-SHA',
    'DHE-RSA-AES128-SHA',
    'DHE-RSA-AES256-SHA',
    'AES128-SHA',
    'AES256-SHA',
    'DES-CBC3-SHA'
].join(':');

var options = {
    ciphers: ciphers,
    secureProtocol: 'TLSv1_2_method',
    url: 'https://www.howsmyssl.com/a/check'
};

request(options, function (error, response, body){
    if (!error) {
        console.log(body);
    }
    else {
        console.log(error);
    }
});

Is there any way to disable sending this cipher in Node.js?


回答1:


Given that this issue is related to Node.js, there is one simple method to deal with your issue without actually digging to much into it:

Put a web proxy in front of your Node.js process and let it handle the complete SSL connection. In the Node.js code itself, you would only send a request to a local HTTP server.

Example configuration with nginx (inside the http directive):

server {
   listen 8080;
   location / {
      resolver 8.8.8.8;
      proxy_pass https://www.howsmyssl.com$uri$is_args&args;
      proxy_ssl_protocols TLSv1.2;
      proxy_ssl_ciphers AESGCM:!aNULL;
   }
}

And change the nodejs to:

var request = require('request');

var options = {
    url: 'http://localhost:8080/a/check'
};

request(options, function (error, response, body){
    if (!error) {
        console.log(body);
    }
    else {
        console.log(error);
    }
});

Unfortunately though I actually did this, and the result was the same:

{"given_cipher_suites":["TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384","TLS_DH_DSS_WITH_AES_256_GCM_SHA384","TLS_DHE_DSS_WITH_AES_256_GCM_SHA384","TLS_DH_RSA_WITH_AES_256_GCM_SHA384","TLS_DHE_RSA_WITH_AES_256_GCM_SHA384","TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384","TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384","TLS_RSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256","TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256","TLS_DH_DSS_WITH_AES_128_GCM_SHA256","TLS_DHE_DSS_WITH_AES_128_GCM_SHA256","TLS_DH_RSA_WITH_AES_128_GCM_SHA256","TLS_DHE_RSA_WITH_AES_128_GCM_SHA256","TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256","TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256","TLS_RSA_WITH_AES_128_GCM_SHA256","TLS_EMPTY_RENEGOTIATION_INFO_SCSV"],"ephemeral_keys_supported":true,"session_ticket_supported":true,"tls_compression_supported":false,"unknown_cipher_suite_supported":false,"beast_vuln":false,"able_to_detect_n_minus_one_splitting":false,"insecure_cipher_suites":{},"tls_version":"TLS 1.2","rating":"Probably Okay"}

This basically means that its probably standard OpenSSL behavior.

There are options which can be set in OpenSSL using SSL_CTX_set_options

Especially interesting here is the SECURE RENEGOTIATION section and this option:

SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION

Allow legacy insecure renegotiation between OpenSSL and unpatched clients or servers. See the SECURE RENEGOTIATION section for more details.

I am not certain though if this actually prevents the renegotiation cipher from being send. If this option is actually correct, there might be a way to either patch Node.js to use that option or recompile OpenSSL with that option.

There would of course also be the option to use an old unpatched version. From my understanding though TLS_EMPTY_RENEGOTIATION_INFO_SCSV is not related to POODLE, but from an older fix:

CVE-2009-3555 (OpenSSL advisory) 5th November 2009:
Implement RFC5746 to address vulnerabilities in SSL/TLS renegotiation. Fixed in OpenSSL 0.9.8m (Affected 0.9.8l, 0.9.8k, 0.9.8j, 0.9.8i, 0.9.8h, 0.9.8g, 0.9.8f, 0.9.8e, 0.9.8d, 0.9.8c, 0.9.8b, 0.9.8a, 0.9.8)

Modern Node.js comes with a statically linked OpenSSL however and does not support OpenSSL 0.9.8, so you would need an older version of Node.js regardless... or use the nginx stuff with an unpatched OpenSSL...

This is kind of where I am stuck. Its not really an complete answer, but I think its at least worth to share.

To sum it up though, I think if you want to do this without recompiling use nginx with and unpatched OpenSSL, and configure multiple servers, one for each client you want to mimic.

If you require this to be soley done in node, your best bet is to patch OpenSSL there directly and recompile node.



来源:https://stackoverflow.com/questions/35254883/avoid-sending-tls-empty-renegotiation-info-scsv-cipher-in-tls-client-hello

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!