Node.js默认发送TLS_EMPTY_RENEGOTIATION_INFO_SCSV
密码以保护自己不受POODLE attack的攻击。</ p>
我试图通过使用自定义密码列表覆盖TLS密码来避免发送此密码(即使这可能会带来安全风险)。
然而,无论我做什么,Node.js都会不断发送TLS_EMPTY_RENEGOTIATION_INFO_SCSV
密码。我试图故意避免发送此密码来模仿Firefox / Chrome的TLS协商。
这是我用来修改和检查节点正在发送的密码的代码:
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);
}
});
有没有办法禁止在Node.js中发送此密码?
答案 0 :(得分:1)
鉴于此问题与Node.js有关,有一种简单的方法可以解决您的问题,而无需深入研究它:
将一个Web代理放在Node.js进程前面,让它处理完整的SSL连接。在Node.js代码本身中,您只需向本地HTTP服务器发送请求。
使用nginx配置示例(在http指令内):
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;
}
}
将nodejs更改为:
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);
}
});
不幸的是,虽然我确实这样做了,但结果是一样的:
{"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"}
这基本上意味着它可能是标准的OpenSSL行为。
在OpenSSL中设置选项这里特别有趣的是SECURE RENEGOTIATION部分和此选项:
SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
允许OpenSSL与未修补的客户端或服务器之间的旧版不安全重新协商。有关详细信息,请参阅SECURE RENEGOTIATION部分。
我不确定这是否真的阻止了重新协商密码的发送。 如果此选项实际上是正确的,则可能有一种方法可以修补Node.js以使用该选项,或者使用该选项重新编译OpenSSL。
当然也可以选择使用旧的未修补版本。
根据我的理解,虽然TLS_EMPTY_RENEGOTIATION_INFO_SCSV
与POODLE无关,但与较旧的修正无关:
CVE-2009-3555(OpenSSL顾问)2009年11月5日:
实施RFC5746以解决SSL / TLS重新协商中的漏洞。 固定在OpenSSL 0.9.8m(受影响的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)
现代Node.js附带一个静态链接的OpenSSL但是不支持OpenSSL 0.9.8,所以无论如何你都需要一个旧版本的Node.js,或者使用未修补的OpenSSL的nginx内容......
这就是我陷入困境的地方。 它不是一个完整的答案,但我认为它至少值得分享。
总而言之,我认为如果你想这样做而不重新编译使用nginx和未修补的OpenSSL,并配置多个服务器,每个服务器一个,你想模仿。
如果您要求在节点中完成此操作,最好的办法是直接在那里修补OpenSSL并重新编译节点。
答案 1 :(得分:0)
TLS_EMPTY_RENEGOTIATION_INFO 似乎是一个占位符密码套件,它执行与扩展“renegotiation_info”相同的功能。此外,OpenSSL 似乎没有办法设置“renegotiation_info”扩展名,并且需要这个空的密码套件。
来源:c-openssl-setting-list-of-ciphers
来源:RFC 5746 Section-3.3