Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1/n-1 record splitting BEAST mitigation not implemented in JRuby, is in MRI #92

Open
mohamedhafez opened this issue May 27, 2016 · 0 comments

Comments

@mohamedhafez
Copy link
Contributor

mohamedhafez commented May 27, 2016

To reproduce, I installed the mechanize gem, then hacked Net::HTTP to use :TLSv1, and then visited the site https://www.howsmyssl.com/, and then copy and pasted the body into a file and viewed it with my browser. On MRI 2.3.0, the site reports that the 1/n-1 record splitting BEAST mitigation is implemented, on JRuby it says its not. (It also reports unsafe cipher suites for both MRI and JRuby, but perhaps those needed for backwards compatibility?)

Oh and I'm using JRuby 9.1.2.0 with Java 7 on a Mac.

Here's the code to paste into irb to reproduce:

require 'mechanize'

module Net
  class HTTP
    def connect
      if proxy? then
        conn_address = proxy_address
        conn_port    = proxy_port
      else
        conn_address = address
        conn_port    = port
      end

      D "opening connection to #{conn_address}:#{conn_port}..."
      s = Timeout.timeout(@open_timeout, Net::OpenTimeout) {
        begin
          TCPSocket.open(conn_address, conn_port, @local_host, @local_port)
        rescue => e
          raise e, "Failed to open TCP connection to " +
              "#{conn_address}:#{conn_port} (#{e.message})"
        end
      }
      s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
      D "opened"
      if use_ssl?
        ssl_parameters = Hash.new
        iv_list = instance_variables
        SSL_IVNAMES.each_with_index do |ivname, i|
          if iv_list.include?(ivname) and
              value = instance_variable_get(ivname)
            ssl_parameters[SSL_ATTRIBUTES[i]] = value if value
          end
        end
        @ssl_context = OpenSSL::SSL::SSLContext.new
        @ssl_context.set_params(ssl_parameters)

        #############################  hack to force :TLSv1 ################
        @ssl_context.ssl_version = :TLSv1
        ####################################################################

        D "starting SSL for #{conn_address}:#{conn_port}..."
        s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
        s.sync_close = true
        D "SSL established"
      end
      @socket = BufferedIO.new(s)
      @socket.read_timeout = @read_timeout
      @socket.continue_timeout = @continue_timeout
      @socket.debug_output = @debug_output
      if use_ssl?
        begin
          if proxy?
            buf = "CONNECT #{@address}:#{@port} HTTP/#{HTTPVersion}\r\n"
            buf << "Host: #{@address}:#{@port}\r\n"
            if proxy_user
              credential = ["#{proxy_user}:#{proxy_pass}"].pack('m')
              credential.delete!("\r\n")
              buf << "Proxy-Authorization: Basic #{credential}\r\n"
            end
            buf << "\r\n"
            @socket.write(buf)
            HTTPResponse.read_new(@socket).value
          end
          # Server Name Indication (SNI) RFC 3546
          s.hostname = @address if s.respond_to? :hostname=
          if @ssl_session and
              Process.clock_gettime(Process::CLOCK_REALTIME) < @ssl_session.time.to_f + @ssl_session.timeout
            s.session = @ssl_session if @ssl_session
          end
          if timeout = @open_timeout
            while true
              raise Net::OpenTimeout if timeout <= 0
              start = Process.clock_gettime Process::CLOCK_MONOTONIC
              # to_io is required because SSLSocket doesn't have wait_readable yet
              case s.connect_nonblock(exception: false)
                when :wait_readable; s.to_io.wait_readable(timeout)
                when :wait_writable; s.to_io.wait_writable(timeout)
                else; break
              end
              timeout -= Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
            end
          else
            s.connect
          end
          if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE
            s.post_connection_check(@address)
          end
            # OpenSSL::SSL::Session somehow works but SSLSocket#session= does nothing with JRuby-OpenSSL
            #@ssl_session = s.session
        rescue => exception
          D "Conn close because of connect error #{exception}"
          @socket.close if @socket and not @socket.closed?
          raise exception
        end
      end
      on_connect
    end
  end
end

puts Mechanize.new.get("https://www.howsmyssl.com/").body

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/34648390-1-n-1-record-splitting-beast-mitigation-not-implemented-in-jruby-is-in-mri?utm_campaign=plugin&utm_content=tracker%2F136995&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F136995&utm_medium=issues&utm_source=github).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant