2016-02-07 19 views
11

Node.js domyślnie wysyła szyfr TLS_EMPTY_RENEGOTIATION_INFO_SCSV, aby zabezpieczyć się przed POODLE attack.Unikaj wysyłania szyfru TLS_EMPTY_RENEGOTIATION_INFO_SCSV w klienta TLS Witaj

Próbuję uniknąć wysyłania tego szyfru (nawet jeśli może to stanowić zagrożenie bezpieczeństwa) przez nadpisanie szyfrów TLS niestandardową listą szyfrów.

Jednak Node.js ciągle wysyła kod TLS_EMPTY_RENEGOTIATION_INFO_SCSV bez względu na to, co robię. Staram się świadomie unikać wysyłania tego szyfru w celu naśladowania negocjacji TLS przeglądarki Firefox/Chrome.

Oto kod używam do modyfikacji i sprawdzić, które szyfry Node wysyła:

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); 
    } 
}); 

Czy istnieje jakiś sposób, aby wyłączyć wysyłanie tego szyfru w node.js?

+0

Myślę, że to nie ma nic wspólnego bezpośrednio z node.js, ale z modułem żądania, którego używasz. A może debugujesz problem w rdzeniu node.js? – migg

+0

Nie jestem pewien, czy to jest poprawne: * "... wysłanie tego szyfrowania nie jest konieczne, jeśli celowo wyłączę obniżenie protokołu (przez wymuszenie TLS 1.2" *.) Wierzę, że wszystkie wersje TLS cierpią z powodu ataków polegających na obniżeniu jakości, ponieważ TLS ma * nie * używaj pary *** '{min-TLS, max-TLS}' ***. Zamiast tego [TLS_FALLBACK_SCS'] (http://tools.ietf.org/html/rfc7507) działa z czasem, więc miałby zastosowanie z kolejnymi połączeniami, a nie pojedynczą próbą połączenia w próżni. – jww

+0

@migg jest w rdzeniu Node.js - sprawdź [ssl_lib.C# L1472] (https://github.com/nodejs/ węzeł/blob/bdd37e1fac77b75c56eb3a7f566ae374ac668a64/deps/openssl/openssl/ssl/ssl_lib.C# L1472), który wydaje się być miejscem w Node.js, gdzie szyfr SCSV jest dodawany do klienta Witaj (może się mylić co do linii, ale jest Moduł 'request' npm zależy od pakietu Node.js' 'tls' który obsługuje połączenie TLS przez openssl. @jww możesz mieć rację, że jest niepewny, jednak do momentu wyłączenia go w przypadku testowym i nie przejmuj się w tym momencie konsekwencjami bezpieczeństwa. –

Odpowiedz

1

Biorąc pod uwagę, że kwestia ta jest związana z node.js, jest jedna prosta metoda radzenia sobie z problemu bez faktycznie kopanie się znacznie do niego:

Put proxy WWW przed swoim procesem node.js i pozwól mu obsługiwać pełne połączenie SSL. W samym kodzie Node.js wyślesz tylko żądanie do lokalnego serwera HTTP.

Przykład konfiguracji z nginx (wewnątrz dyrektywy 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; 
    } 
} 

i zmienić nodejs do:

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); 
    } 
}); 

Niestety choć rzeczywiście to zrobił, i wynik był taki sam:

{"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"} 

Zasadniczo oznacza to prawdopodobnie standardowe zachowanie OpenSSL.

Istnieją opcje, które mogą być ustawione w OpenSSL wykorzystujące SSL_CTX_set_options

Szczególnie interesujący jest tu sekcji Bezpieczna renegocjacji i tę opcję:

SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION

Allow legacy niezabezpieczoną renegocjację między OpenSSL i załatane klientów lub serwerów. Zobacz sekcję SECURE RENEGOTIATION, aby uzyskać więcej informacji.

Nie jestem jednak pewien, czy to rzeczywiście uniemożliwia wysłanie szyfru renegocjacyjnego. Jeśli ta opcja jest rzeczywiście poprawna, może istnieć sposób na załatanie Node.js, aby użyć tej opcji, lub rekompilacja OpenSSL z tą opcją.

Oczywiście istnieje również możliwość użycia starej wersji niezałatanej. Z mojego zrozumienia chociaż TLS_EMPTY_RENEGOTIATION_INFO_SCSV nie jest związana z pudla, ale ze starszej Fix:

CVE-2009-3555 (doradczy OpenSSL) 5 listopada 2009:
Wdrożenie RFC5746 dotycząca luk w SSL/TLS renegocjacji. Naprawiono w 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)

Nowoczesne node.js wyposażony statycznie połączony OpenSSL jednak nie obsługuje OpenSSL 0.9.8, więc potrzebna jest starsza wersja Node.js niezależnie ... lub użyj rzeczy nginx z niezałataną OpenSSL ...

To jest coś takiego Utknąłem. To nie jest kompletna odpowiedź, ale myślę, że przynajmniej warto ją udostępnić.

Podsumowując, myślę, że jeśli chcesz to zrobić bez ponownej kompilacji, użyj nginx z i niezałatwioną OpenSSL i skonfiguruj wiele serwerów, po jednym dla każdego klienta, który chcesz naśladować.

Jeśli chcesz, aby to było wykonywane wyłącznie w węźle, najlepiej jest załatać OpenSSL bezpośrednio i ponownie skompilować węzeł.

+0

To jest droga. Zawsze pozwalałem, aby Ngnix obsługiwał moje SSL - znacznie mniejsze ryzyko problemów w przyszłości. –

+0

Dziękuję bardzo za szczegółową odpowiedź! Myślę, że skończę łatać Node.js i kompilować go ręcznie, ponieważ nie byłem w stanie uniknąć wysyłania tego szyfru nawet w węźle 0.8.x. –