rapid7/metasploit-framework — pull request #3282 by musalbas (2014-04-20 17:34:48+00:00)
Title: Make heartbeat request send TLS record with TLS version specified by server_hello, in accordance with RFC 5246

This change reduces false negatives.

When sending the heartbeat request packet, the TLS version specified in the packet is now the same TLS version specified in the server_hello, thus enabling backward compatibility with servers that support a lower TLS version than that specified in the TLS_VERSION option.

From [E.1. in RFC 5246](http://tools.ietf.org/html/rfc5246#appendix-E):

A TLS 1.2 client who wishes to negotiate with such older servers will
send a normal TLS 1.2 ClientHello, containing { 3, 3 } (TLS 1.2) in
ClientHello.client_version. If the server does not support this
version, it will respond with a ServerHello containing an older
version number. If the client agrees to use this version, the
negotiation will proceed as appropriate for the negotiated protocol.

So, specifying a TLS_VERSION of 1.2 in the options will now successfully test hosts with a TLS version of 1.2 or lower. Specifying a TLS_VERSION of 1.1 will successfully test hosts with a TLS version of 1.1 or lower, etc. (The TLS_VERSION option specifies what TLS version to use in the client_hello.)

Therefore on the basis of this change, I've bumped the default TLS version up to 1.2 as this will increase the number of hosts that the test works with by default (e.g. a host may support TLS 1.1 but not 1.0, or vice versa - this change works with both scenarios).

Verification
-

With TLS_VERSION set to 1.2:
* On a vulnerable host that supports TLS 1.0 but not 1.2, the module should return "exploitable".
* On a vulnerable host that supports TLS 1.2 but not 1.0, the module should return "exploitable".
* On a non-vulnerable host that supports TLS 1.0 but not 1.2, the module should return "not exploitable".
* On a non-vulnerable host that supports TLS 1.2 but not 1.0, the module should return "not exploitable".

With TLS_VERSION set to 1.0:
* On a vulnerable host that supports TLS 1.0 but not 1.2, the module should return "exploitable".
* On a vulnerable host that supports TLS 1.2 but not 1.0, the module should not return a result (stops after "Sending Client Hello...").
* On a non-vulnerable host that supports TLS 1.0 but not 1.2, the module should return "not exploitable".
* On a non-vulnerable host that supports TLS 1.2 but not 1.0, the module should not return a result (stops after "Sending Client Hello...").

On a non-vulnerable host that ONLY supports TLS 1.1 and with TLS_VERSION set to 1.2, output should look like this:

msf > use auxiliary/scanner/ssl/openssl_heartbleed

msf auxiliary(openssl_heartbleed) > set VERBOSE true
VERBOSE => true
msf auxiliary(openssl_heartbleed) > set RHOSTS musalbas.com
RHOSTS => musalbas.com
msf auxiliary(openssl_heartbleed) > set ACTION SCAN
ACTION => SCAN

msf auxiliary(openssl_heartbleed) > set TLS_VERSION 1.2
TLS_VERSION => 1.2
msf auxiliary(openssl_heartbleed) > run
[*] 91.121.149.158:443 - Sending Client Hello...
[*] 91.121.149.158:443 - Sending Heartbeat...
[-] 91.121.149.158:443 - No Heartbeat response...
[-] 91.121.149.158:443 - Looks like there isn't leaked information...
[*] Scanned 1 of 2 hosts (050% complete)
[*] Scanned 2 of 2 hosts (100% complete)
[*] Auxiliary module execution completed

msf auxiliary(openssl_heartbleed) > set TLS_VERSION 1.1
TLS_VERSION => 1.1
msf auxiliary(openssl_heartbleed) > run
[*] 91.121.149.158:443 - Sending Client Hello...
[*] 91.121.149.158:443 - Sending Heartbeat...
[-] 91.121.149.158:443 - No Heartbeat response...
[-] 91.121.149.158:443 - Looks like there isn't leaked information...
[*] Scanned 1 of 2 hosts (050% complete)
[*] Scanned 2 of 2 hosts (100% complete)
[*] Auxiliary module execution completed

msf auxiliary(openssl_heartbleed) > set TLS_VERSION 1.0
TLS_VERSION => 1.0
msf auxiliary(openssl_heartbleed) > run
[*] 91.121.149.158:443 - Sending Client Hello...
[*] Scanned 1 of 2 hosts (050% complete)
[*] Scanned 2 of 2 hosts (100% complete)
[*] Auxiliary module execution completed